Skip to content

故障排除

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

¥If you get stuck, please try discussing the issue on the Rollup Discord or posting a question to Stackoverflow. If you've found a bug, or Rollup can't meet your needs, please try raising an issue. Lastly, you may try contacting @RollupJS on Twitter.

避免 eval

¥Avoiding eval

你可能已经知道“eval 是邪恶的”,至少有些人是这么认为的。但它对于 Rollup 来说尤其有害,因为它的工作方式 - 与其他将每个模块封装在一个函数中的模块打包器不同,Rollup 将所有代码放在同一范围内。

¥You probably already know that 'eval is evil', at least according to some people. But it's particularly harmful with Rollup, because of how it works – unlike other module bundlers, which wrap each module in a function, Rollup puts all your code in the same scope.

这更有效,但这意味着每当你使用 eval 时,共享作用域都是 'polluted',而使用不同的打包器时,不使用 eval 的模块不会被污染。压缩器无法破坏受污染代码中的变量名称,因为它无法保证要评估的代码不会引用这些变量名称。

¥That's more efficient, but it means that the shared scope is 'polluted' whenever you use eval, whereas with a different bundler, modules that didn't use eval would not be polluted. A minifier can't mangle variable names in polluted code, because it can't guarantee that the code to be evaluated doesn't reference those variable names.

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

¥Furthermore, it poses a security risk in that a malicious module could access another module's private variables with eval('SUPER_SEKRIT').

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

¥Luckily, unless you really do intend for the evaluated code to have access to local variables (in which case you're probably doing something wrong!), you can achieve the same effect in one of two ways:

eval2 = eval

Simply 'copying' eval 为你提供了一个执行完全相同操作的函数,但它在全局作用域而不是本地作用域内运行:

¥Simply 'copying' eval provides you with a function that does exactly the same thing, but which runs in the global scope rather than the local one:

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

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

¥Using the Function constructor generates a function from the supplied string. Again, it runs in the global scope. If you need to call the function repeatedly, this is much, much faster than using eval.

摇树优化似乎不起作用

¥Tree-shaking doesn't seem to be working

有时,你最终会在包中得到看起来不应该存在的代码。例如,如果你从 lodash-es 导入实用程序,你可能希望获得该实用程序运行所需的最少代码。

¥Sometimes, you'll end up with code in your bundle that doesn't seem like it should be there. For example, if you import a utility from lodash-es, you might expect that you'll get the bare minimum of code necessary for that utility to work.

但 Rollup 必须对其删除的代码保持保守,以保证最终结果正确运行。如果导入的模块似乎对你正在使用的模块的位或全局环境有副作用,Rollup 会谨慎行事并包含这些副作用。

¥But Rollup has to be conservative about what code it removes in order to guarantee that the end result will run correctly. If an imported module appears to have side effects, either on bits of the module that you're using or on the global environment, Rollup plays it safe and includes those side effects.

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

¥Because static analysis in a dynamic language like JavaScript is hard, there will occasionally be false positives. Lodash is a good example of a module that looks like it has lots of side effects, even in places that it doesn't. You can often mitigate those false positives by importing submodules (e.g. import map from 'lodash-es/map' rather than import { map } from 'lodash-es').

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

¥Rollup's static analysis will improve over time, but it will never be perfect in all cases – that's just JavaScript.

错误:"[名称] 未由 [模块] 导出"

¥Error: "[name] is not exported by [module]"

有时你会看到如下错误消息:

¥Occasionally you will see an error message like this:

'foo' 不是由 bar.js 导出的(由 baz.js 导入的)

¥'foo' is not exported by bar.js (imported by baz.js)

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

¥Import declarations must have corresponding export declarations in the imported module. For example, if you have import a from './a.js' in a module, and a.js doesn't have an export default declaration, or import {foo} from './b.js', and b.js doesn't export foo, Rollup cannot bundle the code.

rollup-plugin-commonjs 转换的 CommonJS 模块经常出现此错误,该包已被弃用并且不再维护。请使用 @rollup/plugin-commonjs

¥This error frequently occurs with CommonJS modules converted by rollup-plugin-commonjs, this package has been deprecated and is no longer maintained. Please use @rollup/plugin-commonjs.

错误:"这是未定义的"

¥Error: "this is undefined"

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

¥In a JavaScript module, this is undefined at the top level (i.e., outside functions). Because of that, Rollup will rewrite any this references to undefined so that the resulting behaviour matches what will happen when modules are natively supported.

偶尔有一些正当理由让 this 具有其他含义。如果你的打包包中出现错误,你可以使用 options.contextoptions.moduleContext 来更改此行为。

¥There are occasional valid reasons for this to mean something else. If you're getting errors in your bundle, you can use options.context and options.moduleContext to change this behaviour.

警告:"Sourcemap 可能不正确"

¥Warning: "Sourcemap is likely to be incorrect"

如果你使用打包包(sourcemap: truesourcemap: 'inline')生成源映射,但你使用一个或多个转换代码的插件而不生成用于转换的源映射,你将看到此警告。

¥You'll see this warning if you generate a sourcemap with your bundle (sourcemap: true or sourcemap: 'inline') but you're using one or more plugins that transformed code without generating a sourcemap for the transformation.

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

¥Usually, a plugin will only omit the sourcemap if it (the plugin, not the bundle) was configured with sourcemap: false – so all you need to do is change that. If the plugin doesn't generate a sourcemap, consider raising an issue with the plugin author.

警告:"将 [模块] 视为外部依赖"

¥Warning: "Treating [module] as external dependency"

默认情况下,Rollup 将仅解析相对模块 ID。这意味着像这样的 import 语句......

¥Rollup will only resolve relative module IDs by default. This means that an import statement like this…

js
import moment from 'moment';

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

¥…won't result in moment being included in your bundle – instead, it will be an external dependency that is required at runtime. If that's what you want, you can suppress this warning with the external option, which makes your intentions explicit:

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 的问题。

¥If you do want to include the module in your bundle, you need to tell Rollup how to find it. In most cases, this is a question of using @rollup/plugin-node-resolve.

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

¥Some modules, like events or util, are built in to Node.js. If you want to include those (for example, so that your bundle runs in the browser), you may need to include rollup-plugin-polyfill-node.

错误:"EMFILE:打开的文件太多”

¥Error: "EMFILE: too many open files"

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

¥For large projects, you may run into an EMFILE error when running Rollup in watch mode on macOS. If you experience this, disabling FSEvents may eliminate the problem:

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

错误:JavaScript 堆内存不足

¥Error: JavaScript heap out of memory

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

¥As Rollup needs to keep all module information in memory simultaneously to be able to analyze relevant side effects for tree-shaking, it is possible that bundling large projects reaches Node's memory limit. If this happens, it can help to increase this limit by running Rollup via

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

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

¥increasing --max-old-space-size as needed. Note that this number can safely surpass your available physical memory. In that case, Node will start paging memory to disk as needed.

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

¥You may reduce memory pressure by introducing code splitting by using dynamic imports, importing just specific modules rather than whole dependencies, disabling sourcemaps, or increasing the size of your swap space.

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

¥Error: Node tried to load your configuration file as CommonJS even though it is likely an ES module

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

¥By default, Rollup will use Node's native module mechanism to load your Rollup configuration. That means if you use ES imports and exports in your configuration, you either need to define "type": "module" in your package.json file or use the .mjs extension for your configuration. See also Configuration Files and Caveats when using native Node ES modules for more information.