Говоря об оптимизации производительности веб-пакета (с огромными подробными примечаниями по изучению веб-пакета)

Webpack
Говоря об оптимизации производительности веб-пакета (с огромными подробными примечаниями по изучению веб-пакета)

предисловие

В настоящее время автор занимается обустройствомwebpackСоответствующие точки знаний, с одной стороны, потому что точки знаний, которые я освоил, относительно фрагментарны и недостаточно систематизированы, иногда я не знаю, с чего начать, сталкиваясь с проблемами, с другой стороныwebpack5.0Уже на подходе, это действительно голая новость.

Так что это побудило меня сделать систематический обзорwebpack4.0все очки знаний, включаяwebpackПроисхождение, использование различных конфигураций, оптимизация производительности,WebpackБазовый принцип и анализ конфигурации связанных лесов, рассмотрели волну, общий каталог выглядит следующим образом:

На этот склад автор закинул серию статей:Webpack учится организовывать документы, Заинтересованные студенты могут посмотреть волну.

Сегодняшняя статья также является авторской разборкой и обзором оптимизации производительности в учебном документе.

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

 

Зачем оптимизировать

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

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

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

Представьте себе сценарий, в котором мы внезапно сталкиваемся с чрезвычайной ситуацией.bug, затраты на запуск проекта3/4минут, после изменения проектаbuildонлайн тоже3/4Минуты, на этот раз мозг?duang,duang,duang...

Тогда давайте посмотрим, как оптимизироватьwebpackпроизводительность, улучшитьwebpackскорость построения.

 

инструмент для анализа

Прежде чем начать оптимизацию, нам нужен количественный показатель, чтобы знать, где проблема, влияющая на время сборки.chunkФайл слишком большой или какойloaderилиpluginСлишком долго пришлось ждать.

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

Анализ объема

первичный анализ

можно через официальнуюstat.jsonФайл помогает нам анализировать результаты упаковки,stat.jsonФайл можно быстро сгенерировать с помощью следующего оператора:

webpack --profile --json > stats.json

Затем предоставляем через официальный сайтинструмент анализа stats.jsonанализировать, загрузитьstats.jsonПосле файла вы можете получить результаты анализа, как показано на следующем рисунке:

которая включает в себяwebpackверсия, время упаковки, процесс упаковкиhashстоимость, количество модулей (modules),chunkКоличество, статические файлы упакованных слоевassetsИ количество предупреждений и пакетов ошибок.

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

сторонние инструменты

webpack-bundle-analyzerЭто артефакт анализа упаковки, интерфейс которого очень красив, и он может интуитивно указать размер каждого упакованного файла и его соответствующих зависимостей, что может помочь нам более удобно анализировать проект.

Используйте следующим образом:

// config/webpack.common.js
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

const commonConfig = {
  // ...
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerPort: 8889, // 指定端口号
      openAnalyzer: false,
    }),
  ]
  // ...
}

webpack-bundle-analyzerНижний слой также зависитstat.jsonфайл, черезstat.jsonАнализ, в результате чего в результате окончательного анализа страницы

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

 

анализ скорости

мы можем пройтиspeed-measure-webpack-pluginЭтот плагин помогает нам проанализировать общее время, затрачиваемое на весь пакет, а также на каждыйloaderи каждыйpluginsВремя, необходимое для сборки, что помогает нам быстро определить, где мы можем оптимизироватьWebpackКонфигурация.

Как показано на рисунке выше, время, требующее времени, будет отмечено красным цветом.

использовать

Внедрите этот плагин, чтобы создатьpluginsПримерsmpпакетwebpackФайла конфигурации достаточно, давайте его модифицируемwebpackобщедоступный файл конфигурацииwebpack.common.js:

// config/webpack.common.js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
// ...
module.exports = (production) => {
  if (production) {
    const endProdConfig = merge(commonConfig, prodConfig);
    return smp.wrap(endProdConfig);
  } else {
    const endDevConfig = merge(commonConfig, devConfig);
    return smp.wrap(endDevConfig);
  }
};

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

  • webpack.dev.js: файл конфигурации, используемый средой разработки.
  • webpack.prod.js: файл конфигурации, используемый рабочей средой.
  • webpack.common.js: общедоступный файл конфигурации

После упаковки можно увидеть следующие рендеры:

