概要
そうだよ。
さて、最近は CommonJS と ES Modules も研究したんで……
- (2023-07-11)誰だよ CommonJS には2通りのエクスポートがあるっつった奴
- (2023-07-15)俺ァ古い Pythonista だからョ、 ES Modules の解説も Python にたとえてくれねェと
……次はそれを、各実行環境で使いやすいようバンドル化する webpack の話をしようぜ。
JavaScript は歴史上、 "モジュールシステムを使いてーけどモジュールで分割されてるとブラウザ側で使えねー" という問題を乗り越えるため、 webpack というスゴツールを2012年に生み出している。これは "モジュールシステムで分割されたコードをくっつける (バンドル化する) ことでブラウザが使えるようにする" ってやつだ。ついでに ES2015 -> ES5 のトランスパイルとか、 TypeScript のトランスパイルとか、 tree shaking とか minification 機能も持っているのでホンマモンのスゴツールだ。今回はそいつの威力を見ようぜ。
CommonJS を webpack でバンドルにしよっか
まずは CommonJS をそのまま実行しよっか
// index.js だよ。 require を使っているから CommonJS だ。
const dayjs = require('dayjs');
const today = dayjs();
console.log('Today:', today.format('YYYY-MM-DD'));
const tomorrow = today.add(1, 'day');
console.log('Tomorrow:', tomorrow.format('YYYY-MM-DD'));
# npm project を用意。
yarn init -y
# dayjs をインストール。
yarn add dayjs
node -v
# v20.3.0
# Node.js は普通に CommonJS を実行できる。
node index.js
# Today: 2023-07-05
# Tomorrow: 2023-07-06
<!--
ブラウザ側で index.js を実行する index.html
ブラウザで index.js を実行すると
Uncaught ReferenceError: require is not defined
を確認できる。
-->
<script src="node_modules/dayjs/dayjs.min.js"></script>
<script src="index.js"></script>
CommonJS を webpack でバンドルしよっか
// Node.js で実行できるバンドルを作るための webpack 設定。
// webpack.config-for-node.js
module.exports = {
target: 'node',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
output: {
filename: 'main-for-node.js',
libraryTarget: 'commonjs2'
}
};
// ブラウザで実行できるバンドルを作るための webpack 設定。
// webpack.config-for-browser.js
module.exports = {
target: 'web',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
output: {
filename: 'main-for-browser.js',
libraryTarget: 'umd'
}
};
# webpack をインストール。
yarn add --dev webpack webpack-cli babel-loader @babel/core
# Node.js のためのバンドル化する!
# production mode を使うとファイルサイズが小さくなる。
yarn webpack --mode development --entry ./index.js --config ./webpack.config-for-node.js
# Node.js では相変わらず普通に実行できる。
node ./dist/main-for-node.js
# Today: 2023-07-05
# Tomorrow: 2023-07-06
# ブラウザのためのバンドル化する!
yarn webpack --mode development --entry ./index.js --config ./webpack.config-for-browser.js
<!--
ブラウザでバンドルを実行する index-with-webpack.html
ブラウザでバンドルを実行すると
Today: 2023-07-05
Tomorrow: 2023-07-06
を確認できる。
-->
<script src="dist/main-for-browser.js"></script>
ES Modules を webpack でバンドルにしよっか
まずは ES Modules をそのまま実行しよっか
// index.mjs だよ。 import を使っているから ES Modules だ。
import dayjs from 'dayjs';
const today = dayjs();
const tomorrow = today.add(1, 'day');
console.log(`Today: ${today.format('YYYY-MM-DD')}`);
console.log(`Tomorrow: ${tomorrow.format('YYYY-MM-DD')}`);
yarn init -y
yarn add dayjs
node -v
# v20.3.0
# Node.js は普通に ES Modules を実行できる。
node index.mjs
# Today: 2023-07-05
# Tomorrow: 2023-07-06
<!--
ブラウザで実行すると
GET http://127.0.../node_modules/dayjs/esm/constant net::ERR_ABORTED 404 (Not Found)
GET http://127.0.../node_modules/dayjs/esm/locale/en 404 (Not Found)
GET http://127.0.../node_modules/dayjs/esm/utils net::ERR_ABORTED 404 (Not Found)
なんかよく分かんないけどうまくいかないことを確認できる。
うまくいくこともあるんだろうけど npm package が関わるとダメなんかな?
-->
<script type="module">
import dayjs from './node_modules/dayjs/esm/index.js';
const today = dayjs();
const tomorrow = today.add(1, 'day');
console.log(`Today: ${today.format('YYYY-MM-DD')}`);
console.log(`Tomorrow: ${tomorrow.format('YYYY-MM-DD')}`);
</script>
ES Modules を webpack でバンドルしよっか
// Node.js で実行できるバンドルを作るための webpack 設定。
// ちょっとこだわって ES Modules 形式にしよう。
// webpack.config-for-node.mjs
export default {
// 中身は CommonJS のほうの設定と同じ。
};
// ブラウザで実行できるバンドルを作るための webpack 設定。
// こだわって ES Modules 形式にしよう。
// webpack.config-for-browser.mjs
export default {
// 中身は CommonJS のほうの設定と同じ。
};
# webpack をインストール。
yarn add --dev webpack webpack-cli babel-loader @babel/core
# Node.js のためのバンドル化する!
# production mode を使うとファイルサイズが小さくなる。
yarn webpack --mode development --entry ./index.mjs --config ./webpack.config-for-node.mjs
# Node.js では相変わらず普通に実行できる。
node ./dist/main-for-node.js
# Today: 2023-07-05
# Tomorrow: 2023-07-06
# ブラウザのためのバンドル化する!
yarn webpack --mode development --entry ./index.mjs --config ./webpack.config-for-browser.mjs
<!--
ブラウザでバンドルを実行する index-with-webpack.html
ブラウザでバンドルを実行すると
Today: 2023-07-05
Tomorrow: 2023-07-06
を確認できる。
-->
<script src="dist/main-for-browser.js"></script>
おしまい
どんなに今風のバージョンの JavaScript を書こうと、どんなモジュールシステムで書こうと、 Node.js でもブラウザでも動かせるようになったぜ! どれだけいかしたスクリプトを書こうと、動かせねーと意味がない。自分で手を動かすことで、 webpack のパワーを実感できたな。