используется в этой статьеWebpack-Quickly-StarterБыстро создайте локальную среду обучения Webpack4.
Рекомендуется прочитать больше документации Webpack "Writing a Plugin", научитесь разрабатывать простые подключаемые модули.
Эта статья поможет вам разработать свой первый плагин Webpack от инженера по настройке Webpack до инженера-разработчика Webpack!
Сделайте свои собственные колеса и позвольте другим использовать их.
Полный код хранится в:GitHub.com/Ping An8787/…
1. Введение
Эта статья вдохновлена обобщением опыта в бизнесе,Не боится богоподобных продуктов, боится только развития одного сухожилия.
Есть проблема с упаковкой проекта: «Когда проект размещается на платформе CDN, есть надежда, что index.js в проекте не будет кэшироваться». потому что нам нужно изменитьindex.js
Содержимое в , не хотите, чтобы пользователи кэшировались.
Поразмыслив некоторое время, появилось несколько идей:
- Отфильтруйте настройки кеша для этого файла на платформе CDN;
- Найдите элемент DOM, измените
script
помеченsrc
значение и добавьте отметку времени; - Динамически создается при упаковке
script
В файл импортируются теги и добавляются временные метки.
(Вы умны, и есть другие способы, добро пожаловать на обсуждение)
Анализ мыслей:
- Очевидно, что если вы измените настройки CDN, симптомы не исчезнут;
- В файле шаблона добавьте
script
тег, выполните, чтобы получить те, которые автоматически добавляются Webpackscript
наклей и сделайsrc
Значение добавляет метку времени. Но дело в том, что файл js был загружен до того, как вы закончили его модифицировать, так что сдавайтесь. - нуждаться в
index.html
Перед созданием измените путь к файлу js и добавьте метку времени.
Поэтому я собираюсь использовать третий метод, вindex.html
Перед созданием выполните следующие изменения:
Проблема проста, но я все еще хочу попробовать разработать плагин Webpack.
2. Базовые знания
Webpack использует обратные вызовы поэтапной сборки, и разработчики могут вводить собственное поведение в процесс сборки Webpack.
Перед разработкой вам необходимо понять следующие концепции, связанные с Webpack:
2.1 Состав плагина Webpack
Прежде чем настраивать плагин, нам нужно понять, что представляет собой плагин Webpack.Ниже приведен отрывок из документа:
- именованная функция JavaScript;
- определить метод применения на его прототипе;
- Указать тач самому Webpackхук событий;
- Манипулировать данными конкретного экземпляра внутри Webpack;
- Обратный вызов, предоставляемый Webpack, вызывается после реализации функции.
2.2 Базовая архитектура плагина Webpack
Плагины создаются конструктором. Определение конструктораapply
метод, при установке плагина,apply
метод будет использоваться Webpackcompiler
Звонил один раз.apply
метод может получить Webpackcompiler
Ссылка на объект, к которому можно получить доступ в функции обратного вызоваcompiler
объект.
Официальная документация предоставляет простую структуру плагина:
class HelloWorldPlugin {
apply(compiler) {
compiler.hooks.done.tap('Hello World Plugin', (
stats /* 在 hook 被触及时,会将 stats 作为参数传入。 */
) => {
console.log('Hello World!');
});
}
}
module.exports = HelloWorldPlugin;
Используйте плагин:
// webpack.config.js
var HelloWorldPlugin = require('hello-world');
module.exports = {
// ... 这里是其他配置 ...
plugins: [new HelloWorldPlugin({ options: true })]
};
2.3 Введение в HtmlWebpackPlugin
Плагин HtmlWebpackPlugin упрощает создание HTML-файлов для обслуживания пакетов Webpack. Это особенно полезно для пакетов веб-пакетов, в именах файлов которых есть хэши, которые меняются при каждой компиляции.
Основные функции плагина резюмируются:Создать HTML-файл.
html-webapck-plugin
плагинДве главные роли:
- Импортируйте внешние ресурсы (например,
script
/link
) Динамически добавлять хэш после каждой компиляции, чтобы предотвратить проблему кэширования файлов, на которые ссылаются; - Динамически создавать файлы ввода HTML, например, для одностраничных приложений.
index.html
документ.
html-webapck-plugin
плагинПринцип введения:
- Читать в вебпаке
entry
Запись, связанная с конфигурациейchunk
а такжеextract-text-webpack-plugin
стили CSS, извлекаемые плагинами; - Вставьте стили в предоставленный плагин
template
илиtemplateContent
В файле шаблона, заданном конфигурацией; - Способ вставки: через
link
теги импортируют стили черезscript
Этикетки импортируют файлы скриптов;
3. Процесс разработки
Разработано в этой статьеАвтоматически добавлять временные метки к ссылкам на файлы сценариев (SetScriptTimestampPlugin)Принцип реализации плагина: черезHtmlWebpackPluginПеред созданием файла HTML скопируйте файл шаблонаЗамените зарезервированное пространство скриптом, сценарий выполняет автоматическую отметку времени для ссылки на файл сценария.
3.1 Вставной рабочий механизм
3.2 Инициализируйте файл плагина
новыйSetScriptTimestampPlugin.js
файл и обратитесь к базовой структуре плагина в официальной документации для инициализации кода плагина:
// SetScriptTimestampPlugin.js
class SetScriptTimestampPlugin {
apply(compiler) {
compiler.hooks.done.tap('SetScriptTimestampPlugin',
(compilation, callback) => {
console.log('SetScriptTimestampPlugin!');
});
}
}
module.exports = SetScriptTimestampPlugin;
apply
Метод является подключаемым методом-прототипом, получаяcompiler
как параметр.
3.3 Выберите время запуска плагина
Выбор момента срабатывания подключаемого модуля на самом деле означает выбор хука компилятора, запускаемого подключаемым модулем (то есть, когда запускается подключаемый модуль).
Webpack предоставляет множество хуков. Вот некоторые из них вкратце. Полную информацию см. в документе "Compiler Hooks":
-
entryOption
: в параметрах веб-пакетаentry
После обработки элемента конфигурации плагин выполняется. -
afterPlugins
: После установки начального плагина запустите плагин. -
compilation
: После компиляции и создания перед генерацией файла выполните плагин. . -
emit
: генерировать ресурсы дляoutput
перед каталогом. -
done
: Компиляция завершена.
Наш плагин должен быть динамически добавлен перед выводом HTMLscript
тег, поэтому мы решили подключиться кcompilation
Стадия, модификация кода:
// SetScriptTimestampPlugin.js
class SetScriptTimestampPlugin {
apply(compiler) {
- compiler.hooks.done.tap('SetScriptTimestampPlugin',
+ compiler.hooks.compilation.tap('SetScriptTimestampPlugin',
(compilation, callback) => {
console.log('SetScriptTimestampPlugin!');
});
}
}
module.exports = SetScriptTimestampPlugin;
существуетcompiler.hooks
указанный вфункция ловушки событий, функция обратного вызова будет выполняться при срабатывании хука.
Webpack предоставляет три способа запуска хуков:
-
tap
:кСинхронноспусковой крючок; -
tapAsync
:кАсинхронный способспусковой крючок; -
tapPromise
:кАсинхронный способАктивировать крючок и вернуть обещание;
Методы перехвата, которые могут быть выбраны этими тремя методами, также различны, потому чтоcompilation
ДаSyncHook
Хук синхронизации, поэтому используйтеtap
триггерный метод.tap
Метод принимает два параметра: имя плагина и функцию обратного вызова.
3.4 Добавить запись о замене плагина
В принципе, мы указываем запись замены в файле шаблона, а затем заменяем ее скриптом, который необходимо выполнить.
Итак, мы в файле шаблонаtemplate.html
добавлено в<!--SetScriptTimestampPlugin inset script-->
Замените запись как идентификатор:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webpack 插件开发入门</title>
</head>
<body>
<!-- other code -->
<!--SetScriptTimestampPlugin inset script-->
</body>
</html>
3.5 Написание логики плагина
На этом этапе мы начинаем писать логику плагина.
Из предыдущего шага мы знаем, что вtap
Второй параметр — это функция обратного вызова, и эта функция обратного вызова имеет два параметра:compilation
а такжеcallback
.
compilation
унаследовано отcompiler
,Включатьcompiler
Все (также Webpackoptions
), а также имеетplugin
Точка задачи доступа к функциям.
// SetScriptTimestampPlugin.js
class SetScriptTimestampPlugin {
apply(compiler) {
compiler.hooks.compilation.tap('SetScriptTimestampPlugin',
(compilation, callback) => {
// 插件逻辑 调用compilation提供的plugin方法
compilation.plugin(
"html-webpack-plugin-before-html-processing",
function(htmlPluginData, callback) {
// 读取并修改 script 上 src 列表
let jsScr = htmlPluginData.assets.js[0];
htmlPluginData.assets.js = [];
let result = `
<script>
let scriptDOM = document.createElement("script");
let jsScr = "./${jsScr}";
scriptDOM.src = jsScr + "?" + new Date().getTime();
document.body.appendChild(scriptDOM)
</script>
`;
let resultHTML = htmlPluginData.html.replace(
"<!--SetScriptTimestampPlugin inset script-->", result
);
// 返回修改后的结果
htmlPluginData.html = resultHTML;
}
);
}
);
}
}
module.exports = SetScriptTimestampPlugin;
В приведенной выше логике плагина эти вещи выполняются специально:
- воплощать в жизнь
compilation.plugin
метод и передать два параметра: событие плагина и метод обратного вызова.
Так называемые «события подключаемого модуля» — это некоторые события, предоставляемые подключаемым модулем для отслеживания состояния подключаемого модуля. Вот некоторые из них.html-webpack-plugin
Предоставленные мероприятия (подробности см.html-webpack-plugin"):
Async:
html-webpack-plugin-before-html-generation
html-webpack-plugin-before-html-processing
html-webpack-plugin-alter-asset-tags
Sync:
html-webpack-plugin-alter-chunks
- Получите список имен файлов сценариев и очистите их.
В методе обратного вызова передайтеhtmlPluginData.assets.js
пройти черезscript
Список имен импортированных файлов сценариев, сделайте копию и очистите исходный список.
- Напишите логику замены.
Логика замены такова: динамически создаватьscript
лейбл, поставьsrc
В качестве значения устанавливается имя файла скрипта, прочитанное на предыдущем шаге, и сплайсированное послеотметка временикак параметр.
- Вставьте логику замены.
пройти черезhtmlPluginData.html
Вы можете получить строковый вывод файла шаблона, нам просто нужно заменить запись в строке шаблона<!--SetScriptTimestampPlugin inset script-->
Просто замените его логикой замены, которую мы написали на предыдущем шаге.
- Возвращает HTML-файл.
Наконец, назначьте измененную строку HTML исходномуhtmlPluginData.html
добиться эффекта модификации.
3.5 Использование плагинов
Пользовательское использование плагина, совместимое с другими плагинами, вplugins
Создать экземпляр в массиве:
// webpack.config.js
const SetScriptTimestampPlugin = require("./SetScriptTimestampPlugin.js");
module.exports = {
// ... 省略其他配置
plugins: [
// ... 省略其他插件
new SetScriptTimestampPlugin()
]
}
На данный момент мы реализовали требование «Когда проект размещается на платформе CDN, мы надеемся, что index.js в проекте не будет кэшироваться».
4. Развитие дела
здесь раньшеSetScriptTimestampPluginПлагины, например, продолжают расширяться.
4.1 Чтение параметров конфигурации плагина
Каждый плагин по сути является классом, который аналогичен созданию экземпляра класса.Вы можете передавать параметры конфигурации во время создания экземпляра и работать в конструкторе:
// SetScriptTimestampPlugin.js
class SetScriptTimestampPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
console.log(this.options.filename); // "index.js"
// ... 省略其他代码
}
}
module.exports = SetScriptTimestampPlugin;
при его использовании:
// webpack.config.js
const SetScriptTimestampPlugin = require("./SetScriptTimestampPlugin.js");
module.exports = {
// ... 省略其他配置
plugins: [
// ... 省略其他插件
new SetScriptTimestampPlugin({
filename: "index.js"
})
]
}
4.2 Добавление временных меток для файлов с несколькими сценариями
Если нам нужно изменить временные метки нескольких файлов сценариев одновременно, нам нужно только настроить тип параметра и сценарий выполнения.
Конкретная модификация скрипта здесь не описывается, место ограничено, вы можете подумать об этом сами~
Вот параметры при использовании плагина:
// webpack.config.js
const SetScriptTimestampPlugin = require("./SetScriptTimestampPlugin.js");
module.exports = {
// ... 省略其他配置
plugins: [
// ... 省略其他插件
new SetScriptTimestampPlugin({
filename: ["index.js", "boundle.js", "pingan.js"]
})
]
}
Сгенерировать результат:
<script src="./index.js?1582425467655"></script>
<script src="./boundle.js?1582425467655"></script>
<script src="./pingan.js?1582425467655"></script>
V. Резюме
В этой статье используется общий настраиваемый плагин Webpack для выполнения некоторых из более сложных ежедневных требований. Он в основном знакомит с базовой композицией и простой архитектурой подключаемого модуля Webpack, а также знакомит с подключаемым модулем HtmlWebpackPlugin. Благодаря этим базовым знаниям подключаемый модуль замены текста HTML завершен, и, наконец, сфера использования подключаемого модуля расширяется за счет двух сценариев.
Наконец, есть больше знаний, чтобы узнать о разработке плагинов Webpack.Рекомендуется взглянуть на официальную документацию "Writing a Plugin" учиться.
Эта статья представляет собой чисто резюме личного опыта, если у вас есть какие-либо возражения, пожалуйста, дайте указатели.