Уведомление:speed-measure-webpack-pluginдляwebpackАпгрейд недостаточно совершенен, и пока его нельзя установить на собственное крепление.html-webpack-pluginкоторый предоставилhooksобычай наPlugin(add-asset-html-webpack-pluginВот оно) сосуществование, кто-то уже упоминал об этом на githubissue, но, похоже, это не решено.

 

Стратегия оптимизации

После соответствующего анализа объема и анализа скорости мы можем приступить к оптимизации.

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

ЭтоwebpackУниверсальная штукатурка с оптимизированными характеристиками, модернизированная версия, безусловно, принесет улучшение производительности, и улучшение очевидно.

Мы можем увидеть сравнительную таблицу:

Из приведенного выше рисунка мы видим, что,webpack4.0строится намного быстрее, чемwebpack3.0,официал так же сказал,что после апгрейда,после апгрейд версии,можно уменьшить время сборки60% - 98%о.

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

может быть вwebpack5.0После его выхода большинство методов оптимизации производительности, о которых мы говорили сегодня, будут интегрированы вwebpackСамо по себе нам нужно всего несколько простых конфигураций для завершения настройки производительности.

В то же время новая версия инструмента управления пакетами (Npm,Yarn) также может помочь нам быстрее анализировать зависимости и внедрять некоторые пакеты, тем самым повышая скорость упаковки.

Оптимизации, внесенные webpack 4.0

  • v8Оптимизации, внесенные движком (for ofзаменятьforEach,Mapа такжеSetзаменятьObject,includesзаменятьindexOf)
  • Быстрее используется по умолчаниюmd4 hashалгоритм
  • webpack ASTнепосредственно изloaderПерейти кAST, сокращение времени разбора
  • Используйте строковые методы вместо регулярных выражений

мы можемgithubВверхwebpackбиблиотекаИтерация релизовПроверьте оптимизацию производительности, которую он приносит на странице:

Одинv8Пример оптимизации производительности:

Мы можем посмотреть на пример и сравнить использованиеincludesзаменятьindexOfПосле того, как ускорение принесено, создайтеcompare-includes-indexof.jsфайл, создайте10000000Массив длин для записи времени, затраченного двумя функциями:

const ARR_SIZE = 10000000;
const hugeArr = new Array(ARR_SIZE).fill(1);

// includes
const includesTest = () => {
  const arrCopy = [];
  console.time('includes')
  let i = 0;
  while (i < hugeArr.length) {
    arrCopy.includes(i++);
  }
  console.timeEnd('includes');
}

// indexOf
const indexOfTest = () => {
  const arrCopy = [];
  console.time('indexOf');
  for (let item of hugeArr) {
    arrCopy.indexOf(item);
  }
  console.timeEnd('indexOf');
}

includesTest();
indexOfTest();

Его можно найтиincludesнамного быстрее, чемindexOf:

  • includes:12.224ms
  • indexOf:147.638ms

Так что используйте более новые как можно больше в проектеwebpack,Node,Npm,YarnВерсия — это наш первый шаг к повышению скорости упаковки.

 

оптимизация объема

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

сжатие js

webpack4.0По умолчанию сжатие кода поддерживается в производственной среде, т.е.mode=productionрежим.

Фактическиwebpack4.0По умолчанию используетсяterser-webpack-pluginЭтот плагин сжатия, ранее использовавшийсяuglifyjs-webpack-plugin, разница между ними в том, что последний не очень хорош для сжатия ES6, и мы можем включитьparallelпараметр для использования многопроцессорного сжатия для ускорения сжатия.

// config/webpack.common.js
const TerserPlugin = require('terser-webpack-plugin');
// ...
const commonConfig = {
  // ...
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 4, // 开启几个进程来处理压缩,默认是 os.cpus().length - 1
      }),
    ],
  },
  // ...
}

CSS-сжатие

Сжать CSS

мы можем использоватьoptimize-css-assets-webpack-pluginплагин для сжатияcss, по умолчанию используется механизм сжатияcssnano. Конкретное использование заключается в следующем:

// config/webpack.prod.js
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
// ...
const prodConfig = {
  // ...
  optimization: {
    minimizer: [
      new OptimizeCSSAssetsPlugin({
        assetNameRegExp: /\.optimize\.css$/g,
        cssProcessor: require('cssnano'),
        cssProcessorPluginOptions: {
          preset: ['default', { discardComments: { removeAll: true } }],
        },
        canPrint: true,
      })
    ]
  },
}
стереть бесполезноCSS

использоватьPurgeCSSчтобы завершить бесполезноеcssстирания, требуется иmini-css-extract-pluginС использованием.

