Конфигурация WebPack4 для принципа оптимизации (ON)

Webpack

предисловие

  • Передняя часть процветает и развивается, а инженерия стала одним из обязательных условий для старших передовых инженеров.Развитие упаковки и конструкции началось сgrunt,fis,glupприбытьrollup,webpack,Parcel, технические средства постоянно меняются,

  • Но на самом деле, независимо от технологии или инструмента, есть пять стадий.

    1. Простой в использовании (новичок)
    2. Мастерство (Старая птица)
    3. Понять принцип (эксперт)
    4. Трансформация и оптимизация (Дэниел)
    5. Инновации и трансцендентность (Великий Бог)

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

WebPack теперь находится в интернет-пакете, созданном самым популярным инструментом, а затем давайте посмотрим на него (WebPack ^ 4.42.1)

Прежде всего, давайте разберемся с содержанием этой статьи.

  1. Основная идея

    • Вход
    • вывод (обработка упакованных файлов)
    • загрузчик (обработка различных ресурсов)
    • плагин (с помощью plug-webpack можно расширить и улучшить)
    • Режим (отличительная среда обработки для среды разработки и создания)
  2. Другие распространенные конфигурации

    • devServer (горячее обновление)
    • разрешение (разрешение модуля)
    • оптимизация
    • devtool (отладка исходного кода)
  3. Средства оптимизации

    • анализ статистики
    • анализ скорости
    • Анализ объема
    • tree-shaking
    • scope-hoisting
    • многопроцессная сборка
    • Построить обработку прерываний
    • Параллельное сжатие
    • Предварительно скомпилированные модули ресурсов
    • Улучшить скорость вторичной сборки
    • css встряхивание дерева
    • сжатие изображений веб-пакетом
    • динамическое заполнение
  4. Сводка конфигурации

  5. Принцип вебпака

  6. Написать загрузчик

  7. писать плагин

Представьте один за другим ниже

I. Основные концепции

1.entry (запись упаковки)

Определить упакованную запись

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

Пример использования

// 简写
module.exports = {
    entry: './src/index.js',
}
// 多入口
module.exports = {
    entry: {
        index: './src/index.js',
        list: './src/index.js',
    },
}

2. выход

Связанная конфигурация вывода скомпилированного файла на диск

// 简写
module.exports = {
    output: {
        filename: '[name]_[chunkhash:8].js' //单个文件名可直接指定,多入口利用占位符保证文件名统一
        path: path.join(__dirname, '../dist') // 写入文件磁盘路径
        publicPath: 'http://cdn.example.com/assets/' 
        //资源使用 CDN ,给所有文件引入模版文件时加上路径前缀
    },
}

Заполнитель

  1. [name]
  • имя записи
  1. [id]
  • Внутренний идентификатор чанка, 0,1,2, например.
  1. [hash]
  • Все файлы имеют одинаковое значение хеш-функции, если измененное содержимое не соответствует предыдущему, все значения хеш-функции изменены.
  1. [chunkhash]
  • Разные записи генерируют разные хэши
  • В одном и том же модуле, даже если js и css разделены, значение хеш-функции одинаковое.Если вы измените одно место, значение хеш-функции js и css изменится.
  1. [contenthash]
  • Содержимое файла другое, сгенерированное значение хэша другое
  1. [hash:8]
  • По умолчанию генерируется 20-битный хэш, количество перехватываемых цифр можно настроить

3. загрузчик (преобразование парсинга ресурсов)

Webpack изначально поддерживает только js и json и использует загрузчик для поддержки различных типов файлов и преобразования их в действительные модули. Простой пример

module.exports = {
    module: {
        rules:[
            {
                test: /\/.txt$/, // 指定匹配规则
                use: 'babel-loader' // 指定使用的loader名称
            }
        ]
    }
}

