Реализация плагина Webpack с нуля

Webpack
Реализация плагина Webpack с нуля

Plugins expose the full potential of the webpack engine to third-party developers. ----------- Webpack

По сравнению с загрузчиками плагины более гибкие, потому что они имеют доступ к компилятору webpack и ядру компиляции. Это позволяет плагину перехватывать выполнение веб-пакета через некоторые функции ловушек, и даже вы можете запускать подкомпилятор последовательно с загрузчиком, напримерMiniCssExtractPluginВот что он делает.

Образец кода:link

базовая структура плагина webpack

кhtml-webpack-pluginНапример, он используется следующим образом

plugins: [
    new HtmlWebpackPlugin({
        ...
    }),
],

Нетрудно заметить, что основная форма плагина webpack — это конструктор.new function(), и в то же время, чтобы получить компилятор, нужно выставить интерфейс для плагина (дляapplyфункция). Итак, его базовая структура выглядит следующим образом:

  • именованный объект функции JavaScript;
  • В своемprototypeвыше, определитеapplyметод.

Есть много способов реализовать эту форму в JavaScript, в этой статье используетсяclassдобиться следующим образом

module.exports = class DemoPlugin {
    apply() {
        console.log('applying')
    }
}

Настроить среду разработки

Чтобы иметь возможность запускать этот плагин, нам нужно создать среду

mkdir webpack-demo-plugin
cd webpack-demo-plugin
npm init

webpack.plugin.js

const path = require("path");

const PATHS = {
  lib: path.join(__dirname, "index.js"),
  build: path.join(__dirname, "build"),
};

module.exports = {
  entry: {
    lib: PATHS.lib,
  },
  output: {
    path: PATHS.build,
    filename: "[name].js",
  },
};

index.js

console.log("hello world")

в то же время, чтобыpackage.jsonдобавлено в

"scripts": {
    "build:plugin": "webpack --config webpack.plugin.js --mode production",
    ...
  }

Реализовать демонстрацию веб-пакета

Создайтеplugins/demo-plugin.jsфайл, содержимое представляет собой предыдущую демо-версию плагина webpack, и оно импортируется вwebpack.plugin.jsВнутри.

webpack.plugin.js

const DemoPlugin = require("./plugins/demo-plugin.js");

module.exports = {
  ...
  // 引入 plugin
  plugins: [new DemoPlugin()],
};

попробуй убежатьnpm run build:plugin, который распечатывается на терминале

applying
Hash: 98c8997160aa995a58a4
Version: webpack 4.12.0
Time: 93ms
Built at: 2019-04-29 14:34:31
 Asset       Size  Chunks             Chunk Names
lib.js  956 bytes       0  [emitted]  lib
[0] ./index.js 26 bytes {0} [built]

Удивительно обнаружил приложение, указывающее на то, что плагин успешно запущен.

передать параметры

При применении плагина иногда необходимо передать параметры, чтобы сообщить плагину, что делать. когдаnew DemoPlugin()вызоветclass DemoPluginизconstructorтак

plugins/demo-plugin.js

module.exports = class DemoPlugin {
    constructor(options) {
        this.options = options
    }
    apply() {
        console.log('apply', this.options)
    }
}

При этом необходимо модифицироватьwebpack.plugin.jsпередать соответствующие параметры

module.exports = {
    ...
    plugins: [new DemoPlugin({ name: 'demo' })],
}

бегатьnpm run build:plugin, его можно найтиapply { name: 'demo' }. Вот обычный плагинschema-utilsМожет использоваться для проверки параметров.

Понимание компилятора и компиляции webpack

Представленный в предыдущей базовой структуре плагина webpack,applyФункции можно использовать для доступа к ядру webpack. Конкретно,applyПараметры функцииcompiler

plugins/demo-plugin.js

module.exports = class DemoPlugin {
    constructor(options) {
        this.options = options
    }
    apply(compiler) {
        console.log(compiler)
    }
}

бежать сноваnpm run build:plugin, вы обнаружите, что терминал выводитcompilerвся информация о которомhooksПоля составляют подавляющее большинство.

Контрастофициальная документация, вы обнаружите, что каждый хук соответствует определенному этапу. Например, практика emit выполняется перед отправкой ресурсов в выходной каталог. Таким образом, вы можете контролировать процесс компиляции, слушая хук.

plugins/demo-plugin.js

module.exports = class DemoPlugin {
    constructor(options) {
        this.options = options
    }
    apply(compiler) {
        compiler.plugin('emit', (compilation, next) => {
            console.log(compilation)

            next()
        })
    }
}

Не забудьте вызвать next, иначе webpack не продолжит связывание.

бегатьnpm run build:pluginпокажет больше информации, чем раньше, потому что скомпилированный объект содержит весь граф зависимостей, через который проходит webpack. Вы можете получить доступ ко всему, что с этим связано, включая записи, фрагменты, модули, активы и т. д.

Запись в файл через компиляцию

в состоянии пройтиcompilationизassetsобъект для записи нового файла или изменения уже созданного файла. Чтобы лучше писать файлы, мы вводим пакет npm

npm install webpack-sources --save-dev

plugins/demo-plugin.js

const { RawSource } = require("webpack-sources");

module.exports = class DemoPlugin {
    constructor(options) {
        this.options = options
    }
    apply(compiler) {
        const { name } = this.options;

        compiler.plugin('emit', (compilation, next) => {
            compilation.assets[name] = new RawSource("demo");

            next()
        })
    }
}

запустить в терминалеnpm run build:plugin

Hash: 98c8997160aa995a58a4
Version: webpack 4.12.0
Time: 95ms
Built at: 2019-04-29 16:08:52
 Asset       Size  Chunks             Chunk Names
lib.js  956 bytes       0  [emitted]  lib
  demo    4 bytes          [emitted]
[0] ./index.js 26 bytes {0} [built]

В столбце «Актив» появится наш пользовательский демонстрационный файл.

Дополнительные функции ловушек см.the official compilation reference.

Управление предупреждениями и ошибками

проведите эксперимент, если выapplyВставить в функциюthrow new Error("Message"), что происходит, терминал печатаетUnhandled rejection Error: Message. Затем webpack прерывает выполнение.

Для того, чтобы не влиять на выполнение вебпака, для предупреждения или сообщений об ошибках пользователю во время компиляции, следует использоватьcompilation.warningsа такжеcompilation.errors.

compilation.warnings.push("warning");
compilation.errors.push("error");

Суммировать

Когда вы начинаете разрабатывать плагин, обязательно найдите время для изучения существующих плагинов того же типа. Разрабатывайте плагины один за другим, чтобы проверять только один плагин за раз. Если у вас возникнут проблемы, вы можете проверить исходный код веб-пакета, это улучшит вашу интуицию в отладке.

Ссылаться на:

Веб-пакет. Просто .org/contribute/…

выжить JS.com/Web pack/ext…

Веб-пакет.Просто .org/API/plugins…