// config/webpack.common.js
const PurgecssPlugin = require('purgecss-webpack-plugin');
// ...
const PATHS = {
  src: path.join(__dirname, './src')
};

const commonConfig = {
  // ...
  plugins: [
    // ...
    new PurgecssPlugin({
      paths: glob.sync(`${PATHS.src}/**/*`,  { nodir: true }),
    }),
  ]
  // ...
}

Например, до использования этого плагина мы использовали толькоnavcontactЭтот класс, остальные не используются, упаковываем перед введением и находим неиспользуемыеcssОн по-прежнему будет упакован в:

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

Для большего использования вы можете обратиться кPurgeCSS-документация.

Сжатие изображения

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

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

Очень прост в использовании, пока мыfile-loaderприсоединиться послеimage-webpack-loaderТолько что:

// config/webpack.common.js
// ...
module: {
  rules: [
    {
      test: /\.(png|jpg|gif)$/,
      use: [
        {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]',
            outputPath: 'images/',
          }
        },
        {
          loader: 'image-webpack-loader',
          options: {
            // 压缩 jpeg 的配置
            mozjpeg: {
              progressive: true,
              quality: 65
            },
            // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
            optipng: {
              enabled: false,
            },
            // 使用 imagemin-pngquant 压缩 png
            pngquant: {
              quality: '65-90',
              speed: 4
            },
            // 压缩 gif 的配置
            gifsicle: {
              interlaced: false,
            },
            // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
            webp: {
              quality: 75
            }
          }
        }
      ]
    },
  ]
}         
// ...

Давайте пока не будем использовать этоloaderУпакуйте его, размер изображения2.1MB:

использоватьimage-webpack-loaderПосле этого размер изображения666KB:

Эффект сжатия очевиден.

сплит-код

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

или вы также можете использоватьsplitChunksPluginРазделение большого файла на несколько небольших файлов также может эффективно улучшитьwebpackСкорость упаковки, подробное введение в конфигурацию, вы можете прочитать письмо автораНастройка плагина SplitChunks, в котором подробно описано, как настроитьsplitChunks, а использование и значение каждого параметра здесь обсуждаться не будет.

 

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

Поговорив об оптимизации объема упаковки, давайте взглянем на оптимизацию с точки зрения скорости.

Отдельные две конфигурации

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

В процессе разработки: нам нужноwebpack-dev-serverпомочь нам в быстром развитии, нуждаясь вГорячее обновление HMRПомогите нам сделать не требующие обновления изменения на странице, которые находятся вПроизводственная средане требуются.

На этапе производства: нам нужносжатие кода,очистка каталога,Рассчитать хэш,Извлечь CSSтак далее;

Это очень просто реализовать.Как мы уже упоминали ранее, мы создадим три новых.webpackФайл конфигурации сделает:

  • webpack.dev.js: файл конфигурации для среды разработки
  • webpack.prod.js: Файл конфигурации для производственной среды.
  • webpack.common.js: общедоступный файл конфигурации

пройти черезwebpack-mergeдля интеграции общей конфигурации двух файлов конфигурацииwebpack.common.js, подробности см. в исходном коде.

 

Сократите процесс поиска

правильноwebpackизresolveНастройте параметры разумно, используйтеresolveполе рассказываетwebpackКак искать файлы.

добросовестное использованиеresolve.extensions

Если оператор импорта не имеет суффикса файла,webpackОн автоматически добавит суффикс, чтобы попытаться узнать, существует ли файл Порядок запроса соответствует нашей конфигурации.resolve.extensionsИщите по порядку спереди назад,webpackПоддерживаемые суффиксы по умолчанию:jsа такжеjson.

Например 🌰: если мы настроимresolve.extensions= ['js', 'json'],Такwebpackнайдет первымxxx.js

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

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

оптимизацияresolve.modules

Это свойство говоритwebpackКаталог, который следует искать при разборе модулей, можно использовать как абсолютные, так и относительные пути. Использование абсолютных путей будет искать только в заданном каталоге, уменьшая иерархию поиска для модулей:

// config/webpack.common.js
// ...

const commonConfig = {
  // ...
  resolve: {
    extensions: ['.js', '.jsx'],
    mainFiles: ['index', 'list'],
    alias: {
      alias: path.resolve(__dirname, '../src/alias'),
    },
    modules: [
      path.resolve(__dirname, 'node_modules'), // 指定当前目录下的 node_modules 优先查找
      'node_modules', // 将默认写法放在后面
    ]
  },
  // ...
}
// ...
использоватьresolve.aliasСократите процесс поиска

