Spec-Zone.ru › webpack 1

Плагины

Для общего ознакомления с написанием плагинов, начните с Как написать плагин.

Многие объекты в Webpack расширяют класс Tapable, который предоставляет метод plugin. А с помощью метода plugin, плагины могут вставлять пользовательские шаги сборки. Вы часто увидите compiler.plugin и compilation.plugin. По существу, каждый из этих вызовов плагина связывает обратный вызов, который срабатывает на определенных этапах процесса сборки.

Плагин устанавливается один раз при запуске Webpack. Webpack устанавливает плагин, вызывая его метод apply, и передаёт ссылку на объект Webpack compiler. Затем вы можете вызвать compiler.plugin, чтобы получить доступ к компиляциям ресурсов и их отдельным шагам сборки. Пример выглядит так:

// MyPlugin.js

function MyPlugin(options) {
  // Configure your plugin with options...
}

MyPlugin.prototype.apply = function(compiler) {
  compiler.plugin("compile", function(params) {
    console.log("The compiler is starting to compile...");
  });

  compiler.plugin("compilation", function(compilation) {
    console.log("The compiler is starting a new compilation...");

    compilation.plugin("optimize", function() {
      console.log("The compilation is starting to optimize files...");
    });
  });

  compiler.plugin("emit", function(compilation, callback) {
    console.log("The compilation is going to emit files...");
    callback();
  });
};

module.exports = MyPlugin;

Затем в webpack.config.js

    plugins: [
        new MyPlugin({options: 'nada'})
    ]

Примечание по типам интерфейсов…

Существует два типа интерфейсов плагинов.

  • Основанные на времени

    • sync (по умолчанию): Как показано выше. Используйте return.
    • async: Последний параметр — это обратный вызов. Подпись: function(err, result)
    • parallel: Обработчики вызываются параллельно (async).
  • Значение возврата

    • не прерывающий (по умолчанию): Значение возврата отсутствует.
    • прерывающий: Обработчики вызываются по порядку, пока один из них не вернёт что-то.
    • параллельный прерывающий: Обработчики вызываются параллельно (async). Первое возвращённое значение (по порядку) является значимым.
    • waterfall: Каждый обработчик получает значение возврата предыдущего обработчика в качестве аргумента.

Экземпляр компилятора

Плагины должны иметь метод apply в своей цепочке прототипов (или связанный с ним), чтобы иметь доступ к экземпляру компилятора.

//MyPlugin.js

function MyPlugin() {};
MyPlugin.prototype.apply = function (compiler) {
    //now you have access to all the compiler instance methods
}
module.exports = MyPlugin;

Что-то вроде этого тоже должно работать

//MyFunction.js

function apply(options, compiler) {
    //now you have access to the compiler instance
    //and options
}

//this little trick makes it easier to pass and check options to the plugin
module.exports = function(options) {
    if (options instanceof Array) {
        options = {
            include: options
        };
    }

    if (!Array.isArray(options.include)) {
        options.include = [ options.include ];
    }

    return {
        apply: apply.bind(this, options)
    };
};
run(compiler: Compiler) асинхронный

Метод run компилятора используется для запуска компиляции. Этот метод не вызывается в режиме наблюдения.

watch-run(watching: Watching) асинхронный

Метод watch компилятора используется для запуска компиляции в режиме наблюдения. Этот метод не вызывается в обычном режиме.

compilation(c: Compilation, params: Object)

Создаётся Compilation. Плагин может использовать его, чтобы получить ссылку на объект Compilation. Объект params содержит полезные ссылки.

normal-module-factory(nmf: NormalModuleFactory)

Создаётся NormalModuleFactory. Плагин может использовать его, чтобы получить ссылку на объект NormalModuleFactory.

compiler.plugin("normal-module-factory", function(nmf) {
    nmf.plugin("after-resolve", function(data) {
        data.loaders.unshift(path.join(__dirname, "postloader.js"));
    });
});
context-module-factory(cmf: ContextModuleFactory)

Создаётся ContextModuleFactory. Плагин может использовать его, чтобы получить ссылку на объект ContextModuleFactory.

compile(params)

Компилятор начинает компиляцию. Этот этап используется в обычном и наблюдаемом режимах. Плагины могут использовать этот момент для изменения объекта params (например, для оформления фабрик).

compiler.plugin("compile", function(params) {
    //you are now in the "compile" phase
});
make(c: Compilation) параллельно

