{
"name" : "Satoshi Takeda / 武田 諭",
"social": "tkdn",
"job" : "Front-End web developer",
"history": {
"2003-2013" : "Actor",
"2013-" : "Developer"
}
}
自責の念にかられながら作った
禁忌の webpack plugin たち。
今日は自責を供養しに来ました。
積極的な使用はおすすめしません。
💀 Es3ifyPlugin
💀 DefinePropertyPatchPlugin
💀 AllowMutateEsmExportsPlugin
予約語をプロパティに宣言すると死
foo.default
配列, オブジェクトで末尾カンマすると死
["foo", "bar",]
const es3ify = require("es3-safe-recast").compile;
const ConcatSource = require("webpack-sources/lib/ConcatSource");
module.exports = class Es3ifyPlugin {
apply(compiler) {
compiler.hooks.emit.tap("Es3ifyPlugin", compilation => {
Object.keys(compilation.assets)
.filter(file => /.js$/.test(file))
.forEach(file => {
const asset = compilation.assets[file];
compilation.assets[file] =
new ConcatSource(es3ify(asset.source(), {
trailingComma: true,
}));
});
}
);
}
}
無駄骨に終わった 😇
new TerserPlugin({
terserOptions: {
ie8: true,
},
}),
Uncaught TypeError: Cannot assign to read only property '__esModule' of #<Object>
Android 4.0.x の端末に存在
Object.defineProperty
が壊れてるwebpack が ES modules を
エミュレートするところで
このバグを踏んでいるっぽい。
// webpack bootstrap
Object.defineProperty(exports, '__esModule', { value: true });
// ...なんやかんや
// some modules
exports.__esModule = true; // バグ踏む
const ConcatSource = require("webpack-sources/lib/ConcatSource");
// バンドルしたファイルの冒頭にパッチをくっつけるだけ
const patch = `パッチの内容`;
module.exports = class DefinePropertyPatchPlugin {
apply(compiler) {
compiler.hooks.afterCompile.tap(
"DefinePropertyPatchPlugin",
compilation => {
Object.keys(compilation.assets)
.filter(file => /.js$/.test(file))
.forEach(file => {
const asset = compilation.assets[file];
compilation.assets[file] =
new ConcatSource(patch + asset.source());
});
});
}
}
雑に作ったのでくっつけた
パッチ部分が minify されない
1年前... webpack 2 -> 4 への移行時...
アップデートしたらテストが壊れた。
テストというか、テストダブルの箇所。
// mod.js
export function test() {
return "fail";
}
// entry.js
import sinon from "sinon";
import * as mod from "./mod";
sinon.stub(mod, "test").returns("pass"); // ⬅
// `TypeError: Attempted to wrap undefined property as function`
仕様として exported module は read-only.
webpack が ES modules の仕様に厳格に。
export されたモジュールは書き換えできなくなった 🤔
// ここを
Object.defineProperty(exports, name, {
enumerable: true,
get: getter
});
// こうしたい
Object.defineProperty(exports, name, {
enumerable: true,
configurable: true,
get: getter
});
テストを回すバンドルの時だけ
無理やり書き換え。
module.exports = class AllowMutateEsmExportsPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
"AllowMutateEsmExportsPlugin",
compilation => {
compilation.mainTemplate.hooks.requireExtensions.tap(
"AllowMutateEsmExportsPlugin",
source =>
// 1つ前のスライド参照
source.replace("ここを", "こうしたい")
)
});
}
}