Webpack Plugin: Как динамически добавить модуль в основной блок?
Я работаю над плагином Webpack, который в основном ищет css
активы внутри кусков, когда он создает такой актив, применяет к нему некоторые postCSS
плагин, который возвращает 2 выхода, который должен быть извлечен с помощью Extract-Text-Plugin
и другой вывод должен стать новым модулем внутри чанка, который вводит его в голову во время выполнения.
Единственная часть, которую мне не удалось реализовать, - это часть, которая создает новый модуль внутри существующего блока. Есть какие-то указатели / идеи?
Мне удалось создать новый кусок из этого, но без упаковщиков, это означает, что я не могу поддерживать HMR для этого куска CSS и загружать его лениво.
class ExtractTPAStylePlugin {
constructor(options) {
this._options = Object.assign({
pattern: [
/"\w+\([^\)]+\)"/
]
}, options);
}
extract(compilation, chunks) {
const promises = [];
chunks.forEach((chunk) => {
promises.push(
chunk.files
.filter(fileName => fileName.endsWith('.css'))
.map(file => postcss([extractStyles(this._options)])
.process(compilation.assets[file].source(), {from: file, to: file})
.then((result) => {
compilation.assets[file] = new RawSource(result.css);
const filename = file.replace('.css', fileSuffix);
const newChunk = new Chunk(filename);
newChunk.files = [filename];
newChunk.ids = [];
compilation.chunks.push(newChunk);
const extractedStyles = `(${addStylesTemplate})()`
.replace('__CSS__', JSON.stringify(result.extracted))
.replace('__ID__', file);
compilation.assets[filename] = new OriginalSource(extractedStyles);
}))
);
});
return Promise.all(promises);
}
apply(compiler) {
compiler.plugin('compilation', (compilation) => {
compilation.plugin('optimize-chunk-assets', (chunks, callback) => {
this.extract(compilation, chunks)
.then(() => callback())
.catch(callback);
});
});
}
}
module.exports = ExtractTPAStylePlugin;
1 ответ
Итак, мне удалось собрать несколько фрагментов кода из нескольких плагинов, и выигрышное решение - внедрить загрузчик в какой-то поддельный файл импорта, в этом загрузчике загрузить весь код js в основной пакет и поместить некоторый заполнитель для результаты от optimize-chunk-assets
фаза.
После этого в optimize-chunk-assets
, вы можете найти соответствующий кусок, и использовать ReplaceSource
найти и заменить заполнитель.
Для вдохновения вы можете проверить этот плагин.
Возможно, есть другие способы сделать это.
Я нашел один удобный способ - создать собственный NormalModuleFactory
plugin и подключив его к компилятору.
Плагин получает запрос модуля и контекст (откуда и что импортируется). При этом вы можете сопоставить запрос и вернуть исходный код модуля. В упрощенном виде это выглядит примерно так:
class CustomModuleFactoryPlugin {
apply (normalModuleFactory) {
// Tap in the factory hook.
normalModuleFactory.hooks.factory.tap(
'CustomModuleFactoryPlugin',
factory => (data, cb) => {
const { context } = data
const { request } = data.dependencies[0]
if (path.join(context, request).contains('/something/you/expect') {
return cb(null, new RawSource('Success!'))
}
return factory(data, cb)
}
)
}
}