Плагины могут использовать этот момент для добавления записей в компиляцию или предварительной выборки модулей. Для этого они могут вызвать addEntry(context, entry, name, callback) или prefetch(context, dependency, callback) на компиляции.

after-compile(c: Compilation) асинхронный

Процесс компиляции завершен, и модули запечатаны. Следующий шаг — выдача сгенерированных данных. Здесь модули могут использовать результаты различными интересными способами.

Обработчики не копируются в дочерние компиляторы.

emit(c: Compilation) асинхронный

Компилятор начинает выдачу сгенерированных ресурсов. Здесь плагины имеют последнюю возможность добавить ресурсы в массив c.assets.

after-emit(c: Compilation) асинхронный

Компилятор выдал все ресурсы.

done(stats: Stats)

Всё завершено.

failed(err: Error)

Компилятор работает в режиме наблюдения и компиляция завершилась неудачно.

invalid()

Компилятор работает в режиме наблюдения и обнаружено изменение файла. Компиляция начнётся в ближайшее время (options.watchDelay).

after-plugins()

Все плагины, извлечённые из объекта параметров, добавляются в компилятор.

after-resolvers()

Все плагины, извлеченные из объекта опций, добавляются в разрешители.

Экземпляр компиляции

Экземпляр Compilation расширяет компилятор. т. е. compiler.compilation Он представляет собой фактическую компиляцию всех объектов в графе require. Этот объект имеет доступ ко всем модулям и их зависимостям (большая часть из которых является циклическими ссылками). На этапе компиляции модули загружаются, запечатываются, оптимизируются, группируются, хэшируются и восстанавливаются и т. д. Это был бы основной жизненный цикл любых операций компиляции.

compiler.plugin("compilation", function(compilation) {
    //the main compilation instance
    //all subsequent methods are derived from compilation.plugin
});
normal-module-loader

Обычный загрузчик модулей — это функция, которая фактически загружает все модули в графе модулей (по одному).

compilation.plugin('normal-module-loader', function(loaderContext, module) {
    //this is where all the modules are loaded
    //one by one, no dependencies are created yet
});
seal

Началась фаза запечатывания компиляции.

compilation.plugin('seal', function() {
    //you are not accepting any more modules
    //no arguments
});
optimize

Оптимизация компиляции.

compilation.plugin('optimize', function() {
    //webpack is begining the optimization phase
    // no arguments
});
optimize-tree(chunks, modules) асинхронный

Асинхронная оптимизация дерева.

compilation.plugin('optimize-tree', function(chunks, modules) {

});
optimize-modules(modules: Module[])

Оптимизация модулей.

compilation.plugin('optimize-modules', function(modules) {
    //handle to the modules array during tree optimization
});
after-optimize-modules(modules: Module[])

Оптимизация модулей завершена.

optimize-chunks(chunks: Chunk[])

Оптимизация пакетов.

//optimize chunks may be run several times in a compilation

compilation.plugin('optimize-chunks', function(chunks) {
    //unless you specified multiple entries in your config
    //there's only one chunk at this point
    chunks.forEach(function (chunk) {
        //chunks have circular references to their modules
        chunk.modules.forEach(function (module){
            //module.loaders, module.rawRequest, module.dependencies, etc.
        }); 
    });
});
after-optimize-chunks(chunks: Chunk[])

Оптимизация пакетов завершена.

revive-modules(modules: Module[], records)

Восстановление информации о модулях из записей.

optimize-module-order(modules: Module[])

Сортировка модулей по важности. Первый — самый важный модуль. Он получит наименьший идентификатор.

optimize-module-ids(modules: Module[])

Оптимизация идентификаторов модулей.

after-optimize-module-ids(modules: Module[])

Оптимизация идентификаторов модулей завершена.

record-modules(modules: Module[], records)

Сохранение информации о модулях в записях.

revive-chunks(chunks: Chunk[], records)

Восстановление информации о пакетах из записей.

optimize-chunk-order(chunks: Chunk[])

Сортировка пакетов по важности. Первый — самый важный пакет. Он получит наименьший идентификатор.

optimize-chunk-ids(chunks: Chunk[])

Оптимизация идентификаторов пакетов.

after-optimize-chunk-ids(chunks: Chunk[])

Оптимизация идентификаторов пакетов завершена.

record-chunks(chunks: Chunk[], records)

Сохранение информации о пакетах в записях.

