лучшие практики веб-пакета

внешний интерфейс JavaScript Webpack
лучшие практики веб-пакета

掘金引流终版.gif

Построить запись каталога серии столбцов

Лу Янъян, главный инженер отдела передовых технологий WeDoctor, — тихая соленая рыба.

предисловие

Рекомендации, описанные в этой статье, основаны на повседневной работе и могут не подходить для всех проектов. В конце концов, каждая компания или отдельный проект уникальны, как и лучшие практики. Но вы можете почерпнуть из этой статьи и почерпнуть кое-что полезное.吐槽指正.

чтобы не появляться我这明明可以,你那怎么不行В неловкой ситуации, вот список статей, связанных с номером версии зависимостей.

├── webpack           5.39.1
├── webpack-cli       4.7.2
├── node              12.8.0
├── npm               6.10.2

текст

Инициализировать проект

1. mkdir test-app && cd test-app
2. npm init

Сначала добавьте файл записи/src/index.jsи файл конфигурации веб-пакетаwebpack.config.js, теперь наша структура каталогов выглядит следующим образом

test-app
    ├── src
    |    └── index.js
    ├── package.json
    ├── webpack.config.js

Установить веб-пакет

npm install webpack webpack-cli -D

начать делать вещи

существуетsrc/index.jsнаписать что-нибудь в

class Test {
  constructor() {
    document.writeTest('hello world')
  }
}

new Test()

Давайте сначала создадим пакет, чтобы увидеть, каков эффект, и выполним командуnpx webpack

1.png

Подождав некоторое время, я увидел, что каталог изменился, и добавился новый.distкаталог, в котором находитсяmain.jsдокумент

test-app
  + ├── dist
  + |    └── main.js
    ├── src
    |    └── index.js
    ├── package.json
    ├── webpack.config.js

Давайте посмотримmain.jsчто там

new class{constructor(){document.writeTest("hello world")}};

Вам не нужно пробовать это, это точно не сработает, вам нужно преобразовать код js в es5. Сначала установите егоbabel-loaderи несколько связанных зависимостей

настроить бабел

  • babel-loader
  • @babel/core
  • @babel/preset-env
  • @babel/plugin-transform-runtime
  • @babel/plugin-proposal-decorators
  • @babel/plugin-proposal-class-properties
  • @babel/plugin-proposal-private-methods
  • @babel/runtime
  • @babel/runtime-corejs3
npm install babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime  @babel/plugin-proposal-decorators  @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-methods -D
npm install @babel/runtime @babel/runtime-corejs3 -s

Исправлятьwebpack.config.jsфайл, добавитьbabel-loaderнастроить

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.[contenthash:8].js',
  },
  module: {
    rules: [
      {
        test: /\.(jsx|js)$/,
        use: 'babel-loader',
        exclude: /node_modules/,
      },
    ]
  }
}

Добавьте соответствующий.babelrcконфигурационный файл

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        ["@babel/plugin-transform-runtime", {"corejs": 3}],
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        ["@babel/plugin-proposal-class-properties", { "loose": true }],
        ["@babel/plugin-proposal-private-methods", { "loose": true }]
    ]
}

выполнить команду еще разnpx webpackПриходите и пакуйтесь. Просмотрите структуру каталогов, когда закончите

test-app
    ├── dist
  + |    ├── bundle.b8ba1739.js
    |    ├── main.js
    ├── src
    |    └── index.js
  + ├── .babelrc
    ├── package.json
    ├── webpack.config.js

Посмотреть построенноеbundle.b8ba1739.jsдокумент

(()=>{"use strict";new function n(){!function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),document.writeTest("hello world")}})();

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

Посмотреть эффект в браузере

В качестве аутрич-вечеринки проституируйте плагин прямо из сообществаhtml-webpack-plugin, роль этого плагина заключается в том, чтобы ввести упакованный продукт в заранее подготовленный нами шаблон.htmlВ файле мы можем интуитивно увидеть эффект, обратившись к этому файлу.

Сначала установите плагин

npm install html-webpack-plugin -D

