トラブルシューティング
もし行き詰まってしまった場合は、Rollup Discord で問題を議論するか、Stackoverflow に質問を投稿してください。もしバグを見つけたり、Rollup があなたのニーズを満たせない場合は、問題を提起してみてください。最後に、Twitter で @RollupJS に連絡することもできます。
eval
の回避
おそらくあなたはすでに「eval
は悪」だと知っているでしょう。少なくとも一部の人々にとっては。しかし、Rollup では特に有害です。なぜなら、Rollup の動作方法が他のモジュールバンドラーとは異なるからです。他のモジュールバンドラーは各モジュールを関数でラップするのに対し、Rollup はすべてのコードを同じスコープに配置します。
これはより効率的ですが、eval
を使用すると共有スコープが「汚染」されることを意味します。一方、他のバンドラーでは、eval
を使用しなかったモジュールは汚染されません。汚染されたコードでは、評価されるコードがそれらの変数名を参照しないことを保証できないため、ミニファイアは変数名をマングルすることができません。
さらに、悪意のあるモジュールが eval('SUPER_SEKRIT')
を使用して別のモジュールのプライベート変数にアクセスできるという点で、セキュリティ上のリスクをもたらします。
幸いなことに、評価されたコードがローカル変数にアクセスすることを本当に意図しない限り(その場合は、おそらく何か間違ったことをしているでしょう)、次の 2 つの方法のいずれかで同じ効果を得ることができます。
eval2 = eval
eval
を単純に「コピー」することで、まったく同じことを行う関数が提供されますが、それはローカルスコープではなくグローバルスコープで実行されます。
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
を使用するよりもはるかに高速です。
ツリーシェイキングが機能していないように見える
バンドルに、あるべきではないと思われるコードが含まれてしまうことがあります。たとえば、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 が undefined です"
JavaScript モジュールでは、トップレベル(つまり、関数の外側)で this
は undefined
です。そのため、Rollup は、モジュールがネイティブにサポートされたときに発生する動作と一致するように、すべての this
参照を undefined
に書き換えます。
this
が他の意味を持つ正当な理由が時々あります。バンドルでエラーが発生している場合は、options.context
および options.moduleContext
を使用してこの動作を変更できます。
警告: "ソースマップが正しくない可能性があります"
バンドルでソースマップを生成する場合 (sourcemap: true
または sourcemap: 'inline'
) に、変換のソースマップを生成せずにコードを変換する 1 つ以上のプラグインを使用すると、この警告が表示されます。
通常、プラグインは (バンドルではなく) プラグインが sourcemap: false
で構成されている場合にのみソースマップを省略するため、必要なのはそれを変更することだけです。プラグインがソースマップを生成しない場合は、プラグインの作者に問題を提起することを検討してください。
警告: "[module] を外部依存関係として扱います"
Rollup は、デフォルトで相対モジュール ID のみを解決します。これは、次のようなインポートステートメントが…
import moment from 'moment';
…moment
がバンドルに含まれないことを意味します。代わりに、ランタイム時に必要な外部依存関係になります。それが望ましい場合は、external
オプションを使用してこの警告を抑制できます。これにより、意図が明確になります。
// rollup.config.js
export default {
entry: 'src/index.js',
dest: 'bundle.js',
format: 'cjs',
external: ['moment'] // <-- suppresses the warning
};
バンドルにモジュールを含める場合は、Rollup にモジュールの検索方法を指示する必要があります。ほとんどの場合、これは @rollup/plugin-node-resolve を使用する問題です。
events
や util
などの一部のモジュールは、Node.js に組み込まれています。それらを含める場合(たとえば、バンドルがブラウザで実行できるようにするため)、rollup-plugin-polyfill-node を含める必要がある場合があります。
エラー: "EMFILE: too many open files"
大規模なプロジェクトでは、macOS で Rollup を watch モードで実行すると、EMFILE エラーが発生する可能性があります。これが発生した場合は、FSEvents を無効にすると問題が解消される可能性があります。
// rollup.config.js
export default {
...,
watch: {
chokidar: {
useFsEvents: false
}
}
};
エラー: JavaScript ヒープメモリ不足
Rollup は、ツリーシェイキングのために関連する副作用を分析できるように、すべてのモジュール情報をメモリに同時に保持する必要があるため、大規模なプロジェクトをバンドルすると Node のメモリ制限に達する可能性があります。これが起こった場合、次の方法で Rollup を実行してこの制限を増やすのに役立ちます。
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 モジュールを使用する際の注意点も参照してください。