跳至内容

疑难解答

如果您遇到问题,请尝试在 Rollup Discord 上讨论该问题,或在 Stackoverflow 上发布问题。如果您发现错误,或者 Rollup 无法满足您的需求,请尝试 提出问题。最后,您可以尝试在 Twitter 上联系 @RollupJS

避免使用 eval

您可能已经知道 'eval 很邪恶',至少有些人是这么认为的。但它对 Rollup 来说尤其有害,因为它的工作原理 - 与其他模块捆绑器不同,其他模块捆绑器将每个模块包装在一个函数中,而 Rollup 将所有代码放在同一个作用域中。

这更有效率,但意味着每次使用 eval 时,共享作用域都会被 '污染',而使用不同的捆绑器,未使用 eval 的模块不会被污染。混淆器无法混淆污染代码中的变量名,因为它无法保证要评估的代码不会引用这些变量名。

此外,它存在安全风险,因为恶意模块可以使用 eval('SUPER_SEKRIT') 访问另一个模块的私有变量。

幸运的是,除非您确实打算让评估的代码访问局部变量(在这种情况下,您可能做错了什么!),否则您可以通过以下两种方式之一实现相同的效果

eval2 = eval

简单地 '复制' eval 为您提供了一个执行完全相同操作的函数,但它在全局作用域中运行,而不是在局部作用域中运行

js
var eval2 = eval;

(function () {
	var foo = 42;
	eval('console.log("with eval:",foo)'); // logs 'with eval: 42'
	eval2('console.log("with eval2:",foo)'); // throws ReferenceError
})();

new Function

使用 Function 构造函数 从提供的字符串生成一个函数。同样,它在全局作用域中运行。如果您需要重复调用该函数,这比使用 eval 快得多。

Tree-shaking 似乎不起作用

有时,您最终会在捆绑包中得到一些似乎不应该存在的代码。例如,如果您从 lodash-es 导入一个实用程序,您可能希望获得该实用程序正常工作所需的最小代码量。

但是 Rollup 必须对它删除的代码保持谨慎,以确保最终结果能够正确运行。如果导入的模块似乎具有副作用,无论是对您正在使用的模块部分还是对全局环境,Rollup 都会谨慎行事并包含这些副作用。

由于像 JavaScript 这样的动态语言中的静态分析很困难,因此偶尔会出现误报。Lodash 是一个很好的例子,它看起来有很多副作用,即使在它没有的地方也是如此。您通常可以通过导入子模块来缓解这些误报(例如,import map from 'lodash-es/map' 而不是 import { map } from 'lodash-es')。

Rollup 的静态分析会随着时间的推移而改进,但它永远不会在所有情况下都完美 - 这就是 JavaScript 的本质。

错误: "[name] 未由 [module] 导出"

有时您会看到这样的错误消息

'foo' 未由 bar.js 导出(由 baz.js 导入)

导入声明必须在导入的模块中具有相应的导出声明。例如,如果您在模块中具有 import a from './a.js',并且 a.js 没有 export default 声明,或者 import {foo} from './b.js',并且 b.js 没有导出 foo,则 Rollup 无法捆绑代码。

此错误经常发生在由 rollup-plugin-commonjs 转换的 CommonJS 模块中,此包已弃用,不再维护。请使用 @rollup/plugin-commonjs

错误: "this 未定义"

在 JavaScript 模块中,this 在顶层(即函数外部)为 undefined。因此,Rollup 会将任何 this 引用重写为 undefined,以便最终行为与模块获得原生支持时发生的行为相匹配。

this 有时有其他含义的有效原因。如果您在捆绑包中遇到错误,您可以使用 options.contextoptions.moduleContext 来更改此行为。

警告: "源映射可能不正确"

如果您使用捆绑包生成源映射(sourcemap: truesourcemap: 'inline'),但您使用了一个或多个插件来转换代码而没有为转换生成源映射,您将看到此警告。

通常,插件只会省略源映射,如果它(插件,而不是捆绑包)配置了 sourcemap: false - 所以您需要做的就是更改它。如果插件没有生成源映射,请考虑向插件作者提出问题。

警告: "将 [module] 视为外部依赖项"

Rollup 默认情况下只会解析相对模块 ID。这意味着像这样的导入语句…

js
import moment from 'moment';

…不会导致 moment 包含在您的捆绑包中 - 相反,它将是一个在运行时所需的外部依赖项。如果这就是您想要的,您可以使用 external 选项来抑制此警告,这会明确您的意图

js
// rollup.config.js
export default {
	entry: 'src/index.js',
	dest: 'bundle.js',
	format: 'cjs',
	external: ['moment'] // <-- suppresses the warning
};

如果您确实想将模块包含在捆绑包中,您需要告诉 Rollup 如何找到它。在大多数情况下,这是一个使用 @rollup/plugin-node-resolve 的问题。

一些模块,如 eventsutil,是内置在 Node.js 中的。如果您想包含这些模块(例如,以便您的捆绑包在浏览器中运行),您可能需要包含 rollup-plugin-polyfill-node

错误: "EMFILE: 打开的文件过多"

对于大型项目,您可能会在 macOS 上以监视模式运行 Rollup 时遇到 EMFILE 错误。如果您遇到此问题,禁用 FSEvents 可能会消除此问题

js
// rollup.config.js
export default {
  ...,
  watch: {
    chokidar: {
      useFsEvents: false
    }
  }
};

错误: JavaScript 堆内存不足

由于 Rollup 需要同时将所有模块信息保存在内存中,以便能够分析与 tree-shaking 相关的副作用,因此捆绑大型项目可能会达到 Node 的内存限制。如果发生这种情况,通过以下方式运行 Rollup 可以帮助增加此限制

shell
node --max-old-space-size=8192 node_modules/rollup/dist/bin/rollup -c

根据需要增加 --max-old-space-size。请注意,此数字可以安全地超过您的可用物理内存。在这种情况下,Node 将根据需要开始将内存分页到磁盘。

您可以通过使用动态导入引入代码拆分、仅导入特定模块而不是整个依赖项、禁用源映射或增加交换空间的大小来减少内存压力。

错误: Node 尝试将您的配置文件加载为 CommonJS,即使它很可能是 ES 模块

默认情况下,Rollup 将使用 Node 的原生模块机制来加载您的 Rollup 配置。这意味着如果您在配置中使用 ES 导入和导出,您需要在 package.json 文件中定义 "type": "module",或者为您的配置使用 .mjs 扩展名。有关更多信息,另请参见 配置文件使用原生 Node ES 模块时的注意事项

根据 MIT 许可证发布。