Затем создайтеpublicКаталог, используемый для хранения статических ресурсов. добавить одинindex.htmlШаблоны, размещенные в публичном каталоге

test-app
    ├── dist
    |    ├── bundle.b8ba1739.js
    |    ├── main.js
    ├── src
    |    └── index.js
  + ├── public
  + |    └── index.html
    ├── .babelrc
    ├── package.json
    ├── webpack.config.js

существуетwebpack.config.jsСредняя конфигурацияhtml-webpack-plugin

// 省略 ...
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 省略 ...
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, './public/index.html'),
      inject: 'body',
      scriptLoading: 'blocking',
    }),
  ]
}

выполнить команду еще разnpx webpackПриходите и пакуйтесь. нашел после упаковкиdistеще один в каталогеindex.htmlдокумент. открыть в браузереindex.htmlвидеть правильно

2.png

Как инженер API, даже API может ошибаться.

3.png

изменитьsrc/index.jsкод

class Test {
  constructor() {
    document.write('hello world')
  }
}

new Test()

выполнить команду еще разnpx webpackПриходите и пакуйтесь. Старые шаги, сначала проверьте правильность упакованного продукта

test-app
    ├── dist
    |    ├── bundle.b8ba1739.js
 +  |    ├── bundle.dc044571.js
    |    ├── index.html
    |    ├── main.js
    ├── src
    |    └── index.js
    ├── public
    |    └── index.html
    ├── .babelrc
    ├── package.json
    ├── webpack.config.js

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

4.png

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

Почему говорят, что он самый маленький, ведь пока такая конфигурация в реальной работев основном бесполезен 实用性不大. Внимательные люди это видели, выше три проблемы

  1. Каждый раз, когда вы изменяете код, вы должны пройти процесс упаковки, а затем вручную открыть html-файл для предварительного просмотра эффекта.
  2. Когда API-интерфейс ошибки вызывается в первый раз, местоположение сообщения об ошибке не является точным.
  3. Ниже каталога пакетов上次构建产物Он все еще существует, и со временем бесполезного кода будет все больше и больше.

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

Обновление в реальном времени и эффект предварительного просмотра

По первому пункту см.webpackОфициальный сайт, нашел официальный сайт, чтобы указать четкий путь

5.png

Согласно учебнику на официальном сайте, сначала установитеwebpack-dev-server

npm install webpack-dev-server -D

опять такиwebpack.config.jsДобавьте соответствующую конфигурацию в

// 省略 ...
module.exports = {
  // 省略 ...
  devServer: {
    port: '3001', // 默认是 8080
    hot: true,
    stats: 'errors-only', // 终端仅打印 error
    compress: true, // 是否启用 gzip 压缩
    proxy: {
      '/api': {
        target: 'http://0.0.0.0:80',
        pathRewrite: {
          '/api': '',
        },
      },
    },
  },
}

существуетpackage.json > scriptдобавить команду в

"dev": "webpack serve  --open",

воплощать в жизньnpm run dev, на этот раз он открыт в браузереhttp://localhost:3001/страница. Недостаточно открывать его автоматически, наша цель - менять его каждый раз不用构建в браузере实时查看. Чтобы проверить, работает ли эта функция, мы произвольно модифицируемsrc/index.jsфайл и сохранить. Было обнаружено, что сработало автоматическое обновление контента в браузере.

хочу узнать больше оdevServerможно прочитать следующие две статьи

конфигурация исходной карты

Хорошо на первый вопрос, давайте посмотрим на второй вопрос报错信息定位不精确. Мы все еще ищем на официальном сайте, чтобы узнать, есть ли соответствующее решение. После 1 часа чтения документации и 7 часов рыбалки я наконец нашел решение через день.

мы вwebpack.config.jsдобавить конфигурацию

// 省略 ...
module.exports = {
  // 省略 ...
  devtool: 'eval-cheap-module-source-map',
}

Что означает эта конфигурация, она нам подскажет, что ошибка в原始代码какая линия . Без лишних слов, давайте посмотрим на эффект

6.png

