Dynamic import() 与 静态 import 相比较,有哪些不同

Dynamic import() 有哪些特点

Dynamic import() 已被 Chrome 63 和 Safari Technology Preview 24 支持。

Dynamic import() 采用 类函数 的方法来塑造 import,相比 static import 解锁了新功能。这篇文章对比了两者并概览新功能。

Static import(概括)

九月份,Chrome 61 发布并支持在 modules 中使用 ES2015 import 声明。

仔细看下面这个模块,位于 ./utils.mjs:

// Default export
export default () => {
  console.log('Hi from the default export!');
};

// Named export `doStuff`
export const doStuff = () => {
  console.log('Doing stuff…');
};

下面是使用 静态 import 引入 ./utils.mjs 模块:


注意: 上面这个例子使用 .mjs 来标识这是一个模块文件而不是普通脚本。在网页端,文件扩展名并不是问题,只要服务端设置了正确的 MIME 类型(比如给 javascript 文件设置 Content-Type:text/javascript)在 HTTP header。.mjs 在其他一些平台上特别有用,如 Node.js 这类没有 MIME 类型或其他 Hooks 如 type=”module” 来确定模块或普通脚本。我们在这里使用相同的扩展名来保持跨平台的一致性,并清楚地区分模块和普通脚本。

这个导入模块的语法形式是 静态 声明:它只接受字符串作为模块标识符,并通过运行前的 “linking” 过程将模块绑定到本地作用域。静态 import 语法只能用于文件顶部。静态import 支持一些重要的用例,如:static analysis, bundling tools, 和 tree-shaking

在一些案例中,下面这些特性会非常有用:

  • 请求时导入模块(或有条件地)
  • 运行时计算模块标识符
  • 在普通脚本中导入模块(而不是在模块中导入)

但是这些用 静态 import 都无法做到。

Dynamic import() 🔥

Dynamic import() 采用 类函数 的方法来塑造满足这些用例的 importimport(moduleSpecifier) 为请求模块的模块名称空间返回一个 promise。它是在获取,实例化和评估模块的所有依赖关系之后创建的,模块本身也是。

下面是如何使用 动态 import,并使用 ./utils.mjs 模块:


注意: 尽管 import() 看起来像一个函数调用,但它只是恰好被规定为使用括号的一种 语法 (类似于 super())。这意味着 import 不会继承 Function.prototype ,所以不能使用 callapply。像 const importAlias = import 这样的代码也不能运行 —— import 甚至不是一个 object 对象!但是这在实践中并不重要。

下面是一个例子,展示了如何在一个小型单页应用的导航上使用 动态 import() 启用懒加载模块:


<meta charset="utf-8">
<title>My librarytitle>
<nav>
  <a href="books.html" data-entry-module="books">Booksa>
  <a href="movies.html" data-entry-module="movies">Moviesa>
  <a href="video-games.html" data-entry-module="video-games">Video Gamesa>
nav>
<main>This is a placeholder for the content that will be loaded on-demand.main>
<script>
  const main = document.querySelector('main');
  const links = document.querySelectorAll('nav > a');
  for (const link of links) {
    link.addEventListener('click', async (event) => {
      event.preventDefault();
      try {
        const module = await import(`/${link.dataset.entryModule}.mjs`);
        // The module exports a function named `loadPageInto`.
        module.loadPageInto(main);
      } catch (error) {
        main.textContent = error.message;
      }
    });
  }
script>

当正确使用 动态 import() 开启懒加载功能时将会非常强大。为了演示目的,Addy 修改了一个 Hacker News PWA 示例,在首次加载时静态地导入所有依赖,包括评论。升级版 使用 动态 import()延迟加载评论,避免加载,解析和编译成本,直到用户确实需要它们。

建议

静态 import 和动态 import() 都很有用。它们都有各自的特点和使用场景。使用静态 import 来初始绘制依赖关系,尤其是首屏内容。另一种情况,考虑到按需加载则使用动态 import()

译者注: static import 是没有括号的,dynamic import() 是带括号的。不注意的可能会混淆。用法的区别:

  • static import: import $ from 'jquery' 有声明提升,一般只放在头部位置
  • dynamic import(): const $ = import('jquery') 可以放在任何位置
0%