import()提供了动态加载 ECMAScript 模块的功能

Posted 好程序员

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了import()提供了动态加载 ECMAScript 模块的功能相关的知识,希望对你有一定的参考价值。

Domenic Denicola 向 ECMAScript 提议在第 3 阶段中加入“”。它提供了动态加载 ECMAScript 模块的功能。这篇博文会解释这个功能。

ECMAScript 模块是静态的

ECMAScript 模块是完全静态的:你必须在编译期指定要导入或者导出什么,不能在运行时根据当时的情况修改。这样做会带来一些好处,你可以在  中阅读到相关内容。

静态结构的导入有两种语法。看看下面的示例:

    import * as someModule from './dir/someModule.js';

首先,这个导入申明必须放在模块的顶层。这就是说你不能在 if 语句或者事件处理函数中导入模块。

第二,模块说明符'./dir/someModule.js' 是固定的;你不能在运行时候把它计算出来(比如通过函数调用之类的)。

提议引入动态导入模块的功能

关于动态加载模块提议的运算符像下面的代码那样工作:

    const moduleSpecifier = './dir/someModule.js';
   import(moduleSpecifier)
   .then(someModule => someModule.foo());

这个运算符用起来像个函数:

  • 它的参数是一个与 import 申明的模块说明符格式一样字符串。不同的是,这个参数可以通过一个结果为字符串的表达式来提供。

  • 这个“函数调用”返回一个 Promise。模块加载完成,则 Promise 完成。

尽管它很像一个函数,import() 是一个运算符:为了能确定想对于当前模块的模块说明符,它需要知道是从哪个模块调用的。普通的函数可没有办法直接找到。

应用场景

按需加载

在 Web 应用刚启动的时候,有些功能不是必须的,它们可以根据后后面的需求来加载。import()对此很有帮助,因为它可以帮你为模块提供这样的能力。比如:

    button.addEventListener('click', event => {
       import('./dialogBox.js')
       .then(dialogBox => {
           dialogBox.open();
       })
       .catch(error => {
           /* Error handling */
       })
   });

按条件加载模块

有时候你可能想根据某些条件来加载模块。比如,在旧平台上加载 polyfill。代码会像下面这样。

    if (isLegacyPlatform()) {
       import(···)
       .then(···);
   }

计算模块描述符

比如在应用需要国际化的时候,它可以帮助你动态计算模块描述符:

    import(`messages_${getLocale()}.js`)
   .then(···);

提示

通过解构访问导出

解构对于访问模块的导出的很用:

    import('./myModule.js')
   .then(({export1, export2}) => {
       ···    });

访问默认导出

对于默认导出,你需要知道 default 是一个关键字。把它作为一个属性,使用点号就可以访问:

    import('./myModule.js')
   .then(myModule => {
       console.log(myModule.default);
   });

但是你不能把它当作变量名来用:

    import('./myModule.js')
   .then(({default: theDefault}) => {
       console.log(theDefault);
   });

动态加载多个模块

可以通过 Promise.all() 来一次性加载多个模块:

    Promise.all([
       import('./module1.js'),
       import('./module2.js'),
       import('./module3.js'),
   ])
   .then(([module1, module2, module3]) => {
       ···    });

异步函数和 import()

import() 返回 Promise,这意味着你可以通过 (这是 ECMAScript 2017 的内容) 来使用它,让语法更漂亮:

    async function main() {
       const myModule = await import('./myModule.js');

       const {export1, export2} = await import('./myModule.js');

       const [module1, module2, module3] =
           await Promise.all([
               import('./module1.js'),
               import('./module2.js'),
               import('./module3.js'),
           ]);
   }
   main();

在模块或者脚本的顶层,你会发现使用立即执行的箭头函数非常有用:

    (async () => {
       const myModule = await import('./myModule.js');
   })();

支持 import()

  • Node.js: Guy Bedford 的  提供了一个 Node.js 的可执行程序来支持 ES6 语法和 import()

  • webpack v1:  是一个将 import() 转译为require.ensure() 的 Babel 插件。

  • webpack v2 ( 或更新版本):




长按二维码分享更多精彩

以上是关于import()提供了动态加载 ECMAScript 模块的功能的主要内容,如果未能解决你的问题,请参考以下文章

Python内置函数 __import__ 动态加载模块

ts 动态加载import()

ts 动态加载import()

vue加载组件报错说提前加载

React 路由动态加载

有没有办法将动态加载的图像文件合并到一个图像文件中?