我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

以前曾经说过,在node程序中引入第三方模块的方式,有两种。一种是commonjs,使用require语句。另外一种是es module,使用import语句。早期的node代码,以require语句居多。目前的趋势是:抛弃require语句,使用import语句。那么,问题就来了:一些代码库只支持最新的import的方式引入代码(目前很常见)。

苏南大叔:node程序commonjs模式下,如何使用动态import语句? - node动态导入模块
node程序commonjs模式下,如何使用动态import语句?(图6-1)

苏南大叔的程序如此灵动博客,记录苏南大叔和计算机代码的故事。本文记录在commonjs环境中,使用import语句的方式(本来是应该使用require的)。本文测试环境:node@16.14.2nanoid@4.0.0。本文的龙套项目是nanoid,目前最新的版本中,已经不支持早期的require方式,可以使用npm i nanoid来进行安装。

requireimport

回顾文章:https://newsn.net/say/node-run-es6.html

  • 通常来说使用node xxx.js来执行的代码,就是commonjs标准的。使用require("xxx")来导入第三方模块。
  • 而使用node xxx.mjs来执行的代码,或者package.json里面定义了type:module,或者各种编译类型(例如webpack)的,就都是属于es module类型(或者称之为es模块)。使用import("xxx")来导入第三方模块。

报错信息

由于目前越来越多的第三方模块,不再支持commonjs。所以,在使用传统的require语句的时候,就会报错。那么,代码提示可以使用dynamic import。提示信息如下:

require() of ES Module C:\Users\sunan\Desktop\demo\node_modules\nanoid\index.js from C:\Users\sunan\Desktop\demo\test.js not supported.
Instead change the require of index.js in C:\Users\sunan\Desktop\demo\test.js to a dynamic import() which is available in all CommonJS modules.

关键信息:

dynamic import() which is available in all CommonJS modules.

苏南大叔:node程序commonjs模式下,如何使用动态import语句? - 代码报错一
node程序commonjs模式下,如何使用动态import语句?(图6-2)

试图在es module里面使用require()字样,也是会报错的。

ReferenceError: require is not defined in ES module scope, you can use import instead

苏南大叔:node程序commonjs模式下,如何使用动态import语句? - 代码报错二
node程序commonjs模式下,如何使用动态import语句?(图6-3)

解决方案一:await【推荐】

普通的commonjs环境下,对比如下:

const { nanoid } = require('nanoid')

vs

const { nanoid } = await import('nanoid');

也就是require('xxx')字样变成了await import('xxx')字样。但是,由于使用了await,大多数情况下,还需要一个async包裹一下对应的语句。

(async ()=>{
    const { nanoid } = await import('nanoid');
    console.log(nanoid(5));
})();

苏南大叔:node程序commonjs模式下,如何使用动态import语句? - 动态导入
node程序commonjs模式下,如何使用动态import语句?(图6-4)

es module里面,使用await import的时候,是不需要async字样的。

苏南大叔:node程序commonjs模式下,如何使用动态import语句? - es-module-动态导入
node程序commonjs模式下,如何使用动态import语句?(图6-5)

解决方案二:eval

也可以使用eval("import('xxx')")的方式。但是本例的测试中,依然需要使用await,所以没有啥特别的意义。

(async () => {
    const { nanoid } = await eval("import('nanoid')");
    console.log(nanoid(5));
})();

或者

(async () => {
    const { nanoid } = await eval(import('nanoid'));
    console.log(nanoid(5));
})();

苏南大叔:node程序commonjs模式下,如何使用动态import语句? - 动态导入2
node程序commonjs模式下,如何使用动态import语句?(图6-6)

结束语

好像在任何的编程语言里面,都存在着明显的两个对立门派。另外说一句,似乎require导入比import导入自由的多,import强制要把所有的导入语句写到顶部,而commonjs里面并没有这样的要求。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   node