Нажмите, чтобы увидеть, что происходит

28.png

7.png

Такое точное позиционирование можно изменить за один день100Жук.

но! ! ! Это хорошо, и производственную среду нельзя использовать без разбора. предложено здесь

开发环境Лучший: eval-cheap-module-source-map生产环境Лучшее: карта скрытого источника

Какой? Ты болтаешь вверх и вниз, говоря, что лучшее есть лучшее? Мы не поверим без веской причины

8.png

Нельзя распространять слухи, никогда в этой жизни. я тоже впитала в себя эту статьюСтатья на 10 000 слов: О исходной карте, этой статьи достаточноСуть подытожена.

Статья из 10 000 слов состоит из двух предложений, которые можно усвоить за 10 секунд.

9.png

Мир всегда так прекрасен.Согласно приведенным выше идеям, при решении второй проблемы возникает новая проблема.Возможно, некоторые конфигурации должны быть установлены в соответствии с окружающей средой, и различные среды могут быть установлены с соответствующими конфигурациями. как решитьbug AВ процессе появляется новый的 bug B. Кажется, что прежде чем решать третью проблему выше, сначала нужно решить эту区分环境配置эта проблема.

разделенная среда

Как правило, у нас есть开发,测试,预发,生产несколько сред. Но во многих случаях я лично开发а также测试Окружение — это тот же набор настроек, поэтому я просто опускаю его здесь.测试эта среда.

Изменить структуру каталогов

test-app
  + ├── build
  + |    ├── webpack.base.js
  + |    ├── webpack.dev.js
  + |    ├── webpack.pre.js
  + |    ├── webpack.pro.js
    ├── dist
    ├──  ├── bundle.b8ba1739.js
    ├──  ├── bundle.dc044571.js
    |    ├── index.html
    |    ├── main.js
    ├── src
    |    └── index.js
    ├── public
    |    └── index.html
    ├── .babelrc
    ├── package.json

Вы можете увидеть что-то из каталога, мы удалили исходный корневой каталогwebpack.config.jsдокумент. добавилbuildсодержание. существуетbuildВ каталоге нам нужно создатьwebpack.base.jsдокумент. Он используется для хранения общей конфигурации каждой среды, ведь невозможно, чтобы все конфигурации были разными в каждой среде. Затем в соответствии с реальными потребностями наших соответствующих проектов установить файлы конфигурации для различных сред.

Сначала измените общедоступный файл конфигурацииwebpack.base.js. оригинальныйdevServeКонфигурация доступна только в среде разработки;devtoolКаждая среда отличается, поэтому эти две конфигурации удалены из общедоступной конфигурации.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const rootDir = process.cwd();

module.exports = {
  entry: path.resolve(rootDir, 'src/index.js'),
  output: {
    path: path.resolve(rootDir, 'dist'),
    filename: 'bundle.[contenthash:8].js',
  },
  module: {
    rules: [
      {
        test: /\.(jsx|js)$/,
        use: 'babel-loader',
        include: path.resolve(rootDir, 'src'),
        exclude: /node_modules/,
      },
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(rootDir, 'public/index.html'),
      inject: 'body',
      scriptLoading: 'blocking',
    }),
  ],
}

Затем настройте конфигурацию каждой среды, которая в основном используется здесь.webpack-mergeПлагин для объединения общей конфигурации, выполнитьnpm install webpack-merge -D

Исправлятьwebpack.dev.js

const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base');

module.exports = merge(baseConfig, {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map',
  devServer: {
    port: '3001', // 默认是 8080
    hot: true,
    stats: 'errors-only', // 终端仅打印 error
    compress: true, // 是否启用 gzip 压缩
    proxy: {
      '/api': {
        target: 'http://0.0.0.0:80',
        pathRewrite: {
          '/api': '',
        },
      },
    },
  },
});

Потому что здесь нет фактической разработки проекта, поэтому здесь预发а также生产Файлы двух сред сначала настраиваются так, чтобы они были одинаковыми, и вы можете создавать разные конфигурации в соответствии с вашими фактическими потребностями.

  • webpack.pre.js
  • webpack.pro.js
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base');