Далее описывается обработка нескольких типов файлов и часто используемых загрузчиков.

  1. Парсинг ES6 и JSX
  • babel-loader: js по умолчанию не поддерживает синтаксис es6 и jsx,
  • .babelrcДокументация: Установка конкретных поддерживаемых методов свойств
{
    test: /\.(j|t)sx?$/,
    use: 'babel-loader',
    exclude: /node_modules/                
},
  1. Разобрать CSS Использовать css файлы в проекте
  • style-loader: передать стиль черезstyleТег вставляется в заголовок файла шаблона
  • css-loader: используется для загрузки файлов .css и преобразования их в объекты commonjs.
      {
        test: /.css$/,
        use: [
          'style-loader',
          'css-loader',
        ],
      },
  1. Разбирать меньше
  • less-loader:less конвертировать в css,
  • Другое то же, что и выше
      {
        test: /.css$/,
        use: [
            'style-loader',
            'css-loader',
            {
                loader: 'less-loader',
                options: { // 可配置属性,修改变量的值,一般利用来修改UI库的主题样式,以下是antd主题样式配置
                    modifyVars: {
                        '@primary-color': '#ec7259',
                    },
                    javascriptEnabled: true,
                },
            },
        ],
      },
  1. Анализ изображений и шрифтов
  • file-loader: Разбор изображений, шрифтов и т. д.
  • url-loader: Может также обрабатывать изображения и шрифты, а также может устанавливать для небольших ресурсов автоматический формат base64.
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: 'static/img/[name].[hash:8].[ext]',// [ext] 文件的后缀名
            },
          },

        ],
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 8192,
          name: 'static/fonts/[name].[hash:8].[ext]',
        },
      },
  1. Адаптация мобильного терминала
  • px2rem-loader: конвертировать px в rem для использования с lib-flexible.
    {
        loader: 'px2rem-loader',
        options: {
            remUnit: 75, // 1rem=多少像素
            remPrecision: 8, // rem的小数点后位数
        }
    }
  1. Завершение префикса CSS
  • postcss-loader: Для адаптации браузера некоторые браузер недвижимости CSS3 не поддерживают необходимость добавления префикса, который автоматически добавляет различные префиксы атрибутов для разных браузеров.
    {
        loader: 'postcss-loader',
        options: {
            plugins: () => [autoprefixer()],
        },
    },

4. плагин (используйте плагины для расширения и улучшения веб-пакета)

  • Решите, что загрузчик не может сделать
  • Поскольку плагины могут содержать параметры/опции,pluginsвходящий атрибутnewпример Простой пример
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    plugin: {
        new webpack.ProgressPlugin(),
        new HtmlWebpackPlugin({template: './src/index.html'}) 
    }
}

Вот некоторые часто используемые плагины

  1. упаковка страницы
    new HtmlWebpackPlugin({
      filename: '../dist/template/index.html', // 指定生成的模版文件名及路径
      template: path.join(__dirname, '../src/template/index.html'), // 指定要使用的模版文件
      inject: true, // 指定的chunk会自动注入html文件中
      chunks: ['index'], //指定生成的html要使用的chunk
      minify: { // 代码的最小化输出
        collapseWhitespace: true, // 删除空格,但是不会删除SCRIPT、style和textarea中的空格
        preserveLineBreaks: false, // 是否保留换行符
        minifyCSS: true, // css压缩
        minifyJS: true, // js压缩
        removeComments: true, // 删除注释,但是会保留script和style中的注释
      },
    }),
  1. очистка файлов
  • Каждый раз, когда вы упаковываете файл в dist, вы должны сначала очистить внутренние файлы dist или удалить папку dist напрямую, чтобы предотвратить дублирование файлов.rimraf dist
  • Но это не элегантный способ, мы можем использовать clean-webpack-plugin, очистить дистрибутив внутренних документов
new CleanWebpackPlugin(),
  1. css зачистки
  • Код css запакован в js файл по умолчанию, но иногда css изменился, а js не изменился, или наоборот, это не способствует кешированию,
  • Мы можем убрать css, чтобы генерировать файлы отдельно для кеширования.
