процесс построения и сортировки webpack

Webpack

Резюме

Функциональность ядра веб-пакета достигается за счет того, что плагин вытащил много, поэтому степень детализации разделения системных функций очень мала, поэтому это идеальное решение, даже в то же время четкое разделение труда, код легче поддерживать. Можно сказать, что это краеугольный камень плагина веб-пакета, который, в свою очередь, влияет на краеугольный камень процесса. Эти хуки связаны строкой Tapable вместе, их можно сравнить с жизненным циклом Vue framework, веб-пакет также имеет свой собственный жизненный цикл, запускает несколько хуков последовательно внутри, монтирует заглушку на этих хуках для выполнения, для выполнения определенной логической обработки. Подключаемый модуль внутри или объекты данных, созданные вне здания, можно подправить, и таким образом получить высокомасштабируемый веб-пакет. Зная это, мы больше не задаемся вопросом, как Webpack может иметь такую ​​богатую экосистему и сообщество, как достичь высокого уровня сегодня.

О компиляторе

CompilerОбъектом является сущность вебпака (экземпляр Tapable), который управляет всем жизненным циклом вебпака, он не выполняет конкретных задач, а лишь выполняет некоторые плановые работы (диспетчеризация войск). Он создает объект «Компиляция», и после выполнения задачи «Компиляция» окончательный результат обработки возвращается Компилятору. На официальном сайте перечислены все крючки, выставленные этим объектом.

О компиляции

CompilationЭто основной исполнитель этапа компиляции (экземпляр Tapable) и объект, выполняющий основные задачи по созданию модуля, сбору зависимостей, разделению и упаковке. На официальном сайте перечислены все крючки, выставленные этим объектом.

Во второй главе мы узнали, что после получения конфигурационных данных запускается метод компилятора.run. На самом деле, перед запуском компилятора в webpack.js мы обнаружим, что выполнили множество операций инициализации, таких как добавление операций по умолчанию, таких как инициализация соответствующих плагинов для различных элементов конфигурации (таких как target, devtool).

Webpack поддерживает передачу нескольких объектов конфигурации.Например, если библиотека имеет несколько целей сборки, необходимо передать несколько объектов конфигурации, и каждый объект конфигурации будет выполнен. Если передается массив, то инициализируется не компилятор, а мультикомпилятор, в конце будет выполнен метод run на мультикомпиляторе, в нем будет пройден объект компилятора, массив компилятора будет сохранен, а затем метод компилятора будет вызываться по очереди.

Compiler

compiler的启动是run方法,run方法里边主要关注两个动作:调用了compile方法;声明了调用compile传入的回调函数onCompiled。
  1. compile()

    Жизненный цикл сборки Webpack включает в себя несколько важных хуков:

    1. Хуки при компиляции: beforeCompile, compile, make (ключевой хук), afterCompile, thisCompilation, компиляция
    2. Крючки на сборку: отделка, печать
      В этом методе параметры, необходимые для создания компиляции, в основном создаются и создается компиляция.Этот параметр является фабричной функцией, необходимой для последующего анализа модуля.
      Хук make является ключевым хуком, при вызове хука make передается вновь созданный объект компиляции, на этот хук монтируется логика обработки некоторых входных плагинов, в этих входных плагинах вызывается Compilation.addEntry(). , управление передается от Компилятора к Компиляции. Крючки Finish и Seal компиляции вызываются в callback-функции хука make.
  2. onCompiled()

    Включает несколько последних важных хуков жизненного цикла сборки веб-пакета: выпустить, выполнить. Этот метод эквивалентен возврату разрешения на компиляцию. Объект компиляции, полученный в это время, представляет собой набор всех файлов ресурсов после синтаксического анализа модуля, обработки загрузчика и компиляции шаблона.
    Этот метод в основном вызывает метод emitAssets, который вызывает ловушку emit (на этом шаге мы можем получить полные данные сборки), получает все данные ресурсов ресурсов, созданные путем компиляции, и рекурсивно вызывает writeOut для записи окончательного файла фрагмента и вызова done. крюк.