module.exports = merge(baseConfig, {
  mode: 'production',
  devtool: 'hidden-source-map',
});

Те, кто смотрел внимательно, обнаружили, что в комплектации есть еще одинmodeАтрибуты, это будет объяснено позже, но я не буду говорить об этом здесь.

Измените команду в package.json

  "scripts": {
    "dev": "webpack serve --config build/webpack.dev.js --open",
    "build:pro": "npx webpack --config build/webpack.pro.js",
  },

выполнить сноваnpm run devувидеть эффект

10.png

Вроде все ок, теперь успешно поставилwebpack.config.jsФайл разбит на несколько файлов в зависимости от среды.

Теперь давайте рассмотрим третий вопрос, поднятый ранее.

11.png

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

Удаление артефактов последней сборки при упаковке

Наша цель - удалять последний упакованный продукт каждый раз, когда он упакован, чтобы убедиться, что все файлы в упакованном каталоге новые.После поиска сообществом плагин будет найден.clean-webpack-plugin, взгляните на введение этого плагина

12.png

Мне лень, поэтому я просто сделал скриншот. Старые шаги, сначала установитеnpm install clean-webpack-plugin -DЗатем непосредственно поместите код примера в документацию.借鉴в наш проект. Исправлятьwebpack.base.js

// 省略...
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  // 省略...
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(rootDir, 'public/index.html'),
      inject: 'body',
      scriptLoading: 'blocking',
    }),
    new CleanWebpackPlugin(),
  ],
}

попробуй эффект, выполниnpm run build:proУпакуйте пакет. Посмотреть каталог

test-app
    ├── build
    |    ├── webpack.base.js
    |    ├── webpack.dev.js
    |    ├── webpack.pre.js
    |    ├── webpack.pro.js
    ├── dist
    |    ├── bundle.fd44c2eb.js
    |    ├── bundle.fd44c2eb.js.map
    |    ├── index.html
    ├── src
    |    └── index.js
    ├── public
    |    └── index.html
    ├── .babelrc
    ├── package.json

distсуществующие в каталогеmain.js,bundle.b8ba1739.jsПосле того, как первые несколько продуктов упаковки были автоматически очищены. Здесь также решается третья проблема

Идеальная функция

Добавить css и меньше поддержки

почему бы не добавитьsassслужба поддержки? потому что я не долженsass

Первый вsrcдобавить каталогindex.lessдокумент

.test {
  color: red;
}

Исправлятьsrc/index.jsфайл, обратитесь к только что добавленному файлу в файлеlessдокумент

import './index.less'

class Test {
  constructor() {
    this.renderDiv()
  }

  renderDiv() {
    const div = document.createElement('div')
    div.className = 'test'
    div.innerHTML = 'hello world'
    document.body.appendChild(div)
  }
}

new Test()

воплощать в жизньnpm run dev

Прождав 10 минут страница ничего не загрузилась, открываем консоль и смотрим

13.png

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

Совмещено с инструкцией на официальном сайте

14.png

Тут я, кажется, смутно понялwebpackИстинный смысл:虽然很多时候我不行,但是很多大佬会让我行. Ба, что не так? это называется灵活可插拔, именно эта функция позволяет webpack гибко поддерживать настраиваемые конфигурации для различных сложных сценариев.

Забудьте о бизнесе, раз проблема найдена, решить ее легко, найдите несколько решенийcssа такжеlessЗагрузчик сделает

Сначала установите загрузчик

npm install less style-loader css-loader less-loader -D

Изменить сноваwebpack.base.jsдокумент

// 省略...

module.exports = {
  // 省略...
  module: {
    rules: [
      // 省略...
      {
        test: /\.(le|c)ss$/,
        exclude: /node_modules/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
    ]
  },
  // 省略...
}

выполнить сноваnpm run dev, проверьте эффект

15.png

css module

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

Исправлятьwebpack.base.js

// 省略...

module.exports = {
  // 省略...
  module: {
    rules: [
      //  省略...
      {
        test: /\.(le|c)ss$/,
        exclude: /node_modules/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: {
                compileType: 'module',
                localIdentName: "[local]__[hash:base64:5]",
              },
            },
          },
          'less-loader'
        ]
      },
    ]
  },
  // 省略...
}