new MiniCssExtractPlugin({
            filename: '[name]_[contenthash:8].css'
        }),
  1. CSS сжатие
  • Так как css вычищается отдельно, необходимо делать сжатие,
new OptimizeCssAsssetePlugin({
    assetNameRegExp: /\.css$/g, //文件匹配
    cssProcessor: require('cssnano') // cssnano 压缩和优化的css插件 
}),
  1. Разделение базовой библиотеки
  • Мы часто выкладываем на cdn какие-то статические ресурсы, которые не сильно меняются, а потом вносим их в файл шаблона
  • Поддержка плагинов также предоставляется в веб-пакете, который можно напрямую настроить и вставить.
  • Если мы разделим реакцию и реакцию-дом

Пример:

const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
    plugins: [
        new HtmlWebpackExternalsPlugin({
            externals:[
                {
                    module: 'react',
                    entry: 'https://cdn.cn/16.8.0/react.min.js',
                    global: 'React',
                },
                {
                    module: 'react-dom',
                    entry: 'https://cdn.cn/16.8.0/react-dom.min.js',
                    global: 'ReactDOM',
                }
            ]
        }),

5. режим (различение среды обработки для среды разработки и среды создания)

  1. режим: соответствует трем атрибутам,
  • development: режим разработки,
  • production: производственный режим,
  • none: без

webpack выполнит некоторую работу по оптимизации непосредственно для различных сред, например, в рабочем режиме,tree-shakingа такжеscope-hostingОптимизация будет подробно описана ниже

2. Общая конфигурация

6. devServer (горячее обновление)

  1. Введение
  • В давние времена, когда мы занимались front-end разработкой, мы писали html-файл и открывали его в браузере для просмотра эффекта, при модификации нам нужно было обновлять его вручную.

  • Позже мы использовали горячее обновление, младшая версия веб-пакета, не поддерживает горячее обновление, мы используем плагины.http-proxy-middlewareа такжеwebpack-hot-middleware, чтобы добиться горячего обновления, конфигурация более неприятно

  • Наконец, webpack интегрирует горячие обновления внутри себя и становится devServer.

Простая конфигурация выглядит следующим образом

  devServer: {
    historyApiFallback: true, // 单页面程序 刷新浏览器会出现404,原因是它通过这个路径(比如: /search/list)来访问后台,所以会出现404,而把historyApiFallback设置为true那么所有的路径都执行index.html

    host: '127.0.0.1', // 域名
    open: true, //支持自动打开浏览器
    hot: true, // 模块热替换,在前端代码变动的时候无需整个刷新页面,只把变化的部分替换掉
    inline: false, // inline选项会为入口页面添加“热加载”功能,即代码改变后重新加载页面
    port: 8080, // 端口
    proxy: proxyConfig._proxy, // 代理后端服务,举例:可本地调试测试接口
    before(app) { // 其他中间件之前, 提供执行自定义中间件
      apiMocker(app, path.resolve('./mocks/mock.js'), // 举例:可用来做mock数据
        proxyConfig._proxy);
    },
  },
  1. принцип

Во-первых, давайте взглянем на простую диаграмму процесса

webpack热更新流程示意图

  • webpack compileСкомпилируйте JS в bundle.js
  • HMR serverЭкспорт файла горячего обновления в среду выполнения HMR, HMR -> HotModuleReplacement (горячая замена модуля)
  • Bundle serverПредоставляет браузеру доступ к файлам
  • HMR RuntimeВнедрите браузер, обновите изменения файла, заставьте браузер и сервер установить связь (веб-сокет)
  • bundle.jsпостроить выходной файл

фаза запуска

  • 1 -> 2 -> 3

  • Исходный код компилируется и упаковывается компилятором webpack.

  • Скомпилированный файл передается на сервер пакетов, который эквивалентен серверу, что делает файл доступным для браузера в виде сервера.

  • files -> webpack Compiler -> Bundle Sever -> bundle.js

этап обновления

  • 1 -> 4 -> 5 -> 6

  • изменения файла файла после компилятора компилятора webpack

  • Скомпилированный файл передается на сервер HMR для уведомления среды выполнения HMR на стороне браузера (обычно передается в формате JSON).

  • Среда выполнения HMR обновляет код для изменения содержимого страницы без обновления

  • files -> webpack Compiler -> HMR server -> HMR Runtime -> code

7. разрешение (разрешение модуля)

  • Установите, как разрешаются модули

Ввести несколько общих атрибутов

  1. aliasСоздайте импорт или требуйте псевдонимы, чтобы упростить импорт модулей
  2. extensionsАвтоматически разрешает определенные расширения
  3. mainFiledsПри импорте модуля из пакета npm решите, какое поле использовать в package.json для импорта модуля.
  4. moudlesСообщите веб-пакету, в каких каталогах он должен искать при разборе модулей

Пример:

// webpack 配置文件
resolve: {
    alias: {
        Util: path.resolve(__dirname, 'src/util/'),
    },
    mainFileds: ['main'],
    extensions: ['.js', '.jsx', '.json'],
    moudles: [path.resolve(__dirname, 'node_modules')]
  },

//业务文件 component.js
import Utility from '../../util/utility.js';
// 简化写法(不用写文件路径前缀,也不用写引用文件的扩展名)
import Utility from 'Util/utility';

8. оптимизация

  • Начиная с webpack 4, в зависимости от выбранного вами режима будут выполняться различные оптимизации, но все оптимизации по-прежнему можно настроить и переписать вручную. Вот некоторые часто используемые оптимизации
  1. Извлечь общедоступные ресурсы
  • Когда в проекте несколько страниц, большинство страниц используют одну и ту же базовую библиотеку или зависимости. В это время каждая страница упаковывается отдельно, что является пустой тратой ресурсов. После упаковки объем большой, а время загрузки страницы долгое. .
  • Таким образом, мы можем извлекать общедоступные ресурсы и упаковывать их отдельно.При доступе к нескольким страницам мы можем использовать механизм кэширования, чтобы загрузить их только один раз для достижения целей оптимизации.
  • splitChunks, вместо предыдущего CommonsChunkPlugin разделение общих ресурсовvendors

Специальное описание атрибута чанков

  • async разделяет файлы, представленные асинхронно (по умолчанию)
  • первоначальное введение разделенной файловой синхронизации
  • all разделяет все совпадающие файлы Синхронный он или асинхронный, мы хотим его разделить, поэтому рекомендуется использовать все
  1. Разделение общедоступных файлов
  • Некоторые файлы класса общедоступных служебных функций, мы можем решить, следует ли их разделить, ограничив количество вызовов.
  • использоватьsplitChunksРазделение общедоступных файловcommons
  1. Список модульных веб-пакетов для извлечения
  • Список информации о модуле будет меняться каждый раз, когда происходит изменение модуля (изменение хэша), поэтому эта часть кода упаковывается отдельно, и с помощью стратегии внутреннего кэширования,
  • Избегайте изменений в модуле, которые могут привести к аннулированию кеша модуля, содержащегося в информации о модуле.
  • конкретное использованиеruntimeChunk

Пример:

  optimization: {
    runtimeChunk: {
      name: 'manifest',
    },
    splitChunks: {
        minSize: 50000 // 分离的包的体积大小
      cacheGroups: {
        vendors: {
          test:  /(react|react-dom)/, //正则匹配要分离的文件
          name: 'vendors',
          chunks: 'all', // 确定对何种引入方式的文件进行分离
          minChunks: 1, // 最小使用的次数
          priority: 10, // 多个缓存组时,需要有优先级排列,优先使用哪个进行分离
        },
        commons: { // 分离公共文件
          name: 'commons',
          chunks: 'all',
          minChunks: 2,
          priority: 5,
        },
      },
    },
  },

9. devtool (отладчик исходного кода)

  • Контролирует, генерировать ли исходную карту и как.
  • Нам нужно сделать конфигурацию, чтобы облегчить обнаружение нашей проблемы в тестовой среде и улучшить отладку исходного кода.

Определение ключевого слова

  • evalМодуль выполняется с помощью пакета Eval(), и это @SourceURL (указание на исходный файл index.js, при отладке по файлу index.js, найденному SourceURL)
  • source mapСоздайте файл .map (этот файл карты создаст сопоставление с исходным файлом, при отладке именно через этот файл .map можно найти местоположение исходного кода)
  • cheapНе содержит информации о столбцах (если есть ошибка в работающем коде, консоль сообщает об ошибке, когда мы нажимаем, чтобы найти конкретный исходный код, мы можем найти только строку, но не конкретный столбец)
  • inlineФайлы .map встраиваются как dataUrl в файл пакета, а не генерируются отдельно.
  • Moudle содержит SourceMap (отлаженный код не будет преобразован, сохранится исходный синтаксис кода)

Комбинация нескольких ключевых слов образует конкретное использование

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

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

Пример

// 开发环境
devtool: 'cheap-module-eval-source-map' // 原始源代码(仅限行)

// 生产环境,一般不进行设置

3. Средства оптимизации

1. Оптимизируйте статистику анализа

построить статистику

Пример использования

// 构建完成后会生成json文件,显示构建的一些信息,时间,各模块的体积等
scripts: {
'build: stats': 'webpack --config build/webpack.prod.config.js --json > stats.json',
}

2. Анализ скорости

  • Анализируйте потребление времени каждым плагином и загрузчиком Пример использования
const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasureWebpackPlugin();
module.exports = smp.wrap(merge(webpackConfigBase, webpackConfigProd));

速度分析示意图

На рисунке мы видим трудоёмкость каждого плагина и загрузчика, Если это занимает много времени, это будет подсказка красным цветом, мы можем проанализировать, почему в этом месте так много времени, и мы можем заменить его другими плагинами для оптимизации скорости сборки.

3. Объемный анализ

  • В виде графического размера более интуитивно понятно видеть объем, занимаемый каждым подключаемым модулем.
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
  plugins: [ 
    new BundleAnalyzerPlugin({ 
      analyzerPort: 8919 //打包构建后体积分析图展示的窗口
      }),
  ],

Запустите команду package, диаграмма анализа объема автоматически откроется в окне 8919.

体积分析示意图

На рисунке видно, что плагин moment занимает много места, и мы можем его оптимизировать

  1. Уменьшенный размер (без учета языковых пакетов)
  • Мы видим, что для поддержки интернационализации, moment содержит много языковых пакетов, мы можем использовать встроенные плагины webpack, чтобы игнорировать его и вводить при необходимости.
new webpack.IgnorePlugin(/\.\/locale/, /moment/),
// compoent
import 'moment/locale/zh-cn';
moment.locale('zh-cn');
  1. заменить плагин
  • Мы можем заменить его более легким плагином dayjs размером всего 2 КБ.

4. tree-shaking

  • Буквально означает встряхивание дерева, то есть стряхивание сломанных листьев с дерева, то есть удаление мертвого кода (т.е. кода, который не используется)
  • Когда используется определенный метод модуля или файла, весь модуль будет упакован в файл пакета, а встряхивание дерева удалит неиспользуемые методы и очистит их на этапе uglify.
  • Поддерживает только синтаксис es6. Настройка производства в webpack 4 включает эту оптимизацию по умолчанию.

Мертвый код (что такое мертвый код?)

  1. код не будет выполнен
  2. Результат выполнения не будет использован
  3. Код влияет только на мертвые переменные

Особенности модуля ES6:

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

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

Статический анализ означает, что код не выполняется, но код анализируется буквально. Например, до модуляризации ES6 мы можем динамически запрашивать модуль. Только после выполнения мы можем знать, на какой модуль ссылаются. Это невозможно сделать с помощью статического анализа. оптимизация, специальные инструкцииimport()Динамический импорт также не поддерживается

5. scope-hoisting

  1. вопрос Существует много кода закрытия после сборки веб-пакета.
  • Большое количество замыканий функций оборачивает код, что приводит к увеличению размера.
  • Область функции при запуске кода, потребляет больше памяти
  1. Пример

ссылочные документыtools.js

export default 'Hello World';

входной файлindex.js

import str from './tools';
console.log(str);

Неоткрытыйscope-hoistingскомпилированный файл


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

/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = ('Hello World');
/***/ })

