Дайте webpack5 поработать некоторое время и консолидируйте webpack4 (оптимизация)

Webpack
Дайте webpack5 поработать некоторое время и консолидируйте webpack4 (оптимизация)

Широкое морепользование, небо высоко птицы летать. Эй привет! Я помощник Цинь. 😄

В статье представлена ​​базовая конфигурация WebPack ввода (Портал 🚀🚀🚀). Теперь поговорим о том, как повысить производительность сборки нашего проекта за счет оптимизации элементов конфигурации.

Что следует оптимизировать?

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

  • среда разработки
    • Оптимизировать производительность выполнения кода
    • Оптимизация отладки кода
  • Оптимизация производственной среды
    • Оптимизируйте упаковку кода и скорость сборки
    • Оптимизировать производительность выполнения кода

Оптимизировать производительность выполнения кода (среда разработки)

сервер разработки devServer

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

devServerИспользуется для автоматизации проекта (автоматическая компиляция, автоматическое открытие браузера, автоматическое обновление браузера и т. д.). Он будет скомпилирован и упакован только в памяти и не будет выводиться наружу.buildВместо этого пакет существует в памяти и автоматически удаляется при закрытии.

Запустите сервер разработки, devServer должен загрузить пакет

npm i -D webpack-dev-server

Напишите основные элементы конфигурации сервера

devServer: {
  // 项目构建后路径
  contentBase: resolve(__dirname, 'dist'),
  // 端口号
  port: 3000,
  // 自动打开浏览器
  open: true,
},

После завершения настройки можно запускать проект.webpackЯвляется ли установка размерности проекта, поэтому используйтеnpxбегать

npx webpack 会输出打包结果在dist文件夹
npx webpack-dev-server 只会在内存中编译打包,没有输出

HMR (горячая замена модуля)

HMR: горячая замена модуля Горячая замена модуля / горячая замена модуля, своевременно реагирует на страницу при изменении файла датчика и освобождает F5 для обновления вручную.

Просто установите для параметра hot значение true в devServer, функция HMR будет автоматически включена.

devServer: {
  // 开启HMR功能
  hot: true
}

Файлы поддержки HMR:

  • Файлы стилей: можно использовать функции HMR,style-loaderВнутри функция горячей замены модуля реализована по умолчанию.

  • js: функция HMR не может использоваться по умолчанию

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

// print.js 为入口js之外的js
if (module.hot) {
  // 一旦 module.hot 为true,说明开启了HMR功能。 --> 让HMR功能代码生效
  module.hot.accept('./print.js', function() {
    // 方法会监听 print.js 文件的变化,一旦发生变化,只有这个模块会重新打包构建,其他模块不会。
    // 会执行后面的回调函数
    print();
  });
}
  • html: функция HMR не может использоваться по умолчанию

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

entry: ['./src/index.js', './src/index.html']

Оптимизированная отладка кода (среда разработки)

Извлечь css в отдельный файл

из-заcss-loaderИнтеграция файлов css в файлы js вызовет следующие эффекты:

1: Размер файла js будет очень большим

2: вам нужно сначала загрузить js, а затем динамически создать тег стиля, скорость рендеринга стиля низкая.

Решение: использоватьMiniCssExtractPlugin.loaderзаменятьstyle-loader, извлечь css в js в отдельный файл

нужно представитьmini-css-extract-plugin

npm i -D mini-css-extract-plugin
// webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

{
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../'
            }
          },
        ],
      },
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/main.css'
    }),
  ]
}

css обработка совместимости

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

нужно представитьpostcss-loader postcss-preset-env

npm i -D postcss-loader postcss-preset-env
// webpack.config.js
{
  loader: 'postcss-loader',
  options: {
    ident: 'postcss',
    plugins: () => [
      require('postcss-preset-env')(),
    ],
  },
},

После импорта загрузчика необходимоpackage.jsonопределено вbrowserslist

// package.json

"browserslist": {
  // 开发环境
  "development": [ // 这里可根据具体业务场景,匹配不同浏览器
    "last 1 chrome version",
    "last 1 firefox version",
    "last 1 safari version"
  ],
  // 生产环境
  "production": [ // 满足绝大多数浏览器的兼容
    ">0.2%",
    "not dead",
    "not op_mini all"
  ]
},

js обработка совместимости

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

нужно представитьbabel-loader @babel/preset-env core-js @babel/core

{
  test: /\.js$/,
  exclude: /node_modules/,
  use:[
    {
      loader: 'babel-loader',
      options: {
        presets: [
          [
            '@babel/preset-env',
            {
              //按需加载
              useBuiltIns: 'usage',
              // 指定core-js版本
              corejs:{
                version: 3
              },
              // 指定兼容到什么版本的浏览器
              targets:{
                chrome: '60',
                firefox: '60',
                ie: '9',
                safari: '10',
                edge: '17'
              }
            }
          ]
        ],
        cacheDirectory:true
      }
    }
  ],
},

source-map

source-map: метод, который обеспечивает сопоставление исходного кода с кодом после сборки (если код после сборки идет не так, ошибки исходного кода можно отследить с помощью сопоставления).