воплощать в жизньnpm run devувидеть эффект

16.png

ДатьclassДобавьте хеш-строку после имени стиля, чтобы можно было увидеть конкретную конфигурацию.официальный сайт css-loader

css авто-префикс

Сначала установите плагин

npm install autoprefixer postcss postcss-loader -D

Исправлятьwebpack.base.jsконфигурационный файл

// 省略...
const autoprefixer = require('autoprefixer');

module.exports = {
  // 省略...
  module: {
    rules: [
      // 省略...
      {
        test: /\.(le|c)ss$/,
        exclude: /node_modules/,
        use: [
          // 省略...
          'less-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  ["autoprefixer"],
                ],
              },
            },
          }
        ]
      },
    ]
  },
  // 省略...
}

Извлеките файл css после упаковки

Установить первымmini-css-extract-pluginплагин

npm install mini-css-extract-plugin -D

Исправлятьwebpack.base.jsконфигурационный файл

// 省略...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // 省略...
  module: {
    rules: [
      // 省略...
      {
        test: /\.(le|c)ss$/,
        exclude: /node_modules/,
        use: [
          MiniCssExtractPlugin.loader,
          // 省略...
        ]
      },
    ]
  },
  plugins: [
    // 省略...
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
  ],
}

воплощать в жизньnpm run build:proПроверьте пакет, чтобы увидеть эффект.

17.png

Вы можете видеть, что css был извлечен

Сжать упакованный файл css

Установить первымoptimize-css-assets-webpack-pluginплагин

npm install optimize-css-assets-webpack-plugin -D

Исправлятьwebpack.base.jsконфигурационный файл

// 省略...
const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
  // 省略...
  plugins: [
    // 省略...
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
    new OptimizeCssPlugin(),
  ],
}

воплощать в жизньnpm run build:proПроверьте пакет, чтобы увидеть эффект.

.test__1PSRs{color:red;transition-duration:.4s}

Видно, что css сжат

Скопируйте статические ресурсы в каталог упаковки

Иногда некоторые сторонние плагины js не предоставляют пакеты npm, а предоставляют только адрес CDN или файл, который необходимо загрузить самостоятельно. Обычно мы скачиваем его и кладем себе вpublic/jsкаталог ниже, затемpublic/index.htmlпрямо в файлеscriptЗнакомство с этикеткой. В это время неважноnpm run devПри разработке по-прежнемуnpm run build:proПосле сборки этот файл js не найден. мы можем попробовать

существуетpublic/jsдобавить новыйtest.jsпустой файл, ничего не нужно. затем вpublic/index.htmlимпортировать этот файл

<!DOCTYPE html>
<html lang="en">
  <head>
    // 省略
  </head>

  <body>
    <div id="root"></div>
    <script src="./js/test.js"></script>
  </body>
</html>

воплощать в жизньnpm run devПосмотреть эффект

18.png

Здесь мы можем использоватьcopy-webpack-pluginЭтот плагин после сборки будетpublic/jsскопируйте статические ресурсы вdistкаталог, чтобы файл можно было найти

Установить плагинnpm install copy-webpack-plugin -D

Исправлятьwebpack.base.jsконфигурационный файл

// 省略...
const CopyWebpackPlugin = require('copy-webpack-plugin');

const rootDir = process.cwd();

module.exports = {
  // 省略...
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(rootDir, 'public/index.html'),
      inject: 'body',
      scriptLoading: 'blocking',
    }),
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: '*.js',
          context: path.resolve(rootDir, "public/js"),
          to: path.resolve(rootDir, 'dist/js'),
        },
      ],
    })
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
    new OptimizeCssPlugin(),
  ],
}

воплощать в жизньnpm run devПосмотреть эффект

19.png

Статические файлы уже могут загружаться нормально.

