Новые возможности webpack4 под микроскопом: подробное объяснение режима

Node.js внешний интерфейс JavaScript Webpack

Новая функция, поддерживаемая webpack4, — это нулевая конфигурация, которую можно запаковать без конфига, что очень заманчиво для ленивых больных раком, но это также означает, что мы не знаем, что случилось с нулевой конфигурацией, и мы не знаем упакованных файлов. соответствует нашим намерениям, все они упакованы по буддийской системе. Однако, как мать и отец проекта, вы по-прежнему несете ответственность за своих детей, и каждый процесс упаковки должен быть контролируемым. В этой статье подробно объясняется, что происходит с упаковкой webpack в разных режимах.

Давайте посмотрим на параметр MODE, который имеет три параметра.production,development,none, первые два - это плагины с пресетами, а последний - ничего, то есть настроен наnoneЕсли это так, веб-пакет выглядит так, как он выглядит в начале, без каких-либо предустановок, и его необходимо настроить с нуля.

В конфигурации вебпака другие конфигурации могут отсутствовать! Но мод нужен, если не добавить мод, хотя официальный пакет будет запакован, он тоже выдаст предупреждение:

WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: Веб-пакет. Просто .org/concepts/mo…

Смысл очень простой, то есть если режим не установлен, система выдаст вам дефолтныйproductionмодель.

Конфигурация режима очень проста, есть только 3 значения, которые вы можете выбрать.noneЭтот параметр, думаю, всем понятен, далее будем изучать два другихproductionа такжеdevelopment, почему существуют эти два состояния, и что они оба делают в упаковке webpack.

Как отличить в упаковкеproductionа такжеdevelopmentположение дел

в режиме какproductionилиdevelopmentВ состоянии, чтобы учесть работу программы в двух состояниях, webpack создает глобальную переменнуюprocess.env.NODE_ENV, что эквивалентно добавлению в плагин pluginsnew webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development|production") }), используется для различения различных состояний и может различать состояния программы в программе.

Итак, как мы различаем при кодировании? потому чтоprocess.env.NODE_ENVявляется глобальным изменением, поэтому вы можете ссылаться на это значение, предполагая, чтоmode:production:

if ("development" === process.env.NODE_ENV){
    ....
}else{
    ....
}

После компиляции:

if ("development" === "production"){
    ....
}else{
    ....
}

То есть в итоге process.env.NODE_ENV будет заменен на константу. Эта небольшая функция может помочь нам отличить онлайн-версию от версии для разработки при написании бизнес-JS.

noneУпаковка модулей в режиме

Без какой-либо оптимизации, а как быть с модулями, упакованными webpack по умолчанию? Ниже приведен простой пример, мы видим, что он упаковывает модуль в массив, при вызове модуля он напрямую вызывает серийный номер модуля в этом массиве. Тогда нет такой оптимизации, как сжатие и обфускация, и даже комментарии помогают нам хорошо нацеливаться, например importing /* импорт гармонии/, /экспорт гармонии по умолчанию */.

[
    /* 0 */
    (function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    __webpack_require__.r(__webpack_exports__);
    /* harmony import */ var _page2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
    console.log(_page2_js__WEBPACK_IMPORTED_MODULE_0__["default"])
    }),
    /* 1 */
    (function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    __webpack_require__.r(__webpack_exports__);
    let str="page1"
    /* harmony default export */ __webpack_exports__["default"] = (str);
    })
]

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

В режиме разработки webpack выполняет упаковку.

developmentОн сообщает программе, что я сейчас нахожусь в состоянии разработки, то есть упакованный контент должен быть дружественным к разработке. В этом режиме выполняются следующие плагины и больше ничего не делается, поэтому эти плагины можно не использовать.

// webpack.development.config.js
module.exports = {
+ mode: 'development'
- devtool: 'eval',
- plugins: [
-   new webpack.NamedModulesPlugin(),
-   new webpack.NamedChunksPlugin(),
-   new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
- ]
}