параметр:[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

 devtool: 'eval-source-map'

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

С таким количеством режимов, какая комбинация более разумна?

В итоге два лучших решения

1: eval-source-map (высокая целостность, высокая скорость)

2: eval-cheap-module-souce-map (подсказка об ошибке игнорирует столбцы, но содержит другую информацию, быстро)

Настроить проверку стиля кода eslint

Разработка команды, спецификации естественным образом важно. ЛичноeslintЭто слишком строго, и рекомендуется, чтобы команда написала подходящий наборeslintправило.

Здесь представлен набор стилей js, популярных в настоящее время.airbnb Портал 🚀🚀🚀

нужно представитьeslint-loader eslint

// webpack.config.js

{
  test: /\.js$/,
  exclude: /node_modules/, // 忽略node_modules
  loader: 'eslint-loader',
  options: {
    fix: true, // 自动修复
  },
}

После введения загрузчика также необходимоpackage.jsonизeslintConfigнапишите конфигурацию в

// package.json

"eslintConfig": {
  "extends": "airbnb-base", // 继承airbnb的风格规范
  "env": {
    "browser": true // 可以使用浏览器中的全局变量(使用window不会报错)
  }
}

Оптимизация упаковки кода и скорости сборки (производственная среда)

oneOf

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

вавилонский кеш

babel 缓存:БудуbabelОбработанные ресурсы кэшируются, так что во время второй упаковки и сборки обновляется только измененный контент, а другой неизмененный контент кэшируется. тем самым увеличивая скорость сборки

// 开启babel缓存
cacheDirectory:true

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

Обходной путь: используйтеhashИмя, изменив имя файла, чтобы определить, какие файлы необходимо обновить.

Хэш-значение можно разделить на (hash,chunkhash,contenthash)contenthashболее разумный

hash:каждый разwepackПри упаковке создается уникальное хеш-значение.

chunkhash:согласно смодульСгенерированоhashстоимость.隶属于同一个модульизhashто же значение

contenthash: Генерируется из содержимого файлаhashзначение, может гарантировать разные файлыhashценить уникальность

Мультипроцессная упаковка

thread-loaderбудет за этимloaderВключить многопроцессную упаковку.

нужно представитьthread-loader

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

npm i -D thread-loader
{
  loader: 'thread-loader',
  options: {
    workers: 2 // 开启2个进程
  }
},

externals

externalsПусть некоторые сторонние библиотеки не будут упакованы

externals: {
  jquery: 'jQuery'
}

Оптимизация производительности выполнения кода (производственная среда)

Сжатый файл

  • Файл стиля Zip

    нужно представитьoptimize-css-assets-webpack-plugin

      npm i -D optimize-css-assets-webpack-plugin
    
      const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
      plugins: [
        new OptimizeCssAssetsWebpackPlugin(),
      ]
    
  • Сжатый HTML

    нужно представитьhtml-webpack-plugin

    html-webpack-pluginАвтоматически импортирует отдельно упакованные файлы стилей через тег ссылки.

      npm i -D html-webpack-plugin
    
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    plugins: [
      new HtmlWebpackPlugin({
        template: './src/index.html',
        minify: {
          // 移除空格
          collapseWhitespace: true,
          // 移除注释
          removeComments: true
        }
      }),
    ]
    
  • js код будет автоматически сжат в рабочей среде

качание дерева

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

помещение для тряски деревьев

1: Должен использовать модульность es6
2: Откройте производственную среду

В обоих приведенных выше предварительных условиях веб-пакет автоматически удалил наш мертвый код.

Могуpackage.json Записывайте элементы конфигурации, управляйтевстряска дереваОбъем

// 不会对css/less文件tree shaking处理
"sideEffects": ["*.css", "*.less"]

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

webpackУпакуйте код js и выведите его вbuild.jsФайл внутри, что для больших проектов несомненно фатально.build.jsФайл слишком большой, это приведет к тому, что время загрузки страницы будет слишком большим, просто измените немного кода для загрузки больших файлов, и так весь ряд вопросов.

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

Существует три способа реализации разделения кода:

1: мульти-разделенный вход (запись ввода файла с использованием множества входов)

entry: {
  index: './src/js/index.js',
  test: './src/js/test.js'
},
output: {
  filename: 'js/[name].[contenthash:10].js',
  path: resolve(__dirname, 'build')
},

2: настроить оптимизацию

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

3:importСинтаксис динамического импорта

import('./test').then(({ a, b }) => {
  // 文件加载成功~
}).catch(() => {
  // 文件加载失败~
});

ленивая загрузка

Отложенная загрузка: загружайте файл, когда его нужно использовать.

Предварительная загрузка: перед использованием загрузите его заранее

доступныйimportСпособ динамического импорта реализует ленивую загрузку и предварительную загрузку.

// 将import的内容放在异步回调函数中使用,需要用到的时候再进行加载
// webpackPrefetch: true表示开启预加载
import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(() => {
  ...
});

Пока что это об этом для оптимизации WebPack. Резюме здесь не могут быть всеобъемлющими, но для большинства проектов достаточно. Давайте работать вместе, учиться усердно и добиться прогресса каждый день.

Рассыпать цветы, посыпать цветы 🌸🌸🌸🌸🌸🌸🌸🌸

Ставьте 👍 и смотрите снова, уже вошло в привычку! Эта серия постоянно обновляется. Ваша тройная ссылка в один клик - самая большая мотивация для меня продолжать писать. Если у вас есть какие-либо комментарии и предложения по этому блогу, вы можете оставить сообщение! Добро пожаловать, чтобы беспокоить! 😜😝

Я Цинь Эйдэ, программист, который выживает в Интернете!