можно увидеть

  • 0 означает индексный модуль
  • 1 означает модуль инструментов
  • В двух модулях два кода закрытия функции, а в реальной сцене модулей будет больше

включиscope-hoistingскомпилированный файл

/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ var tools = ('Hello World');
console.log(tools);

/***/ })

можно увидеть

  • Объявление функции изменилось с двух на одно, а содержимое, определенное в tools.js, напрямую вводится в соответствующий модуль index.js.
  1. преимущество Использование подъема области видимости
  • Размер кода меньше, потому что оператор объявления функции будет генерировать много кода;
  • Накладные расходы на память также уменьшаются, поскольку код выполняется с меньшим объемом создаваемой функции.
  1. принцип
  • Справочный код для всех модулей в соответствии с порядком, в функции объема,
  • Переименуйте некоторые переменные, чтобы предотвратить конфликты имен.
  1. резюме
  • Эта оптимизация также включена по умолчанию после установки режима производства в webapack4.
  • Использование модулей, отличных от ES6, или использование асинхронного импорта() также не поместит модули в одну и ту же область функций.
  • Следует также отметить, что объединяются только модули, на которые ссылаются один раз, а те, на которые ссылаются несколько раз, разделяются на несколько замыканий для уменьшения избыточности кода.

6. Многопроцессная сборка

  • WebPack Construction - это процесс, включающий чтение и запись файлов. Если проект очень сложен, время строительства будет дольше.
  • И веб-пакет, работающий на nodejs, является однопоточной моделью и может обрабатывать только одну задачу за раз.
  • Можем ли мы сделать webpack многозадачным одновременно?happypackа такжеthread loaderПредоставляет нам решения

