Rollup を使って JS をビルドしていたのですが CommonJS 形式の require
が解決されずそのまま出力されてしまう問題にハマったのでメモ
環境
- rollup
v2.77.2
- @rollup/plugin-node-resolve
v13.3.0
- @rollup/plugin-commonjs
v22.0.1
rollup.config.js
import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; const config = { input: './src/main.js', output: { file: './build/bundle.js', format: 'esm' }, plugins: [nodeResolve(), commonjs(),] }; export default config;
🙆 CommonJS (require
) のみの場合は OK
sub.cjs.js
exports.sub = (x, y) => { return x - y; };
main.js
const { sub } = require('./sub.cjs'); const x = sub(10, 5); console.log(x);
👇 ビルド npx rollup -c
/build/bundle.js
var main = {}; var sub_cjs = {}; const sub$1 = (x, y) => { return x - y; }; sub_cjs.sub = sub$1; const { sub } = sub_cjs; const x = sub(10, 5); console.log(x); export { main as default };
🙅 ESM (import
) と CommonJS (require
) が混在すると NG
sum.js
export const sum = (x, y) => { return x + y; };
main.js
import { sum } from './sum'; const { sub } = require('./sub.cjs.js'); const a = sum(1, 2); console.log(a); const b = sub(10, 5); console.log(b);
👇 ビルド npx rollup -c
/build/bundle.js
const sum = (x, y) => { return x + y; }; const { sub } = require('./sub.cjs.js'); const a = sum(1, 2); console.log(a); const b = sub(10, 5); console.log(b);
require
文がそのまま残ってしまう
main.js
で import より先に const { sub } = require('./sub.cjs.js');
を書いても同様
import
と require
が混在する場合は transformMixedEsModules
オプションを true
にする必要がある
transformMixedEsModules
Type:boolean
Default:false
Instructs the plugin whether to enable mixed module transformations. This is useful in scenarios with modules that contain a mix of ES
import
statements and CommonJSrequire
expressions. Set totrue
ifrequire
calls should be transformed to imports in mixed modules, orfalse
if therequire
expressions should survive the transformation. The latter can be important if the code contains environment detection, or you are coding for an environment with special treatment forrequire
calls such as ElectronJS. See also the "ignore" option.
cf. https://github.com/rollup/plugins/tree/master/packages/commonjs#transformmixedesmodules
rollup.config.js
を修正する
import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; const config = { input: './src/index.js', output: { file: './build/dist.js', format: 'iife', }, - plugin: [commonjs(), nodeResolve()], + plugins: [ + nodeResolve(), + commonjs({ + transformMixedEsModules: true, + }), + ], };
main.js
import { sum } from './sum'; const { sub } = require('./sub.cjs.js'); const a = sum(1, 2); console.log(a); const b = sub(10, 5); console.log(b);
👇 ビルド npx rollup -c
/build/bundle.js
var sub_cjs = {}; const sub$1 = (x, y) => { return x - y; }; sub_cjs.sub = sub$1; const sum = (x, y) => { return x + y; }; const { sub } = sub_cjs; const a = sum(1, 2); console.log(a); const b = sub(10, 5); console.log(b);
npm パッケージを require
で読み込んでも大丈夫っぽい
懐かしの jQuery を npm でインストールしたものを使ってみる
cf. jquery - npm
& npm i jquery
パッケージの中を見てみると export とかがされている訳ではなく return jQuery
の様になっていた
import $ from "jquery";
も使えるようだけど敢えて const $ = require( "jquery" );
で読み込ませる
main.js
const $ = require('jquery'); import { sum } from './sum'; const { sub } = require('./sub.cjs.js'); const a = sum(1, 2); console.log(a); const b = sub(10, 5); console.log(b); $(() => { const btn = $('.btn'); btn.on('click', () => { console.log('clicked!'); }); });
👉 ビルド npx rollup -c
ビルドされた JS を簡易な HTML で読み込ませて <button class="btn">
がクリックされた時にコンソールに clicked!
が出力されることを確認できれば恐らくOK!
所管
最初 require
がバンドルされずにハマっていたのですが明示的にオプションを指定してあげなければならないだけでした。ドキュメント…ちゃんと読もう… (いつものこと)
おわり
[参考]
(神クズ☆アイドル おもしろい)