загрузчик ресурсов

Неизбежно внедрение в проект каких-то иконок, картинок и прочих ресурсов.Без какой-либо обработки мы пытаемся ссылаться на картинки в коде и модифицироватьsrc/index.jsФайл выглядит следующим образом

import wuhanjiayou from '../public/asset/a.jpeg'

class Test {
  constructor() {
    this.renderImg()
  }

  renderImg() {
    const img = document.createElement('img')
    img.src = wuhanjiayou
    document.body.appendChild(img)
  }
}

new Test()

воплощать в жизньnpm run devПосмотрите на эффект и сообщите о знакомой ошибке

20.png

Согласно предыдущей процедуре, непосредственно обратитесь к набору из трех частей сообщества.raw-loader,url-loader,file-loader, установить зависимости, настроить зависимости и решить проблему одной операцией. Теперь мы используемwebpack5Это гораздо удобнее, не нужно устанавливать никаких зависимостей, просто модифицировать напрямуюwebpack.base.jsконфигурационный файл

// 省略...
rules: [
    {
        test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
        type: 'asset',
    },
]

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

Конфигурация изменена, выполнитьnpm run devДавайте посмотрим на эффект

21.png

Возьми!

Упомянутого выше в основном достаточно для ежедневных потребностей разработки небольших проектов, и были задействованы часто используемые загрузчики и плагины. Однако, если ваш проект особенно сложен, требования относительно невелики, а у сообщества нет готовых загрузчиков и плагинов для обучения, вы можете только自己动手实现один.

22.png

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

прочитать эту статьюWebpack - шаг за шагом научит вас писать загрузчик/плагинСкоро должно начаться

Оптимизация проекта

Как я только что упомянул, приведенной выше однопроходной операции в основном достаточно для разработки и использования небольшого проекта. Почему маленький проект? Не большой проект? Когда проект достаточно велик для маршрутизации几百个В то время горячее обновление занимало более десяти-двадцати секунд, а пакет — полчаса. При разработке приходится ждать сохранения изменения кода.20 秒, Никто не может выдержать это. В настоящее время нам нужно найти способ оптимизации.

оптимизация конфигурации загрузчика

Собственно это и было сделано выше. Явно указать загрузчику, какие файлы не должны обрабатываться (исключать), а какие файлы следует обрабатывать только (включать).

{
    test: /\.(jsx|js)$/,
    use: 'babel-loader',
    // include: [path.resolve(rootDir, 'src')]
    // exclude: /node_modules/,
  },

обычно предпочитают использоватьinclude, но если вы боитесь пропустить какие-то файлы, грубите и используйтеexclude: /node_modules/Также может.

Эта часть теста была протестирована, и скорость улучшения не очень очевидна.Это должно быть вишенкой на торте.

тайник

Скажи это первымwebpack5Как вы это делали раньше.

использоватьcache-loaderкэшировать результаты на диске; использоватьhard-source-webpack-pluginкэшировать результаты вnode_modules/.cacheУлучшить скорость вторичной упаковки; использоватьDllReferencePluginСторонние библиотеки, которые будут меняться нечасто提前单独Упаковано в библиотеку динамической компоновки для повышения скорости упаковки реального бизнес-кода.

webpack5 поставляется с постоянным кешем, конфигурация следующая

среда разработкиwebpack.dev.js

cache: {
    type: 'memory'
},

Производственная средаwebpack.pro.js

cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename]
    }
},

Этот тест измеряет время упаковки до и после

23.png

24.png

Данные это данные:

  • первый раз:12592 ms
  • второй раз:920 ms

Но я про себя тихо посчитал.Второй пакет около 3 секунд.Мы не знаем,какая логика тайминга у консоли.

25.png

Если во время сборки вы активно решили отказаться от старого кеша, вы можете передать новыйversionпараметр, чтобы отказаться от использования кеша

cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename]
    },
    version: 'new_version'
},

разделение кода

optimization: {
    splitChunks: {
      chunks: 'all',
    }
}

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

Фото взято с официального сайта:

26.png