Поскольку автор happypack больше не поддерживает этот проект, а принципы у них примерно одинаковые, мы в основном представимthread loader

  • загрузчик потоков предоставляется официальным
  • Загрузчик потока находится вверху и будет выполняться в конце, предыдущий загрузчик будет работать в отдельном пуле рабочих процессов.
  • Каждый работник является отдельным процессом Node.js с пределом 600 мс, тем самым реализуя многопроцессную конструкцию и сокращение времени строительства Пример
  rules: [
    {
      test: /.js$/,
      use: [
        {
          loader: 'thread-loader',
          options: {
            workers: 3, // 产生的 worker 的数量,默认是 cpu 的核心数
          }
        }
      ]
  },
]

Примечание. Загрузчик потоков может быть значительно выделен только тогда, когда проект огромен, если это проект малого и среднего размера, в этом нет необходимости.

отчет журнала

7. Создание исключений, обработка прерываний

  • В процессе построения иногда будут возникать исключения и ошибки построения, мы можем зафиксировать их с помощью некоторых методов и настроить некоторую логику.
  plugins: [
    // 主动捕获构建错误
    function () {
      this.hooks.done.tap('done', (stats) => {
        if (stats.compilation.errors
          && process.argv.indexOf('--watch' == -1)) {
          console.log('error', stats.compilation.errors);
          // 可以做一个构建系统的日志,在此处上报错误原因
          process.exit(12); // 自定义错误code码
        }
      });
    },
  ],

