“require(x)”和“await import x”的区别

5
这个问题看起来与“require(x)和import x之间的区别”(链接)相似,但实际上是不同的。
我最近注意到了await import的用法,在Next.js项目中,例如: https://github.com/zeit/next.js/blob/canary/examples/with-apollo/lib/apollo.js#L134
if (ssr && AppTree) {
    // Import `@apollo/react-ssr` dynamically.
    // We don't want to have this in our client bundle.
    const { getDataFromTree } = await import('@apollo/react-ssr')
}

乍一看,我认为使用await import('@apollo/react-ssr')允许在源代码中条件地使用import,而不是在顶层导入@apollo/react-ssr模块。其目标是减少生成的浏览器捆绑包(浏览器将不包含@apollo/react-ssr包)。
到目前为止,我总是使用const reactSSR = require('@apollo/react-ssr')有条件地导入软件包。我想知道两种方法之间有什么区别。
也许使用await import('@apollo/react-ssr')更好,因为它允许树摇?与require相比,使用它的任何“缺点”吗?
2个回答

2

import()语法可以导入ECMAScript模块,而require()不能:

import()语法,通常称为动态导入,是一种类似函数的表达式,允许异步和动态地将一个ECMAScript模块加载到可能是非模块环境中。

ESM / CJS互操作性:

由于CommonJs模块(CJS)是同步加载的,而ECMAScript模块(ESM)是异步加载的

CJS require()函数会加载一段代码并立即执行。

在实际代码执行之前,ESM模块会被递归解析,即变量名会被声明,但函数不会被执行,值也不会被计算和赋值。

另请参阅:

import声明被设计为在语法上严格[...],这使得模块可以在被评估之前进行静态分析和链接

静态[import]更适合加载初始依赖项,并且可以更方便地受益于静态分析工具和树摇动

import()

为了能够从CJS模块加载ESM模块,发明了新的import()语法,它允许在其他同步环境(例如CJS模块)中异步加载ESM模块。

为什么不用require()

ESM模块设计为异步的,无论如何都不能决定同步加载它们使用require()。例如,考虑以下示例(使用.mjs作为ESM模块):

// -- otherModule.mjs --

export default 10 + 20;

// -- module.mjs --

import submodule from './otherModule.mjs';
const container = { submodule: submodule };
export default container;

// -- CJS file --

var mjsModule = require('./module.mjs'); // <-- doesn't work !!
console.log( mjsModule.submodule );      // <-- what is the value of `.submodule` ?

如果您能同步导入module.mjs,那么要么:
  • 所有其他模块也需要同步加载,尽管ESM导入声明import submodule ...,这将导致许多意外行为(当然也会禁用此语法的所有功能),或者
  • module.mjs在CJS文件想要访问它之前,还不知道{ submodule: ??? }的值。

1

使用await import语法而不是标准的静态ESM导入的一个原因是,如果导入的包在某些环境中可能不存在。使用await import语法允许try/catch导入并在抛出异常时动态调整。

例如,Node.js可以在没有Crypto支持的情况下构建。如果环境中的Node.js版本没有使用Crypto支持,则静态导入Crypto功能(import { randomUUID } from 'crypto';)将抛出异常。使用await import语法(const { randomUUID } = await import('node:crypto');)允许捕获和处理异常。


是的,但这并没有真正回答问题。它也没有解释使用import而不是require有什么不同。使用require还允许使用try/catch。 - Vadorequest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接