javascript - Plugin Webpack: Bagaimana cara menambahkan loader ke modul secara dinamis?
Saya sedang menulis sebuah plugin Webpack. Selama resolusi modul, plugin ini harus secara dinamis menambahkan loader tertentu untuk beberapa modul, tetapi tidak untuk semua.
Ide saya saat ini adalah memanfaatkan event after-resolve dari normal-module-factory. Di sana, saya bisa memodifikasi array data.loaders. Beberapa debugging menunjukkan bahwa array ini berisi objek dalam bentuk { loader: string, options: object | undefined }.
Saya tidak dapat menemukan dokumentasi tentang cara memodifikasi pemuat per-modul secara langsung. Jadi saya bertanya-tanya:
- Apakah ini pendekatan yang benar?
- Beberapa (tetapi tidak semua) entri
loadersyang ada mengandung properti tambahanident, yang terlihat seperti ini:'ref--0-0'. Kapan saya harus mengatur properti ini, dan dengan nilai apa?
Jawaban #1
Saya tidak yakin apakah ini solusi terbaik, tetapi kode ini tampaknya bekerja:
class MyPlugin {
apply(compiler) {
compiler.plugin('normal-module-factory', normalModuleFactory => {
normalModuleFactory.plugin('after-resolve', (data, callback) => {
data.loaders.push({
loader: ..., // Path to loader
options: {}
});
callback(null, data);
});
});
}
}
module.exports = MyPlugin;
Mengenai properti tambahan ident: Webpack perlu dapat membandingkan opsi loader. Secara default, ini dilakukan dengan memanggil JSON.stringify() pada objek opsi, lalu membandingkan string yang dihasilkan. Dengan menambahkan properti ident, Anda dapat secara eksplisit menentukan representasi string dari objek opsi tersebut. Untuk detailnya, lihat https://stackoverflow.com/a/49006233/52041.
Jawaban #2
Saya sedang mencoba menyelesaikan masalah serupa, dan ingin menambahkan loader hanya untuk file tertentu yang diidentifikasi di tempat lain dalam sebuah plugin. Solusi saya adalah sebagai berikut:
loader.js
module.exports = function loader(content) {
return mySpecialTransformation(content);
};
plugin.js
const path = require('path');
class MyPluginName {
apply(compiler) {
compiler.hooks.compilation.tap('MyPluginName', compilation => {
compilation.hooks.normalModuleLoader.tap('MyPluginName', (loaderContext, module) => {
if (myModuleCondition(module)) {
module.loaders.unshift({
loader: path.resolve(__dirname, 'loader.js'), // Path to loader
options: {}
});
}
});
});
}
}
Perlu dicatat bahwa saya menggunakan unshift daripada push untuk menambahkan loader - saya masih dalam tahap pengembangan jadi saya bisa saja salah, tetapi pemahaman saya saat ini adalah saya ingin loader saya dijalankan setelah semua loader 'standar' yang mungkin sedang mentranspilasi TypeScript, dll. Saya percaya bahwa loader kemudian diterapkan dari kanan ke kiri. Tergantung pada apa yang Anda lakukan, ini mungkin tidak penting.