8. Параллельное сжатие

  • рекомендуется использовать webpack4terser-webpack-pluginОткрыть параллель
    • uglify-webpack-pluginПараллельное сжатие также поддерживается, но es6 не поддерживается.Конкретного введения не будет.Заинтересованные студенты могут проверить сами.
    optimization: {
        minimizer: [
            new TerserPluginWebpack({
                parallel: 4, // 开启 不主动指定的话,默认数值是当前电脑cpu数量的2倍减1
            })
        ],
    }

9. Субподряд, предварительная компиляция модулей ресурсов

  1. вопрос Возникла проблема с предыдущим субподрядом
  • Подпакет Externals будет набирать слишком много тегов сценария
  • для пакетирования splitchunk требуется время анализа
  1. решить
  • Предварительно скомпилированные модули ресурсов
  • Упаковать react, react-dom redux и другие базовые пакеты и базовые бизнес-пакеты в один файл
  1. метод
  • dll-pluginсубподряд,
  • dllreferencepluginСсылка на mainfest.json (описание отдельного пакета) для загрузки предварительно скомпилированного модуля в
  • использоватьadd-asset-html-webpack-pluginВставьте сгенерированный файл в шаблон

Пример

// package.json
  "scripts": {
    "dll": "webpack --config build/webpack.dll.js" // 打包前只需执行一次,只要基础包不变则不需要执行
  },