Давайте посмотримNamedModulesPluginа такжеNamedChunksPluginЧто делают эти два плагина?Изначально наш веб-пакет не добавлял имя упакованным модулям.Как правило, он основан на серийном номере, начиная с 0, и затем загружая первые несколько модулей. Машине это не важно, поиск загружается быстро, но для человеческого мозга это катастрофа, поэтому в это время добавляйте названия каждому модулю, чтобы облегчить поиск при разработке.

нетNamedModulesPlugin, модуль представляет собой массив, и ссылки также указываются в порядке в массиве.Добавление или вычитание модулей приведет к изменению серийного номера, что по умолчанию является случаем упаковки веб-пакета, см. предыдущий раздел.

имеютNamedModulesPlugin, все модули имеют имена, и все они являются уникальными ключами.Независимо от того, сколько модулей добавляется или вычитается, ключи модулей фиксированы.

{

"./src/index.js":   (function(module, __webpack_exports__, __webpack_require__) {
                        "use strict";
                        __webpack_require__.r(__webpack_exports__);
                        var _page2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/page2.js");
                        console.log(_page2_js__WEBPACK_IMPORTED_MODULE_0__["default"])
                    }),
"./src/page2.js":    (function(module, __webpack_exports__, __webpack_require__) {
                        "use strict";
                        __webpack_require__.r(__webpack_exports__);
                        let str="page1"
                         __webpack_exports__["default"] = (str);
                    })
}

КромеNamedModulesPlugin, есть еще одинNamedChunksPlugin, это чтобы назвать каждый сконфигурированный чанк, исходные чанки также являются массивами без имен.

             Asset      Size  Chunks             Chunk Names
          index.js  4.04 KiB       0  [emitted]  index
          page2.js  3.75 KiB       1  [emitted]  page2
             Asset      Size           Chunks             Chunk Names
          index.js   4.1 KiB            index  [emitted]  index
          page1.js  4.15 KiB            page1  [emitted]  page1

NamedChunksPluginНа самом деле, он предоставляет функцию, с помощью которой вы можете настроить имена чанков.Что делать, если у меня есть одно и то же имя чанка в разных пакетах? В настоящее время необходимо различать, что мы можем использовать все имена зависимых модулей, чтобы добавить имя модуля в эту книгу. потому чтоChunk.modulesУстарело, теперь заменено другими методамиchunk.mapModules, а затем переименуйте фрагмент:

new webpack.NamedChunksPlugin((chunk) => {
    return chunk.mapModules(m => {
        return path.relative(m.context, m.request)
    }).join("_")
}),      

Взглянув на эффект от выполнения этой строки кода, мы увидим, что чанки были переименованы, что может во многом решить проблему с одинаковыми именами чанков:

             Asset      Size             Chunks             Chunk Names
          index.js   4.1 KiB  index.js_page2.js  [emitted]  index
          page2.js  3.78 KiB           page2.js  [emitted]  page2

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

production

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

// webpack.production.config.js
module.exports = {
+  mode: 'production',
-  plugins: [
-    new UglifyJsPlugin(/* ... */),
-    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
-    new webpack.optimize.ModuleConcatenationPlugin(),
-    new webpack.NoEmitOnErrorsPlugin()
-  ]
}

UglifyJsPlugin

Первое, с чем нам нужно разобраться, это обфускация и сжатие JS, сейчас мы попросим об этом.UglifyJsтеперь в вебпаке его зовутconst UglifyJsPlugin = require('uglifyjs-webpack-plugin');, так что вы можете использовать его.

ноnew UglifyJsPlugin(), этот плагин мы можем использовать вoptimizeСредняя конфигурация, эффект тот же, тогда нам не нужно импортировать новый плагин, который замедлит скорость упаковки webpack.

optimization:{
    minimize: true,
},