aliasозначаетпсевдоним, который может сопоставить исходный путь импорта с новым путем импорта.

Например, в нашем проекте могут быть какие-то относительные пути, мы можем использоватьaliasнастройка для сокращения процесса поиска;

Также как мы часто используемreactбиблиотеку, на самом деле, мы можем напрямую использовать ееdistУпакованный каталогreact.min.js, чтобы можно было пропустить трудоемкий синтаксический анализ модуля Конкретный пример конфигурации выглядит следующим образом:

// config/webpack.common.js
// ...
const commonConfig = {
  // ...
  resolve: {
    // ...
    alias: {
      react: path.resolve(__dirname, './node_modules/react/dist/react.min.js'),
      @alias: path.resolve(__dirname, '../src/alias'),
    },
  },
  // ...
}
// ...

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

 

Минимизировать цель сборки

исключатьWebpackМодули, которые не нужно разрешать, т.е. использоватьloaderПри его использовании используйте его в как можно меньшем количестве модулей.

мы можем использоватьincludeа такжеexcludeЭти два параметра определяютloaderТолько в тех модулях это применяется и в каких модулях это не.

Модифицируем публичный файл конфигурацииwebpack.common.js:

// config/webpack.common.js
// ...
const commonConfig = {
  // ...
  module: {
    rules: [
      { 
        test: /\.js|jsx$/, 
        exclude: /node_modules/,
        include: path.resolve(__dirname, '../src'),
        use: ['babel-loader']
      },
      // ...
    ]
  },
}
// ...

Сначала не добавляемexcludeа такжеincludeДва параметра, упакуйте егоnpm run build, время упаковки3350msо:

Затем мы добавляем эти два параметра, что означает:

  • exclude: /node_modules/:исключатьnode_modulesфайл ниже
  • include: path.resolve(__dirname, '../src'): ТолькоsrcСледующие файлы используют

Переупакуйте его, время упаковки становится1400msо:

 

Увеличьте скорость сборки с помощью многопоточности

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

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

HappyPack

Принцип: каждый разwebapckразбор модуля,HappyPackназначит его и его зависимостиworkerв теме. После завершения обработки верните обработанные ресурсы вHappyPackосновной процесс для ускорения упаковки.

существуетwebpack4.0используется вhappypackнужно использовать его5.0Версия.

мы будемHappyPackПредставляя общедоступный файл конфигурации, его использование состоит в том, чтобы поместить соответствующийloaderзаменитьhappypack/loader, при заменеloaderв свой плагинloadersвариант, давайте заменим его покаbabel-loader:

// config/webpack.common.js
// ...
const makePlugins = (configs) => {
  const plugins = [
    // ...
    new HappyPack({
      loaders: ['babel-loader']
    }),
  ];
  // ...
  return plugins;
}
// ...

const commonConfig = {
  entry: {
    main: "./src/index.js",
    entry2: "./src/entry2.js",
    entry3: "./src/entry3.js",
    entry4: "./src/entry4.js",
    entry5: "./src/entry5.js",
    entry6: "./src/entry6.js",
  },
  // ...
  module: {
    rules: [{ 
      test: /\.jsx?$/, 
      // exclude: /node_modules/,
      // include: path.resolve(__dirname, '../src'), 
      use: [
        'happypack/loader'
        // 'babel-loader'
      ]
    }]
  },
  // ...
}
// ...

Чтобы сделать эффект более очевидным, добавим в проект еще несколько входных файлов.happypackВ случае с пакетом время составляет около8sмного:

включиhappypackПосле этого мы можем увидеть из консоли,happypackОн у нас включен по умолчанию3процесс, время упаковки становится6.5sо:

Уведомление:HappyPackАвторы этого плагина практически больше не поддерживают этот плагин, так как интерес автора к проекту ослабевает. Он также рекомендовал нам использоватьwebpackофициальныйthread-loader.

Для получения дополнительных параметров вы можете обратиться кОфициальный сайт HappyPack

thread-loader

webpackОфициально запущено многопроцессное решение для заменыHappyPack.

принцип иHappyPackаналогичный,webpackРазбирать по одному модулю за раз,thread-loaderназначит его и его зависимостиworkerВ потоке, чтобы достичь цели мультипроцессной упаковки.

Он очень прост в использовании, прямо вloaderдобавить передthread-loaderХорошо, нам нужно сначала закомментироватьHappyPackКод:

