передняя часть Seewo ENOW
Официальный сайт компании:CVTE (Гуанчжоу CVTE)
Команда: enow team центра программных платформ Seewo для будущего образования в рамках CVTE
Автор этой статьи:
предисловие
В сегодняшнем все более сложном интерфейсном проектировании инструменты упаковки модулей играют все более важную роль в наших разработках, среди которыхwebpack
Это один из самых популярных упаковочных инструментов.
Говоря оwebpack
, многие мелкие партнеры могут показаться как знакомыми, так и незнакомыми, знакомыми, потому что мы используем их почти в каждом проекте, и потому чтоwebpack
Сложная конфигурация и различные функции незнакомы. Особенно, когда мы используем что-то вродеumi.js
Такие фреймворки приложений также помогают нам инкапсулировать конфигурацию веб-пакета другим уровнем.webpack
Природа его кажется более далекой и непостижимой от нас.
Когда интервьюер спрашивает, понимаешь ли тыwebpack
Когда, может быть, ты сможешь сказать строку знакомуюwebpack loader
иplugin
Название плагина и даже ряд конфигураций могут быть загружены и упакованы по требованию.Знаете ли вы его механизм работы и принцип реализации?Тогда мы будем исследовать его вместе сегодня.webpack
границы компетенции, постарайтесь понятьwebpack
Некоторые процессы и принципы реализации, отказываются делатьAPI
инженер.
Вы знаете, что делает веб-пакет?
Это не сложно понять из описания на официальном сайте.webpack
На самом деле он выполняет следующие функции:
-
Упаковка модуля. Файлы разных модулей могут быть упакованы и объединены вместе, а ссылки между ними могут быть гарантированно правильными и выполняться упорядоченным образом. Используя упаковку, мы можем свободно делить файловые модули в соответствии с нашими собственными делами во время разработки, чтобы обеспечить ясность и читабельность структуры проекта.
-
Совместимость с компиляцией. В «древние времена» фронтенда написание от руки кучи совместимого с браузером кода всегда вызывало онемение у фронтенд-инженеров, но сегодня эта проблема сильно ослабла.
webpack
изLoader
Механизм не только может помочь нам сделать с кодомpolyfill
, вы также можете скомпилировать преобразования, такие как.less, .vue, .jsx
Этот тип файла формата, который не распознается браузером, позволяет нам использовать новые функции и новый синтаксис для разработки во время разработки, повышая эффективность разработки. -
расширение емкости. пройти через
webpack
изPlugin
Механизм, на основе реализации модульной упаковки и совместимости компиляции, мы можем дополнительно реализовать ряд функций, таких как загрузка по требованию, сжатие кода и т. д., чтобы помочь нам еще больше повысить степень автоматизации, инженерную эффективность и качество выход упаковки.
Расскажите о принципе работы модульной упаковки?
Если интервьюер спрашивает васWebpack
Вы понимаете, как эти модули объединяются вместе и гарантированно работают правильно?
Во-первых, мы должны кратко понятьwebpack
Весь процесс упаковки:
- 1. Читать
webpack
параметры конфигурации; - 2. Старт
webpack
,СоздайтеCompiler
объект и начать разбор элемента; - 3. Из входного файла (
entry
) начать синтаксический анализ и найти импортированные зависимые модули, рекурсивно пройти анализ и сформировать дерево зависимостей; - 4. Используйте соответствующие файлы модулей для зависимых файлов модулей разных типов файлов.
Loader
Скомпилируйте и, наконец, конвертируйте вJavascript
документ; - 5. В течение всего процесса
webpack
Некоторые из них будут выбрасываться через модель публикации-подписки.hooks
,иwebpack
Плагин может прослушивать эти ключевые узлы событий, выполнять задачи плагина, а затем достигать цели вмешательства в результаты вывода.
Разбор и создание файлов — относительно сложный процесс.webpack
Исходный код в основном зависит отcompiler
иcompilation
Реализованы два основных объекта.
compiler
Объект представляет собой глобальный синглтон, отвечающий за управление всемwebpack
Пакетный процесс сборки.compilation
Объект является объектом контекста каждой сборки, он содержит всю информацию, необходимую для текущей сборки, каждого горячего обновления и сборки,compiler
будет регенерировать новыйcompilation
Объект, отвечающий за процесс сборки этого обновления.
Зависимости между каждым модулем зависят отAST
синтаксическое дерево. Каждый файл модуля передаетсяLoader
После завершения синтаксического анализа он пройдетacorn
библиотека для генерации кода модуляAST
Синтаксическое дерево, через синтаксическое дерево можно проанализировать, есть ли у этого модуля зависимые модули, а затем продолжить выполнение компиляции и анализа следующего модуля в цикле.
наконец-тоWebpack
в упаковкеbundle
файл представляет собойIIFE
функция исполнения.
// webpack 5 打包的bundle文件内容
(() => { // webpackBootstrap
var __webpack_modules__ = ({
'file-A-path': ((modules) => { // ... })
'index-file-path': ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { // ... })
})
// The module cache
var __webpack_module_cache__ = {};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
var cachedModule = __webpack_module_cache__[moduleId];
if (cachedModule !== undefined) {
return cachedModule.exports;
}
// Create a new module (and put it into the cache)
var module = __webpack_module_cache__[moduleId] = {
// no module.id needed
// no module.loaded needed
exports: {}
};
// Execute the module function
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
// Return the exports of the module
return module.exports;
}
// startup
// Load entry module and return exports
// This entry module can't be inlined because the eval devtool is used.
var __webpack_exports__ = __webpack_require__("./src/index.js");
})
иwebpack4
по сравнению с,webpack5
Упакованный комплект был довольно обтекаемым. упаковка сверхуdemo
, всего три переменных и один метод функции во всей функции непосредственного выполнения,__webpack_modules__
Сохраняет содержимое JS каждого скомпилированного файлового модуля,__webpack_module_cache__
Используется для кэширования модулей,__webpack_require__
даWebpack
Набор функций импорта зависимостей, реализованных внутри. Последнее предложение является отправной точкой выполнения кода, начиная с входного файла и запуская весь проект.
Из них стоит упомянуть, что__webpack_require__
Функция введения модуля, когда мы разрабатываем модульно, мы обычно используемES Module
илиCommonJS
Спецификация экспорта/импорта зависимых модулей,webpack
При упаковке и компиляции он будет единообразно заменен собственным__webpack_require__
Реализовать импорт и экспорт модулей, реализовать механизм кэширования модулей и сгладить некоторые различия между спецификациями разных модулей.
Вы знаете, что такое sourceMap?
упомянулsourceMap
, многие друзья могут сразу подумать оWebpack
внутри конфигурацииdevtool
параметры и соответствующиеeval
,eval-cheap-source-map
и т.д. необязательные значения и что они означают. Помимо того, что мы знаем разницу между разными параметрами и разницу в производительности, мы также можем узнать об этом вместе.sourceMap
способ реализации.
sourceMap
Это технология, которая отображает скомпилированный, упакованный и сжатый код обратно в исходный код.Поскольку упакованный и сжатый код не читается, как только сообщается об ошибке или возникает проблема во время разработки, она находится непосредственно в запутанном коде.debug
Проблемы могут привести к очень плохому опыту,sourceMap
Это может помочь нам быстро определить местонахождение исходного кода и повысить эффективность нашей разработки.sourceMap
не совсемWebpack
уникальная функция, ноWebpack
служба поддержкиsourceMap
,рисунокJQuery
также поддерживаетsouceMap
.
Поскольку это сопоставление исходного кода, необходимо иметь файл сопоставления, чтобы отметить расположение соответствующего исходного кода в запутанном коде.Обычно этот файл сопоставления начинается с.map
В итоге структура данных внутри выглядит так:
{
"version" : 3, // Source Map版本
"file": "out.js", // 输出文件(可选)
"sourceRoot": "", // 源文件根目录(可选)
"sources": ["foo.js", "bar.js"], // 源文件列表
"sourcesContent": [null, null], // 源内容列表(可选,和源文件列表顺序一致)
"names": ["src", "maps", "are", "fun"], // mappings使用的符号名称列表
"mappings": "A,AAAB;;ABCDE;" // 带有编码映射数据的字符串
}
вmappings
Данные имеют следующие правила:
- Каждая группа строк в make-файле отделяется ";";
- Каждый абзац отделяется ",";
- Каждый сегмент состоит из 1, 4 или 5 полей переменной длины;
С этим файлом сопоставления нам просто нужно добавить этот комментарий в самый конец нашего кода сжатия, чтобы sourceMap вступил в силу:
//# sourceURL=/path/to/file.js.map
С этим комментарием браузер пройдетsourceURL
Чтобы получить этот файл сопоставления, после его синтаксического анализа с помощью интерпретатора реализуйте сопоставление между исходным кодом и запутанным кодом. Таким образом, sourceMap на самом деле является технологией, требующей поддержки браузера.
Если мы внимательно посмотрим на файлы пакетов, упакованные webpack, мы обнаружим, что в файле по умолчаниюdevelopment
В режиме разработки каждый_webpack_modules__
В конце кода файлового модуля будет добавлено//# sourceURL=webpack://file-path?
, чтобы реализовать поддержку sourceMap.
Генерация таблицы сопоставления sourceMap имеет набор относительно сложных правил. Заинтересованные партнеры могут прочитать следующие статьи, которые помогут понять принцип и реализацию sourceMap:
Исследование по принципу Source Map
Исходные карты под капотом — VLQ, Base64 и Yoda
Вы написали Loader? Кратко опишите идею написания загрузчика?
Из приведенного выше кода упаковки мы можем узнать, чтоWebpack
Окончательный упакованный результат представляет собойJavascript
код, на самом деле вWebpack
Внутреннее значение по умолчанию может обрабатывать толькоJS
Код модуля в процессе упаковки по умолчанию будет обрабатывать все встречающиеся файлы какJavaScript
код анализируется, поэтому, когда проект имеет не-JS
При вводе файла нам нужно преобразовать его по мере необходимости, прежде чем приступить к задаче упаковки, которая такжеLoader
наличие механизма.
Loader
Использование конфигурации, с которым мы должны быть хорошо знакомы:
// webpack.config.js
module.exports = {
// ...other config
module: {
rules: [
{
test: /^your-regExp$/,
use: [
{
loader: 'loader-name-A',
},
{
loader: 'loader-name-B',
}
]
},
]
}
}
Из конфигурации видно, что для каждого типа файлаloader
Он поддерживает несколько конфигураций в виде массивов, поэтому, когдаWebpack
При преобразовании этого типа файла каждый вызов будет цепочкой по порядку.loader
,Предыдущийloader
Возвращенный контент будет использоваться в качестве следующегоloader
ввод. следовательноloader
Разработка должна соответствовать некоторым спецификациям, например, возвращаемое значение должно быть стандартным.JS
строка кода, чтобы гарантировать следующийloader
Может работать правильно, и в то же время нужно строго следовать «единой ответственности» в разработке, заботиться только оloader
вывод и соответствующий вывод.
loader
в функцииthis
контекст поwebpack
доступный, черезthis
Связанные свойства, предоставляемые объектом, получают текущийloader
Различные информационные данные, необходимые, по сути, этоthis
указывая наloaderContext
изloader-runner
уникальный объект. Заинтересованные друзья могут прочитать исходный код самостоятельно.
module.exports = function(source) {
const content = doSomeThing2JsString(source);
// 如果 loader 配置了 options 对象,那么this.query将指向 options
const options = this.query;
// 可以用作解析其他模块路径的上下文
console.log('this.context');
/*
* this.callback 参数:
* error:Error | null,当 loader 出错时向外抛出一个 error
* content:String | Buffer,经过 loader 编译后需要导出的内容
* sourceMap:为方便调试生成的编译后内容的 source map
* ast:本次编译生成的 AST 静态语法树,之后执行的 loader 可以直接使用这个 AST,进而省去重复生成 AST 的过程
*/
this.callback(null, content);
// or return content;
}
Более подробную документацию по разработке можно посмотреть прямо на официальном сайтеLoader API.
Вы написали плагин? Кратко опишите идею написания плагина?
если мы предположимLoader
отвечает за преобразование файлов, затемPlugin
Он отвечает за расширение функций.Loader
иPlugin
в видеWebpack
Два важных компонента компании берут на себя две разные обязанности.
Выше было сказано,webpack
На основе модели публикации-подписки в течение рабочего жизненного цикла будет транслироваться множество событий, прослушивая эти события, плагин может выполнять свои собственные задачи плагина на определенном этапе, тем самым реализуя нужные функции.
Поскольку он основан на модели публикации-подписки, то знайтеWebpack
Как упоминалось выше, очень важно, какие обработчики событий предоставляются разработчикам подключаемых модулей.compiler
иcompilation
даWebpack
Два очень важных объекта, из которыхcompiler
подвергается иWebpack
Хуки, связанные со всем жизненным циклом (compiler-hooks),иcompilation
затем предоставляет более детализированные перехватчики событий, связанные с модулями и зависимостями (Compilation Hooks).
Webpack
Механизм события основан наwebpack
самореализуемый наборTapable
Схема потоковой передачи событий (github)
// Tapable的简单使用
const { SyncHook } = require("tapable");
class Car {
constructor() {
// 在this.hooks中定义所有的钩子事件
this.hooks = {
accelerate: new SyncHook(["newSpeed"]),
brake: new SyncHook(),
calculateRoutes: new AsyncParallelHook(["source", "target", "routesList"])
};
}
/* ... */
}
const myCar = new Car();
// 通过调用tap方法即可增加一个消费者,订阅对应的钩子事件了
myCar.hooks.brake.tap("WarningLampPlugin", () => warningLamp.on());
Plugin
развитие и развитиеLoader
Точно так же необходимо соблюдать некоторые нормы и принципы развития:
- Плагин должен быть функцией или включать
apply
объект метода, чтобы вы могли получить доступcompiler
пример; - передается каждому плагину
compiler
иcompilation
Все объекты являются одной и той же ссылкой, если свойства на них изменены в одном плагине, это повлияет на следующие плагины; - Асинхронные события должны вызывать уведомление функции обратного вызова, когда плагин завершает обработку задачи.
Webpack
Войдите в следующий процесс, иначе он зависнет;
Зная вышеизложенное, я хочу разработатьWebpack Plugin
, это не сложно.
class MyPlugin {
apply (compiler) {
// 找到合适的事件钩子,实现自己的插件功能
compiler.hooks.emit.tap('MyPlugin', compilation => {
// compilation: 当前打包构建流程的上下文
console.log(compilation);
// do something...
})
}
}
Более подробную документацию по разработке можно посмотреть прямо на официальном сайтеPlugin API.
Наконец
Эта статья также сочетает в себе несколько отличных статей иwebpack
Исходный код сам по себе примерно описывает несколько относительно важных концепций и процессов, а детали реализации и проектные идеи необходимо читать и медленно понимать вместе с исходным кодом.
Webpack
Являясь отличным инструментом упаковки, он изменил традиционный режим разработки интерфейса и является краеугольным камнем современной разработки интерфейса. У такого превосходного проекта с открытым исходным кодом есть много отличных дизайнерских идей и концепций, на которых можно поучиться.Естественно, мы не должны останавливаться только наAPI
На уровне использования попытка прочитать исходный код с вопросами и понять процесс и принцип реализации также может позволить нам получить больше знаний и глубже понять, чтобы мы могли легко применить их в проекте.