Compilation

compilation开始于addEntry方法并结束于addEntry。
  1. addEntry(): 根据入口的配置模式,分为单入口和多入口。该方法里边主要调用了_addModuleChain()。
  2. _addModuleChain(): Создать модуль. В соответствии с вводом используйте различные фабрики модулей (получение от создания компиляции в параметрах, включая ContextModuleFactory или NormalModuleFactory), модули создания, получайте информацию о данных, связанных с Parser, Loader, Hash.
  3. buildModule(): Вызовите module.build(), чтобы построить модуль.
  4. addModuleDependencies(): После успешной сборки зависимые модули рекурсивно получаются и собираются (логика та же, что и у _addModuleChain).
  5. successEntry: После выполнения вышеуказанных операций вызовите хук successEntry в callback-функции _addModuleChain, в котором можно получить только что созданный модуль. Затем верните управление компилятору.

После того, как вышеуказанные этапы завершены, cipiler вызывает методы finish() и seal() компиляции.Здесь мы сосредоточимся на методе уплотнения.

  1. seal(): Основной способ завершения построения чанка. Основной заключается в сборе модулей, чанков, используя шаблон (Шаблон инициализируется при компиляции несколькими буквами в построении: MainTemplate, ChunkTemplate и т.д.) для компилирования чанка. Атрибуты конфигурации модуля ввода входа с использованием MainTemplate, внутри кода будет добавлено, чтобы запустить веб-пакет, многим необходимо создать и обновить хеш-информацию, а вызовы emitAsset () будут конечным файлом ресурсов для сбора всех объектов в активах внутри.
  2. emitAsset(): 收集assets资源数据,多个插件都有调用该方法。

Наклеиваемая модернизация

Чтобы облегчить изучение исходного кода, я хочу получить монтирование и срабатывание хуков во время выполнения вебпака, поэтому Tapable был модифицирован. Главное модифицировать файл Hook.js. Сверху нужно импортировать библиотеку fs.

const fs = require('fs')
  1. Вставьте логику в метод вызова
_fnCp(fn, name, type) {
      const _fn = (...arg) => {
            // console.log('hahaha:', arg)
            fs.writeFileSync('/Users/eleme/Documents/my/test-webpack/calls.js', `${type}: ${name} \n`, { 'flag': 'a' },  () => {})
                  return fn(...arg)
            }
      return _fn
}
// 改造tap、tapAsync、tapPromise方法
tap(options, fn) {
      // ...
      // options = Object.assign({ type: "sync", fn: fn }, options);
      options = Object.assign({ type: "sync", fn: this._fnCp(fn, options.name, "sync") }, options);
      // ...
}
tapAsync(options, fn) {
      // ...
      // options = Object.assign({ type: "async", fn: fn }, options);
      options = Object.assign({ type: "async", fn: this._fnCp(fn, options.name, "async") }, options);
      // ...
}
tapPromise(options, fn) {
      // ...
      // options = Object.assign({ type: "promise", fn: fn }, options);
      options = Object.assign({ type: "promise", fn: this._fnCp(fn, options.name, "promise") }, options);
      // ...
}
  1. Вставьте логику в метод tap
// 改造insert方法,在方法最后插入一条语句
_insert(item){
      fs.writeFileSync('/Users/eleme/Documents/my/test-webpack/taps.js', `${item.type}: ${item.name} \n`, { 'flag': 'a' },  () => {})
}

Суммировать

Пока что мы примерно разобрались с контекстом построения веб-пакетов. Система webpack очень большая, и многие собственные библиотеки webpack инкапсулированы внутри. Цель изучения исходного кода веб-пакета — изучить хорошие идеи построения, а другая — облегчить разработку плагинов в бизнесе.здесьАннотированные версии исходного кода и другие материалы доступны для расширения.