before-hash

Перед хэшированием компиляции.

after-hash

После хэширования компиляции.

before-chunk-assets

Перед созданием ресурсов пакета.

additional-chunk-assets(chunks: Chunk[])

Создание дополнительных ресурсов для пакетов.

record(compilation, records)

Сохранение информации о компиляции в записях.

optimize-chunk-assets(chunks: Chunk[]) асинхронный

Оптимизация ресурсов для пакетов.

Ресурсы хранятся в this.assets, но не все из них являются ресурсами пакетов. У Chunk есть свойство files, которое указывает на все файлы, созданные этим пакетом. Дополнительные ресурсы пакета хранятся в this.additionalChunkAssets.

Вот пример, который просто добавляет заголовок к каждому пакету.

compilation.plugin("optimize-chunk-assets", function(chunks, callback) {
    chunks.forEach(function(chunk) {
        chunk.files.forEach(function(file) {
            compilation.assets[file] = new ConcatSource("\/**Sweet Banner**\/", "\n", compilation.assets[file]);
        });
    });
    callback();
});
after-optimize-chunk-assets(chunks: Chunk[])

Ресурсы пакетов оптимизированы. Вот пример плагина от @boopathi, который выводит то, что вошло в каждый пакет.

var PrintChunksPlugin = function() {};
PrintChunksPlugin.prototype.apply = function(compiler) {
    compiler.plugin('compilation', function(compilation, params) {
        compilation.plugin('after-optimize-chunk-assets', function(chunks) {
            console.log(chunks.map(function(c) {
                return {
                    id: c.id,
                    name: c.name,
                    includes: c.modules.map(function(m) {
                        return m.request;
                    })
                };
            }));
        });
    });
};
optimize-assets(assets: Object{name: Source}) асинхронный

Оптимизация всех ресурсов.

Ресурсы хранятся в this.assets.

after-optimize-assets(assets: Object{name: Source})

Ресурсы оптимизированы.

build-module(module)

Перед началом сборки модуля.

compilation.plugin('build-module', function(module){
    console.log('build module');
    console.log(module);
});
succeed-module(module)

Модуль успешно собран.

compilation.plugin('succeed-module', function(module){
    console.log('succeed module');
    console.log(module);
});
failed-module(module)

Сборка модуля завершилась неудачно.

compilation.plugin('failed-module', function(module){
    console.log('failed module');
    console.log(module);
});
module-asset(module, filename)

Ресурс модуля добавлен в компиляцию.

chunk-asset(chunk, filename)

Ресурс пакета добавлен в компиляцию.

Экземпляр MainTemplate

startup(source, module, hash)
    compilation.mainTemplate.plugin('startup', function(source, module, hash) {
      if (!module.chunks.length && source.indexOf('__ReactStyle__') === -1) {
        var originName = module.origins && module.origins.length ? module.origins[0].name : 'main';
        return ['if (typeof window !== "undefined") {',
            '  window.__ReactStyle__ = ' + JSON.stringify(classNames[originName]) + ';',
            '}'
          ].join('\n') + source;
      }
      return source;
    });

Экземпляр Parser (compiler.parser)

Экземпляр парсера принимает строку и обратный вызов и вернёт выражение при совпадении.

compiler.parser.plugin("var rewire", function (expr) {
    //if you original module has 'var rewire'
    //you now have a handle on the expresssion object   
    return true;
});
program(ast) прерывающий

Плагин общего назначения для абстрактного синтаксического дерева (AST) фрагмента кода.

statement(statement: Statement) прерывающий

Плагин общего назначения для инструкций фрагмента кода.

call <identifier>(expr: Expression) прерывающий

abc(1) => call abc

a.b.c(1) => call a.b.c

expression <identifier>(expr: Expression) прерывающий

abc => expression abc

a.b.c => expression a.b.c

expression ?:(expr: Expression) прерывающий

(abc ? 1 : 2) => expression ?!

Возвращает логическое значение, чтобы пропустить разбор неправильного пути.

typeof <identifier>(expr: Expression) прерывающий

typeof a.b.c => typeof a.b.c

statement if(statement: Statement) прерывающий

if(abc) {} => statement if

Возвращает логическое значение, чтобы пропустить разбор неправильного пути.

label <labelname>(statement: Statement) прерывающий

xyz: abc => label xyz

var <name>(statement: Statement) прерывающий

var abc, def => var abc + var def