// webpack.dll.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
    entry: { // 指定要分离的包
        library: [ // 基础包
            'react',
            'react-dom',
        ],
    },
    output: {
        filename: "[name]_[hash].dll.js",
        path: path.resolve(__dirname, './library'),
        library: "[name]_[hash]", //包名称 注意此名需和下面的DllPlugin,name名一致
    },
    plugins: [
        new webpack.DllPlugin({
            name: "[name]_[hash]",
            path: path.resolve(__dirname, './library/[name].json')
        })
    ]
}
// webpack.prod.js
plugins: [
  ...
  // 将给定的 JS文件添加到 webpack 配置的文件中,并插入到模版文件中
  new AddAssetHtmlPlugin({
      filepath: path.resolve(__dirname, '../build/library/*.dll.js'),
    }),
  //           
  new webpack.DllReferencePlugin({
      manifest: require('../build/library/library.json')
    }),
]
  1. Суммировать 【1】Сфера применения
  • Пакеты npm указаны, но не изменены 【2】Преимущества:
  • Несколько пакетов, связанных вместе
  • DllPlugin соберет библиотеку, содержащую большое количество повторно используемых модулей, и не будет часто обновляться.Его нужно скомпилировать только один раз, чтобы повысить скорость упаковки.

10. Улучшить скорость после второго билда

  • кеш-плагинhard-source-webpack-plugin
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
  plugins: [
    ...
    new HardSourceWebpackPlugin() 
  ]
]}

Суммировать

  • Хотя DLL обновлена ​​до скорости упаковки, она сложна.
  • а такжеvue-cliа такжеcreate-react-appdll не используется в
  • Поэтому, если вы просто хотите улучшить скорость упаковки, вы можете использоватьhard-source-webpack-pluginзаменятьdll
  • Но если вы хотите поместить несколько пакетов NPM в общедоступный пакет, DLL все еще немного

11. Tree-shaking css (удалить неиспользуемый CSS)

  • Очистить бесполезный код css
  • Ранний PurifyCSSPlugin, его основная функция заключается в удалении неиспользуемого кода CSS, подобно JS Tree Shaking, который больше не поддерживается.
  • Теперь используйте purgecss-webpack-plugin с mini-css-extract-plugin.

Пример

const PATHS = {
    src: path.join(__dirname, '../src')
  }
plugin: [
          new PurgecssPlugin({	
            paths: glob.sync(`${PATHS.src}/**/*`,  { nodir: true }),	// 注意是绝对路径匹配
          }),
]