Удалите плагин, обфусцируйте сжатие и вставьте его вoptimizationТак что скорость WebPack лета. Только первый пакет замедлит, после перепаковки быстро.

ModuleConcatenationPlugin

webpack.optimize.ModuleConcatenationPlugin()Какова роль этого плагина? Официальный документ описывается так:

Помните, что этот плагин работает только с модулями ES6, которые обрабатываются непосредственно webpack. При использовании транспилятора необходимо отключить обработку модулей (например, опцию modules в Babel).

NoEmitOnErrorsPlugin

Последний плагинwebpack.NoEmitOnErrorsPlugin(), это используется, чтобы программа не сообщала об ошибках.Даже если есть ошибка, она будет продолжать компилироваться для меня, что очень жестоко.

others

Есть также некоторые конфигурации плагинов по умолчанию, на которые нельзя ссылаться в плагинах:

flagIncludedChunks

flagIncludedChunksРоль этой конфигурации заключается в том, чтобы увидеть результаты:

Не включено

   Asset       Size  Chunks             Chunk Names
index.js   1.02 KiB       0  [emitted]  index
page1.js  970 bytes       1  [emitted]  page1

Когда включено, если только два файла появляются не очевидно, поэтому я добавил три документа, страницу 1, вызов страницы 2, индекс вызова страницы 1, так что здесь ясно, что все фрагменты идентификатора справочного модуля.

  Asset       Size   Chunks             Chunk Names
index.js   1.08 KiB  0, 1, 2  [emitted]  index
page1.js   1.01 KiB     1, 2  [emitted]  page1
page2.js  971 bytes        2  [emitted]  page2

OccurrenceOrderPlugin

webpack.optimize.OccurrenceOrderPluginЦель этого плагина — упорядочить порядок вхождений в соответствии с количеством ссылок на чанки, потому что это позволяет часто используемым модулям и чанкам иметь меньшие идентификаторы. Запуск приведенного выше примера с этой конфигурацией выглядит следующим образом.

   Asset       Size   Chunks             Chunk Names
page2.js  969 bytes        0  [emitted]  page2
page1.js   1.01 KiB     1, 0  [emitted]  page1
index.js   1.08 KiB  2, 0, 1  [emitted]  index

SideEffectsFlagPlugin

webpack.optimize.SideEffectsFlagPlugin()Чтобы этот плагин вступил в силу, необходимы два условия: одно — импортированный модуль помечен sideEffect, то есть свойство sideEffects в package.json равно false, а второе — текущий модуль ссылается на модуль. без побочных эффектов, и нет никакого побочного эффекта. Тогда при упаковке модуль не будет упакован в файл.

Суммировать

На самом деле, в рабочем режиме, по сравнению с официальной документацией, его конфигурация более эквивалентна следующей конфигурации:

module.exports = {
    mode:"none",
    optimization:{
        flagIncludedChunks:true,
        minimize: true,
    },
    plugins: [
        new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new webpack.NoEmitOnErrorsPlugin(),
        new webpack.optimize.SideEffectsFlagPlugin()
    ]
}

Справочная документация по производственным подключаемым модулям

name effect
FlagDependencyUsagePlugin Отметьте неиспользуемые зависимости.Этот плагин нельзя получить через webpack.Я могу только импортировать его, принудительно импортировав файл класса в webpack/lib.
SideEffectsFlagPlugin Используется для обработки тряски деревьев,tree shaking,sideEffectФункция этого плагина заключается в том, что если на текущий модуль нет ссылки, а sideEffects в package.json имеет значение false, пакет можно удалить при упаковке.Полезные ответы на stackoverflow
FlagIncludedChunksPlugin Добавьте чанкид, содержащийся в текущем чанке, к имени чанка
ModuleConcatenationPlugin повышение масштаба
NoEmitOnErrorsPlugin предотвратить любую ошибку
OccurrenceOrderPlugin Сортировка чанков по количеству звонков
UglifyJsPlugin запутанное сжатие