Проекты у всех могут быть разные, и соответствующая оптимальная конфигурация тоже может быть разной, поэтому вот субсидия на конкретную конфигурацию.Если вам это нужно, вы можете прочитать документацию на официальном сайте, чтобы настроить свой собственный проект.Официальная оптимизация сайта.splitChunks больше настроек,«Webpack» учится разбивать код от 0 до 1

mode

mode: productionОн столько раз появлялся выше, и там конкретно не сказано, какие у него функции. На самом деле при настройкеmode: productionчас,webpackНекоторые меры оптимизации уже включены по умолчанию.

27.png

Некоторые вещи здесь не объясняются одна за другой из-за большого пространства.В любом случае, просто помнитеmode: productionМы сделали для нас ряд оптимизаций.Очень хочется узнать какие оптимизации есть.Нашел статью.Если интересно,можете глянуть.Детали режима

happypack

использоватьhappypackПлагины упакованы в несколько потоков и настроены в соответствии с официальной документацией сайта.

// 省略...
const Happypack = require('happypack');
const os = require('os')
const happyThreadPool = Happypack.ThreadPool({ size: os.cpus().length })

// 省略...
rules: [
  {
    test: /\.(jsx|js)$/,
    // use: 'babel-loader',
    use: 'Happypack/loader?id=js',
    exclude: /node_modules/,
  },
]

plugins: [
    new Happypack({
      id: 'js', // 这个 id 值为上面 Happypack/loader?id=js 问号后跟的参数
      use: ['babel-loader'],
      threadPool: happyThreadPool
    }),
]

Поскольку эта статья написана как демо и не имеет бизнес-кода, время, когда этот пакет в основном не изменилось甚至还多了 1 秒, карта эффекта здесь не будет размещена. Это потому чтоhappypackВыполнение также требует времени, и если проект относительно небольшой, настройка не требуется.jsПосле обработки он должен быть обработанcss, судя по обработкеjsПуть,ctrl+c/ctrl+vиметь дело сcss.

воплощать в жизньnpm run build:pro

ERROR in ./src/index.less
Module build failed (from ./node_modules/Happypack/loader.js):
Error: You forgot to add 'mini-css-extract-plugin' plugin (i.e. `{ plugins: [new MiniCssExtractPlugin()] }`), please read https://github.com/webpack-contrib/mini-css-extract-plugin#getting-started

Ошибка говорит, что я забыл добавитьmini-css-extract-pluginПлагин, но он явно был добавлен.После тестирования выяснилось, что онmini-css-extract-pluginЭтот плагин вызываетhappypackнеправильно. Наконец, после百度,谷歌После ряда уловок я сдался и не нашел решения

尴尬.png

Перед нами три пути:

  • сдатьсяhappypack
  • использоватьhappypackоптимизацияjsа такжеcss, отказаться от использованияmini-css-extract-plugin
  • использоватьhappypackоптимизацияjs, отказаться от оптимизацииcss,Резервmini-css-extract-plugin

Если вы знаете, как решить эту проблему или у вас есть лучший способ, вы можете оставить сообщение ниже и сообщить мне.проституцияУчитесь на этом.

thread-loader

Если вы используете первый из вышеперечисленных, откажитесь от использованияhappypack,Можно использоватьthread-loaderвместо. И эта конфигурация очень проста.

Сначала установите:npm install thread-loader -D, а затем изменить конфигурацию

// 省略...
rules: [
  {
    test: /\.(jsx|js)$/,
    use: ['thread-loader', 'babel-loader'],
    exclude: /node_modules/,
  },
  {
    test: /\.(le|c)ss$/,
    exclude: /node_modules/,
    use: [
      MiniCssExtractPlugin.loader,
      'thread-loader',
      {
        loader: 'css-loader',
        options: {
          modules: {
            compileType: 'module',
            localIdentName: "[local]__[hash:base64:5]",
          },
        },
      },
      'less-loader',
      {
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            plugins: [
              ["autoprefixer"],
            ],
          },
        },
      }
    ],
  },
]

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

использованная литература:

Категории