12. сжатие изображений веб-пакетом

  • Сделать изображение более автоматизированным сжатием
  • imagemin на основе библиотеки узлов
  1. преимущество
  • Поддержка параметров настройки,
  • Могут быть введены сторонние плагины
  • Поддерживает несколько форматов изображений
  1. В частности, загрузчик изображений-webpack Пример
         {
             test: /.(png|jpg|gif|jpeg)$/,
             use: [
                {
                    loader: 'url-loader',
                    options: {
                        limit: 8192,
                        name:'[name]_[hash:8].[ext]'
                    }
                 },
                 {
                    loader: 'image-webpack-loader',
                    options: {
                      mozjpeg: {
                        progressive: true,
                        quality: 65
                      },
                      optipng: {
                        enabled: false,
                      },
                      pngquant: {
                        quality: [0.65, 0.90],
                        speed: 4
                      },
                      gifsicle: {
                        interlaced: false,
                      },
                      webp: {
                        quality: 75
                      }
                    }
                  },
             ],
         },

13 Динамический полифилл-сервис

  1. вопрос
  • На Babel-polyfill приходится большая часть ресурсов при упаковке
  • Может ли он быть загружен по требованию?
  1. polyfill-service
  • Получите агент пользователя браузера, чтобы определить статус поддержки,
  • Возврат характеристик динамического нового браузера не поддерживает
  • https://polyfill.io/v3/polyfill.min.js
  • Вы также можете более свободно настраивать свойства на основе официального самодельного сервиса polyfill (например, указав только уровень поддержки промисов). Напримерhttps://polyfill.alicdn.com/polyfill.min.js?features=Promise
  1. Уведомление
  • Отечественные браузеры многочисленны и сложны, а некоторые браузеры модифицировали агент пользователя в частном порядке, что приводит к неточным суждениям.
  • Мы можем судить об ошибке выполнения, чтобы загрузить обратно все полифиллы и выполнить процесс понижения версии.

4. Сводка конфигурации

Давайте соберем и разберем распространенные конфигурации webpack исходя из реальных целей.

1. Базовая конфигурация

  1. Парсить js
  2. Разобрать css
  3. Разбирать меньше
  4. Разобрать изображение
  5. Разбирать шрифты
  6. завершение префикса
  7. Адаптация мобильного терминала
  8. Очистка каталога
  9. упаковка страницы
  10. css оторваться
  11. Активно перехватывать исключения

2. Улучшить скорость сборки

  1. разрешение сужает поиск файлов
  2. Используйте DllPlugin, чтобы уменьшить количество компиляций основных модулей.
  3. многопроцессорная сборка загрузчика потоков
  4. краткое параллельное сжатие
  5. hard-source-webpack-plugin повышает скорость вторичной сборки
  6. dll субподряд, предварительно скомпилированные модули ресурсов

3. Уменьшенный размер сборки

  1. Разделение государственных ресурсов
  2. Tree Shaking
  3. scope-hoisting
  4. js, css, шрифты, сжатие изображений
  5. Динамический полифилл
  6. css встряхивание дерева
  7. Разделение кода, импорт по запросу, импорт динамической загрузки

4. Улучшите опыт разработки

  1. отладка исходного кода исходной карты
  2. горячее обновление сервера разработки
  3. дружественное сообщение об ошибке

5. Обеспечьте стабильность и безопасность

  1. обфускация сжатия кода

резюме

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

Суммировать

Конечно, в конце концов, мы должны помнить, что все технологии — это всего лишь инструменты, и они должны быть направлены на создание возможностей для бизнеса и создания ценности.

  • Повысить эффективность работы,
  • Улучшить опыт разработки,
  • улучшить пользовательский опыт,
  • Гарантия стабильности и безопасности

оwebpack原理а такжеloader&pluginпожалуйста, посмотриКонфигурация webpack4 по принципу оптимизации (ниже)

Ссылаться на

  1. Играть в WebPack
  2. документация веб-пакета
  3. hard-source-webpack-plugin, альтернатива конфигурации webpack DllPlugin