// config/webpack.common.js
// ...
const commonConfig = {
  // ...
  module: {
    rules: [{ 
      test: /\.jsx?$/, 
      // exclude: /node_modules/,
      // include: path.resolve(__dirname, '../src'), 
      use: [
        {
          loader: 'thread-loader',
          options: {
            workers: 3, // 开启几个 worker 进程来处理打包,默认是 os.cpus().length - 1
          }
        },
        'babel-loader'
      ]
    }]
  },
  // ...
}
// ...

Запустим еще раз, это почти то же самое6.5sо:

Предварительно скомпилированные модули ресурсов (DllPlugin)

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

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

Добавить файл конфигурации

Мы находимся в каталоге файла конфигурацииconfigсоздать новыйwebpack.dll.js, этот файл используется для упаковки файлов наших сторонних пакетов вdllПерейдите в папку:

// config/webpack.dll.js
const path = require('path');
const webpack = require('webpack');

module.exports = {
  mode: 'production', // 环境
  entry: {
    vendors: ['lodash'], // 将 lodash 打包到 vendors.js 下
    react: ['react', 'react-dom'], // 将 react 和 react-dom 打包到 react.js 下
  },
  output: {
    filename: '[name].dll.js', // 输出的名字
    path: path.resolve(__dirname, '../dll'), // 输出的文件目录
    library: '[name]' // 将我们打包出来的文件以全部变量的形式暴露,可以在浏览器变量的名字进行访问
  },
  plugins: [
    // 对生成的库文件进行分析,生成库文件与业务文件的映射关系,将结果放在 mainfest.json 文件中
    new webpack.DllPlugin({
      name: '[name]', // 和上面的 library 输出的名字要相同
      path: path.resolve(__dirname, '../dll/[name].manifest.json'),
    })
  ]
}
  • надlibraryна самом деле означает, чтоdllФайл экспортируется в виде глобальной переменной, удобной для последующего обращения, как показано на следующем рисунке:
  • mainfest.jsonФайл — это отношение отображения, его роль — помочьwebpackИспользуйте наши ранее упакованные***.dll.jsфайл вместо повторного переходаnode_modulesнайти в.

Давайте упакуем его в командной строкеdllфайл, вы можете видеть, что корневой каталог генерируетdllпапка, и соответствующие файлы генерируются ниже, иloaderупакованныйvendor.dll.jsсередина,reactа такжеreact-domупакованныйreact.dll.jsбинго:

Затем нам нужно изменить общедоступный файл конфигурацииwebpack.common.js, который мы сгенерировали ранееdllимпорт файла вhtmlпосередине, если мы не хотим вручнуюhtmlфайл для добавленияdllфайл, мы можем использовать плагинadd-asset-html-webpack-plugin, этот плагин, как следует из названия, предназначен для добавления некоторых файлов вhtmlвходить.

При этом нам нужно использоватьwebpackавтономныйDllReferencePluginпара плагиновmainfest.jsonФайлы карты для анализа.

// config/webpack.common.js
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

// ...

const commonConfig = {
  // ...
  plugins: [
    // ...
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, '../dll/vendors.dll.js')
    }),
    new AddAssetHtmlWebpackPlugin({
      filepath: path.resolve(__dirname, '../dll/react.dll.js')
    }),
    new webpack.DllReferencePlugin({
      manifest: require(path.resolve(__dirname, '../dll/vendors.dll.mainfest.json'))
    }),
    new webpack.DllReferencePlugin({
      manifest: require(path.resolve(__dirname, '../dll/react.dll.mainfest.json'))
    }),
  ],
  // ...
}
// ...

Код здесь тоже можно оптимизировать, за подробностями можно обратиться к составленным автором заметкам.оптимизация dllэта секция.

Мы осуществляем упаковку, и мы видим, что время упаковки составляет1450msСлева и справа одновременно видно, что файлы библиотеки упакованы вvendors.chunk.jsдля1.22MB.

мы комментируем правоdllПосле эталонного анализа переупаковки время упаковки составляет1950msвлево и вправо, глядяvendors.chunk.jsдля5.28MB.

Связанный с кешем

Мы можем включить соответствующийloaderилиplugincache для повышения скорости вторичной сборки. Как правило, мы можем сделать следующее:

  • babel-loaderвключить кеш
  • terser-webpack-pluginвключить кеш
  • использоватьcache-loaderилиhard-source-webpack-plugin