Возвращает false, чтобы не добавлять переменную в известные определения.

evaluate <expression type>(expr: Expression) прерывающий

Оценить выражение.

evaluate typeof <identifier>(expr: Expression) прерывающий

Оценить тип идентификатора.

evaluate Identifier <identifier>(expr: Expression) прерывающий

Оценить идентификатор, являющийся свободной переменной.

evaluate defined Identifier <identifier>(expr: Expression) отмена

Оценить идентификатор, являющийся определённой переменной.

evaluate CallExpression .<property>(expr: Expression) отмена

Оценить вызов члена функции успешно оценённого выражения.

Фабрика модулей NormalModuleFactory

before-resolve(data) асинхронная каскадная обработка

Перед тем, как фабрика начнёт разрешение. Объект data имеет следующие свойства:

  • context Абсолютный путь к каталогу для разрешения.
  • request Запрос выражения.

Плагины могут изменять объект или передать новый похожий объект в коллбэк.

after-resolve(data) асинхронная каскадная обработка

После того, как фабрика выполнила разрешение запроса. Объект data имеет следующие свойства:

  • request Разрешённый запрос. Он служит идентификатором для NormalModule.
  • userRequest Запрос, введённый пользователем. Он разрешён, но не содержит пре- и пост-загрузчиков.
  • rawRequest Неразрешённый запрос.
  • loaders Массив разрешённых загрузчиков. Он передаётся NormalModule, и они будут выполнены.
  • resource Ресурс. Он будет загружен NormalModule.
  • parser Парсер, который будет использован NormalModule.

Фабрика модулей ContextModuleFactory

before-resolve(data) асинхронная каскадная обработка
after-resolve(data) асинхронная каскадная обработка
alternatives(options: Array) асинхронная каскадная обработка

Разрешители

  • compiler.resolvers.normal Разрешитель для обычного модуля
  • compiler.resolvers.context Разрешитель для модуля контекста
  • compiler.resolvers.loader Разрешитель для загрузчика

Любой плагин должен использовать this.fileSystem в качестве fileSystem, поскольку он кешируется. Он содержит только асинхронные именованные функции, но они могут вести себя синхронно, если пользователь использует синхронную реализацию файловой системы (например, в enhanced-require).

Для объединения путей любой плагин должен использовать this.join. Он нормализует пути. Также есть this.normalize.

Доступна асинхронная реализация forEach для отмены this.forEachBail(array, iterator, callback).

Для передачи запроса другим плагинам разрешения используйте метод this.doResolve(types: String|String[], request: Request, callback) . types — это несколько возможных типов запросов, которые тестируются в порядке предпочтения.

interface Request {
    path: String // The current directory of the request
    request: String // The current request string
    query: String // The query string of the request, if any
    module: boolean // The request begins with a module
    directory: boolean // The request points to a directory
    file: boolean // The request points to a file
    resolved: boolean // The request is resolved/done
    // undefined means false for boolean fields
}

// Examples
// from /home/user/project/file.js: require("../test?charset=ascii")
{
    path: "/home/user/project",
    request: "../test",
    query: "?charset=ascii"
}
// from /home/user/project/file.js: require("test/test/")
{
    path: "/home/user/project",
    request: "test/test/",
    module: true,
    directory: true
}
resolve(context: String, request: String)

Перед началом процесса разрешения.

resolve-step(types: String[], request: Request)

Перед началом отдельного шага в процессе разрешения.

module(request: Request) асинхронная каскадная обработка

Найден запрос на модуль и должен быть разрешён.

directory(request: Request) асинхронная каскадная обработка

Найден запрос на каталог и должен быть разрешён.

file(request: Request) асинхронная каскадная обработка

Найден запрос на файл и должен быть разрешён.

Плагины могут предложить дополнительные точки расширения

Вот список того, что предлагают стандартные плагины в webpack. Все они — (request: Request) асинхронная каскадная обработка.

Процесс для обычных модулей и контекстов — module -> module-module -> directory -> file.

Процесс для загрузчиков — module -> module-loader-module -> module-module -> directory -> file.

module-module

Модуль должен быть найден в указанном каталоге. path содержит каталог.

module-loader-module (только для загрузчиков)

Используется перед применением шаблонов модулей к имени модуля. Процесс продолжается с module-module.

© 2012–2015 Tobias Koppers
Licensed under the MIT License.
https://webpack.github.io/docs/plugins.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API