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)
      }
    )
  }
}
Другие вопросы по тегам