Если в проекте есть кеш, вnode_modulesБудет соответствующее.cacheкаталог для хранения соответствующего кеша.

babel-loader

Сначала мы включаемbabel-loaderкеш, модифицируемbabel-loaderпараметр, параметрcacheDirectoryУстановить какtrue:

// config/webpack.common.js
// ...
module: {
  rules: [
    { 
      test: /\.jsx?$/, 
      // exclude: /node_modules/,
      // include: path.resolve(__dirname, '../src'), 
      use: [
        {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true,
          }
        },
      ]
    },
  ]
}         
// ...

Время первой упаковки8.5sили так, после завершения упаковки, мы можем обнаружить, что вnode_modulesсгенерировал.cacheкаталог, в котором хранятсяbabelКэш-файл:

Мы перепаковываем один раз и обнаруживаем, что время становится6sо:

TerserPlugin

Мы проходимTerserPluginсерединаcacheустановить какtrue, вы можете включить кэширование:

// config/webpack.common.js
const TerserPlugin = require('terser-webpack-plugin');
// ...
const commonConfig = {
  // ...
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 4, // 开启几个进程来处理压缩,默认是 os.cpus().length - 1
        cache: true,
      }),
    ],
  },
  // ...
}

Время первой упаковки8-9sвокруг, в то же время.cacheсоздается в каталогеterser-webpack-pluginКаталог кэша:

Мы перепаковываем один раз и обнаруживаем, что время становится5sо:

HardSourceWebpackPlugin

Этот плагин на самом деле используется для обеспечения промежуточного кеша для модулей.

Используйте следующее, мы можем напрямую ввести его в плагин, и это нормально:

// config/webpack.common.js
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
// ...
const plugins = [
  // ...
  new HardSourceWebpackPlugin(),
];
// ...

Давай упакуем, это видно, когда мы упаковываем в первый разHardSourceWebpackPluginПросто помогите нам начать генерировать файлы пакетов, и в то же время.cacheкаталог созданhard-sourceкаталог, требуется время для упаковки в первый раз6.6sо:

Мы перепаковываем один раз и обнаруживаем, что время становится2.7sо:

Разумное использование sourceMap

Мы говорили об этом раньше, до того, как упаковали и сгенерировалиsourceMapКогда информация более подробная, скорость упаковки будет ниже.

Поэтому нам нужно использовать соответствующий код в соответствующей среде в процессе упаковки кода.sourceMapОчень важный.

 

разное

В дополнение к общим методам, которые мы упоминали выше, существуют и другие методы, такие как:

  • использоватьES6 ModulesГрамматика, чтобы обеспечитьTree-Shakingворваться

потому чтоtree-shakingтолько правильноES6 ModulesСтатический импорт вступает в силу для чего-то вродеCommonJsНедопустимый метод динамического импорта

  • добросовестное использованиеPloyfill

Если мы представимpolyfillЕсли не разобраться,Webpackположит всеPolyfillзагружаются, в результате чего выходной файл получается слишком большим. Рекомендуемое использование@babel/preset-envизuseBuiltIns='usage'схема, этот элемент конфигурации поможет нам ввести необходимые прокладки по мере необходимости в соответствии с совместимостью браузера; кроме того, мы также можем использовать динамическиеpolyfillслужбы, каждый раз в соответствии с браузеромUser Agent, отправить разныеPolyfill, вы можете обратиться кpolyfill.io.

  • Предварительно загрузить ресурсыwebpackPrefetch

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

  • iconиспользование изображения классаcss Spriteобъединить фотографии

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

  • html-webpack-externals-plugin

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

  • Разумная конфигурацияchunkхэш-значение

Упаковка в производственной среде, обязательно настроить файлhash, который помогает браузеру кэшировать наши файлы. Когда наш файл кода не изменяется, пользователю нужно только прочитать файл, кэшированный браузером.Вообще говоряjavascriptиспользование файла[chunkhash],cssиспользование файла[contenthash], другие ресурсы (такие как изображения, шрифты и т. д.)[hash].

Больше методов оптимизации производительности автор перечислять не будет, т.к.webpackСуществует слишком много методов оптимизации производительности, и вы можете сформулировать соответствующие схемы оптимизации в соответствии с реальными возникающими проблемами.

 

резюме

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

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

Некоторое содержание статьи вы можете найти в моемWebpack учится организовывать документыНайдите соответствующее введение.

Честно говоря, я хочу комплимент!

 

Ссылки по теме

 

образец кода

Пример кода можно найти здесь: