Лучшее руководство по настройке для веб-пакета

JavaScript

предисловие

Для игроков начального уровня элементов конфигурации веб-пакета много и они тяжелые, поэтому стоит подумать о том, как быстро настроить веб-пакет, который можно использовать в онлайн-среде. На самом деле, ознакомившись с webpack, вы обнаружите, что это очень просто, базовую настройку можно разделить на следующие аспекты:entry,output,mode,resolve,module,optimization,plugin,source map,performanceПодождите, эта статья будет посвящена этим частям.

Прилагается изображение для сравнения нулевой конфигурации веб-пакета, обратите внимание на публичную учетную запись [джентльмен с бутылкой переднего плана] и ответьте [веб-пакет], чтобы получить файл PDF бесплатно.

Сначала настройте запись

1. Однократный и многократный въезд

Добавьте исходные файлы в процесс сборки веб-пакета, который может быть одной записью:

module.exports = {
  entry: `./index.js`,
}

имя пакета сборки[name]дляmain;

или множественная запись:

module.exports = {
  entry: { 
    "index": `./index.js`,
  },
}

key:valueФорма пар ключ-значение:

  • ключ: имя пакета сборки, т.е.[name], здесь дляindex
  • значение: путь входа

Запись определяет, из какого модуля webapck начинает генерировать граф зависимостей (пакет сборки), и каждый файл записи соответствует графу зависимостей.

2. Файл записи динамической конфигурации

Динамически упаковать все подпроекты

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

// 使用 glob 等工具使用若干通配符,运行时获得 entry 的条目
module.exports = {
  entry: glob.sync('./project/**/index.js').reduce((acc, path) => {
    const entry = path.replace('/index.js', '')
    acc[entry] = path
    return acc
  }, {}),
}

будет соответствовать всем./project/**/index.jsФайлы упакованы как входные файлы.Если вы хотите добавить подпроект, простоprojectСоздайте каталог подпроекта и создайтеindex.jsкак входной файл.

Этот метод более подходит для сценариев, где входные файлы не сосредоточены, и много.

Динамически упаковать подпроект

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

npm run build --project components

Разобрать аргументы командной строки при упаковке:

// 解析命令行参数
const argv = require('minimist')(process.argv.slice(2))
// 项目
const project = argv['project'] || 'index'

Затем настройте запись:

module.exports = {
  entry: { 
    "index": `./${project}/index.js`,
  } 
}

эквивалентно:

module.exports = {
  entry: { 
    "index": `./components/index.js`,
  } 
}

Конечно, вы можете передать другие параметры, которые также можно применять в нескольких местах, напримерresolve.aliasсередина.

2. Настройте вывод экспорта

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

module.exports = {
  output: { 
    // path 必须为绝对路径
    // 输出文件路径
    path: path.resolve(__dirname, '../../dist/build'),
    // 包名称
    filename: "[name].bundle.js",
    // 或使用函数返回名(不常用)
    // filename: (chunkData) => {
    //   return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js';
    // },
    // 块名,公共块名(非入口)
    chunkFilename: '[name].[chunkhash].bundle.js',
    // 打包生成的 index.html 文件里面引用资源的前缀
    // 也为发布到线上资源的 URL 前缀
    // 使用的是相对路径,默认为 ''
    publicPath: '/', 
  }
}

В режиме разработки webpack4 он запустится по умолчанию.output.pathinfo, который выводит дополнительную информацию в комментариях, полезную для отладки проекта, особенно при использовании eval devtool.

filename:[name]настроен для входаkey, в дополнение к этому, также может быть[id](внутренний идентификатор блока),[hash],[contenthash]Ждать.

1. Кэш браузера и хэш-значение

Для каждого приложения, которое мы разрабатываем, браузер кэширует статические ресурсы.Если мы обновляем статические ресурсы без обновления имени статического ресурса (или пути), браузер может не получить обновленные ресурсы из-за проблем с кэшированием. Когда мы используем webpack для упаковки, webpack предоставляет концепцию хэша, поэтому мы можем использовать хэш для упаковки.

После определения имени пакета (например,chunkFilename,filename), мы обычно используем хеш-значения, и в разных сценариях используются разные хеш-значения:

hash

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

chunkhash

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

contenthash

Content-Specific, в соответствии с хэш-значением, рассчитанным в соответствии с содержимым, если содержимое пакета является постоянным,contenthashне изменится,Подходит для производственной среды

webpack также позволяет нарезать хэши. если ты напишешь[hash:8], то он получает первые 8 бит хеша.

Уведомление:
  • Попробуйте использовать хэши в продакшене
  • Блоки, загружаемые по требованию, не подлежатfilenameзатронутыйchunkFilenameвлияние
  • использоватьhash/chunkhash/contenthashобычно сотрудничаютhtml-webpack-plugin(создайте html и свяжите соответствующий файл пакета),clean-webpack-plugin(чтобы очистить исходный файл пакета) используются вместе.

2. Упакован в виде библиотеки

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

module.exports = {
  output: { 
    // path 必须为绝对路径
    // 输出文件路径
    path: path.resolve(__dirname, '../../dist/build'),
    // 包名称
    filename: "[name].bundle.js",
    // 块名,公共块名(非入口)
    chunkFilename: '[name].[chunkhash].bundle.js',
    // 打包生成的 index.html 文件里面引用资源的前缀
    // 也为发布到线上资源的 URL 前缀
    // 使用的是相对路径,默认为 ''
    publicPath: '/', 
    // 一旦设置后该 bundle 将被处理为 library
    library: 'webpackNumbers',
    // export 的 library 的规范,有支持 var, this, commonjs,commonjs2,amd,umd
    libraryTarget: 'umd',
  }
}

Три, режим режима конфигурации (webpack4)

настраиватьmode, что позволяет веб-пакету автоматически вызывать соответствующие встроенные оптимизации.

module.exports = {
  // 可以是 none、development、production
  // 默认为 production
  mode: 'production'
}

Или настройте его в командной строке:

"build:prod": "webpack --config config/webpack.prod.config.js --mode production"

в обстановкеmodeПосле этого webpack4 выполнит синхронизацию конфигурацииprocess.env.NODE_ENVдляdevelopmentилиproduction.

Наиболее примечательные особенности webpack4:

  • Сокращение времени компиляции

    Время упаковки сократилось более чем на 60%

  • Нулевая конфигурация

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

webpack4 поддерживает нулевую конфигурацию, где нулевая конфигурация означает,modeтак же какentry(по умолчаниюsrc/index.js) можно указать через файл ввода, а webpack4 нацелен на разныеmodeВстроенные соответствующие стратегии оптимизации.

1. production

Конфигурация:

// webpack.prod.config.js
module.exports = {
  mode: 'production',
}

Эквивалент встроенного по умолчанию:

// webpack.prod.config.js
module.exports = {
  performance: {
    // 性能设置,文件打包过大时,会报警告
    hints: 'warning'
  },
  output: {
    // 打包时,在包中不包含所属模块的信息的注释
    pathinfo: false
  },
  optimization: {
    // 不使用可读的模块标识符进行调试
    namedModules: false,
    // 不使用可读的块标识符进行调试
    namedChunks: false,
    // 设置 process.env.NODE_ENV 为 production
    nodeEnv: 'production',
    // 标记块是否是其它块的子集
    // 控制加载块的大小(加载较大块时,不加载其子集)
    flagIncludedChunks: true,
    // 标记模块的加载顺序,使初始包更小
    occurrenceOrder: true,
    // 启用副作用
    sideEffects: true,
    // 确定每个模块的使用导出,
    // 不会为未使用的导出生成导出
    // 最小化的消除死代码
    // optimization.usedExports 收集的信息将被其他优化或代码生成所使用
    usedExports: true,
    // 查找模块图中可以安全的连接到其它模块的片段
    concatenateModules: true,
    // SplitChunksPlugin 配置项
    splitChunks: {
      // 默认 webpack4 只会对按需加载的代码做分割
      chunks: 'async',
      // 表示在压缩前的最小模块大小,默认值是30kb
      minSize: 30000,
      minRemainingSize: 0,
      // 旨在与HTTP/2和长期缓存一起使用 
      // 它增加了请求数量以实现更好的缓存
      // 它还可以用于减小文件大小,以加快重建速度。
      maxSize: 0,
      // 分割一个模块之前必须共享的最小块数
      minChunks: 1,
      // 按需加载时的最大并行请求数
      maxAsyncRequests: 6,
      // 入口的最大并行请求数
      maxInitialRequests: 4,
      // 界定符
      automaticNameDelimiter: '~',
      // 块名最大字符数
      automaticNameMaxLength: 30,
      cacheGroups: { // 缓存组
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    },
    // 当打包时,遇到错误编译,将不会把打包文件输出
    // 确保 webpack 不会输入任何错误的包
    noEmitOnErrors: true,
    checkWasmTypes: true,
    // 使用 optimization.minimizer || TerserPlugin 来最小化包
    minimize: true,
  },
  plugins: [
    // 使用 terser 来优化 JavaScript
    new TerserPlugin(/* ... */),
    // 定义环境变量
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
    // 预编译所有模块到一个闭包中,提升代码在浏览器中的执行速度
    new webpack.optimize.ModuleConcatenationPlugin(),
    // 在编译出现错误时,使用 NoEmitOnErrorsPlugin 来跳过输出阶段。
    // 这样可以确保输出资源不会包含错误
    new webpack.NoEmitOnErrorsPlugin()
  ]
}

2. development

Конфигурация:

// webpack.dev.config.js
module.exports = {
  mode: 'development',
}

Эквивалент встроенного по умолчанию:

// webpack.dev.config.js
module.exports = {
  devtool: 'eval',
  cache: true,
  performance: {
    // 性能设置,文件打包过大时,不报错和警告,只做提示
    hints: false
  },
  output: {
    // 打包时,在包中包含所属模块的信息的注释
    pathinfo: true
  },
  optimization: {
    // 使用可读的模块标识符进行调试
    namedModules: true,
    // 使用可读的块标识符进行调试
    namedChunks: true,
    // 设置 process.env.NODE_ENV 为 development
    nodeEnv: 'development',
    // 不标记块是否是其它块的子集
    flagIncludedChunks: false,
    // 不标记模块的加载顺序
    occurrenceOrder: false,
    // 不启用副作用
    sideEffects: false,
    usedExports: false,
    concatenateModules: false,
    splitChunks: {
      hidePathInfo: false,
      minSize: 10000,
      maxAsyncRequests: Infinity,
      maxInitialRequests: Infinity,
    },
    // 当打包时,遇到错误编译,仍把打包文件输出
    noEmitOnErrors: false,
    checkWasmTypes: false,
    // 不使用 optimization.minimizer || TerserPlugin 来最小化包
    minimize: false,
    removeAvailableModules: false
  },
  plugins: [
    // 当启用 HMR 时,使用该插件会显示模块的相对路径
    // 建议用于开发环境
    new webpack.NamedModulesPlugin(),
    // webpack 内部维护了一个自增的 id,每个 chunk 都有一个 id。
    // 所以当增加 entry 或者其他类型 chunk 的时候,id 就会变化,
    // 导致内容没有变化的 chunk 的 id 也发生了变化
    // NamedChunksPlugin 将内部 chunk id 映射成一个字符串标识符(模块的相对路径)
    // 这样 chunk id 就稳定了下来
    new webpack.NamedChunksPlugin(),
    // 定义环境变量
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
  ]
}

3. none

Никаких опций оптимизации по умолчанию не делается.

Конфигурация:

// webpack.com.config.js
module.exports = {
  mode: 'none',
}

Эквивалент встроенного по умолчанию:

// webpack.com.config.js
module.exports = {
  performance: {
   // 性能设置,文件打包过大时,不报错和警告,只做提示
   hints: false
  },
  optimization: {
    // 不标记块是否是其它块的子集
    flagIncludedChunks: false,
    // 不标记模块的加载顺序
    occurrenceOrder: false,
    // 不启用副作用
    sideEffects: false,
    usedExports: false,
    concatenateModules: false,
    splitChunks: {
      hidePathInfo: false,
      minSize: 10000,
      maxAsyncRequests: Infinity,
      maxInitialRequests: Infinity,
    },
    // 当打包时,遇到错误编译,仍把打包文件输出
    noEmitOnErrors: false,
    checkWasmTypes: false,
    // 不使用 optimization.minimizer || TerserPlugin 来最小化包
    minimize: false,
  },
  plugins: []
}

4. Резюме производства, разработки, нет

Примечание. Обратите внимание на общедоступную учетную запись [Front-end Bottle King] и ответьте на [webpack], чтобы получить исходный pdf-файл бесплатно.

Дайте вам лучший пользовательский опыт в производственном режиме:

  • Меньший размер выходного пакета
  • Более быстрое выполнение кода в браузере
  • Игнорировать код в разработке
  • Не раскрывайте исходный код или пути к файлам
  • Простые в использовании ресурсы вывода

Режим разработки даст вам лучший опыт разработки:

  • Инструменты отладки браузера
  • Быстрая инкрементная компиляция ускоряет циклы разработки
  • Предоставляет полезные сообщения об ошибках во время выполнения

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

5. Переменная окружения process.env.NODE_ENV

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

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

Способ 1: режим: «производство» в webpack4 настроено с помощью process.env.NODE_ENV = «производство» по умолчанию, поэтому webapck4 не может быть определен

Хотя определено в webpack4modeбудет автоматически настроенprocess.env.NODE_ENV, то нам не нужно вручную настраивать переменные окружения?

вообще-то нет,modeможно определить только какdevelopmentилиproduction, и в проекте у нас есть не только среда разработки или производства, но во многих случаях нам нужно настроить разные среды (например, тестовую среду), в это время нам нужно вручную настроить другие переменные среды (такие как тестовая среду, нам нужно определитьprocess.env.NODE_ENVдля'test'), вы можете сделать следующее:

Способ 2: webpack.DefinePlugin

// webpack编译过程中设置全局变量process.env
new webpack.DefinePlugin({
  'process.env': require('../config/dev.env.js')
}

config/prod.env.js:

module.exports ={
  // 或  '"production"' ,环境变量的值需要是一个由双引号包裹的字符串
  NODE_ENV: JSON.stringify('production') 
}

Способ 3: когда команда веб-пакета NODE_ENV=development

Настроить в окнеNODE_ENV=productionМожет застрять, поэтому используйте cross-env:

cross-env NODE_ENV=production webpack --config webpack.config.prod.js

Способ 4: Использованиеnew webpack.EnvironmentPlugin(['NODE_ENV'])

EnvironmentPluginпропускwebpack.DefinePluginустанавливатьprocess.envЯрлыки для переменных среды.

new webpack.EnvironmentPlugin({
  NODE_ENV: 'production',
});

Примечание: приведенное выше фактически даетNODE_ENVУстановите значение по умолчанию'production', если определено в другом местеprocess.env.NODE_ENV, значение по умолчанию недопустимо.

В-четвертых, настройте стратегию разрешения

Настройте стратегию поиска зависимых модулей (например,import _ from 'lodash'):

module.exports = {
  resolve: {
    // 设置模块导入规则,import/require时会直接在这些目录找文件
    // 可以指明存放第三方模块的绝对路径,以减少寻找,
    // 默认 node_modules
    modules: [path.resolve(`${project}/components`), 'node_modules'],
    // import导入时省略后缀
    // 注意:尽可能的减少后缀尝试的可能性
    extensions: ['.js', '.jsx', '.react.js', '.css', '.json'],
    // import导入时别名,减少耗时的递归解析操作
    alias: {
      '@components': path.resolve(`${project}/components`),
      '@style': path.resolve('asset/style'),
    },
    // 很多第三方库会针对不同的环境提供几份代码
    // webpack 会根据 mainFields 的配置去决定优先采用那份代码
    // 它会根据 webpack 配置中指定的 target 不同,默认值也会有所不同
    mainFields: ['browser', 'module', 'main'],
  },
}

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

Решите, как обрабатывать различные типы модулей в вашем проекте, обычно путем настройки загрузчиков в module.rules:

module.exports = {
  module: {
    // 指明 webpack 不去解析某些内容,该方式有助于提升 webpack 的构建性能
    noParse: /jquery/,
    rules: [
      {
        // 这里编译 js、jsx
        // 注意:如果项目源码中没有 jsx 文件就不要写 /\.jsx?$/,提升正则表达式性能
        test: /\.(js|jsx)$/,
        // 指定要用什么 loader 及其相关 loader 配置
        use: {
          loader: "babel-loader",
          options: {
            // babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启
            // 使用 cacheDirectory 选项将 babel-loader 的速度提高2倍
      		cacheDirectory: true,
      		// Save disk space when time isn't as important
      		cacheCompression: true,
      		compact: true,     
          }
        },
        // 排除 node_modules 目录下的文件
        // node_modules 目录下的文件都是采用的 ES5 语法,没必要再通过 Babel 去转换
        exclude: /node_modules/
        // 也可以配置 include:需要引入的文件
      }
    ]
  }
}

1. noParse

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

2. rules

Обычные загрузчики:

  • babel-loader: разбор.js а также .jsxдокумент

    // 配置 .babelrc
    {
      "presets": [
        [
          "@babel/preset-env",
        ],
        "@babel/preset-react"
      ],
      "plugins": [
        [
          "@babel/plugin-proposal-class-properties",
          {
            "loose": true
          }
        ],
        [
          "@babel/plugin-transform-runtime",
          {
            "absoluteRuntime": false,
            "corejs": false,
            "helpers": true,
            "regenerator": true,
            "useESModules": false
          }
        ],
      ]
    }
    
  • tsx-loader: Обработать файлы ts

  • less-loader: Обрабатывать меньше файлов и компилировать их в css

  • sass-loader: Обрабатывать файлы sass, scss и компилировать их в css.

  • postcss-loader:

    // postcss.config.js
    module.exports = { // 解析CSS文件并且添加浏览器前缀到 CSS 内容里
    	plugins: [require('autoprefixer')],
    };
    
  • css-loader: обрабатывать css-файлы

  • style-loader: внедрить CSS в DOM

  • file-loader: положить файл наimport / requireрешаетurl, и выведите файл в выходной каталог

  • url-loader: загрузчик webpack для преобразования файлов в base64 uri

  • html-loader: экспортировать HTML в виде строки, минимизировать HTML, когда компилятор запрашивает это.

Другие загрузчики для просмотраLOADERS.

Шесть, оптимизация оптимизации конфигурации (webpack4)

webapck4 будетmodeЧтобы оптимизировать, вы можете настроить его вручную, он переопределит автоматическую оптимизацию, пожалуйста, обратитесь к подробной настройкеOptimization.

В основном это включает два аспекта оптимизации:

  • Свернутый пакет
  • Распаковка

1. Минимизируйте пакет

  • использоватьoptimization.removeAvailableModulesУдалить доступные модули
  • использоватьoptimization.removeEmptyChunksудалить пустые модули
  • использоватьoptimization.occurrenceOrderОтметьте порядок загрузки модулей, чтобы уменьшить исходный пакет.
  • использоватьoptimization.providedExports,optimization.usedExports,concatenateModules,optimization.sideEffectsудалить мертвый код
  • использоватьoptimization.splitChunksИзвлечь общедоступные пакеты
  • использоватьoptimization.minimizer || TerserPluginминимизировать пакет

2. Распаковка

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

Сплит Node_Modules.

Во многих случаях нам не нужно вручную разбивать пакет, мы можем использоватьoptimization.splitChunks:

const path = require('path');
module.exports = {
  entry: path.resolve(__dirname, 'src/index.js'),
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
  },
  optimization: {
    splitChunks: {
      // 对所有的包进行拆分
      chunks: 'all',
    },
  },
};

Нам не нужно разрабатывать стратегию распаковки,chunks: allбудет автоматическиnode_modulesпоместите все в файл с именемvendors〜main.jsв файле.

Разделить бизнес-код
module.exports = {
  entry: {
    main: path.resolve(__dirname, 'src/index.js'),
    ProductList: path.resolve(__dirname, 'src/ProductList/ProductList.js'),
    ProductPage: path.resolve(__dirname, 'src/ProductPage/ProductPage.js'),
    Icon: path.resolve(__dirname, 'src/Icon/Icon.js'),
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash:8].js',
  },
};

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

Разделить сторонние библиотеки
const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: path.resolve(__dirname, 'src/index.js'),
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
  },
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: Infinity,
      minSize: 0,
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name(module) {
            // 获取第三方包名
            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];

            // npm 软件包名称是 URL 安全的,但是某些服务器不喜欢@符号
            return `npm.${packageName.replace('@', '')}`;
          },
        },
      },
    },
  },
};

При обновлении стороннего пакета просто обновите соответствующий пакет.

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

динамическая нагрузка

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

import React, { useState, useEffect } from 'react';
import './index.scss'

function Main() {
  const [NeighborPage, setNeighborPage] = useState(null)

  useEffect(() => {
    import('../neighbor').then(({ default: component }) => {
      setNeighborPage(React.createElement(component))
    });
  }, [])

  return NeighborPage
    ? NeighborPage
    : <div>Loading...</div>;
}

export default Main

Семь, настроить плагин

Настройте плагин для обработки и оптимизации других требований,

module.exports = {
  plugins: [
    // 优化 require
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en|zh/),
    // 用于提升构建速度
    createHappyPlugin('happy-babel', [{
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env', "@babel/preset-react"],
        plugins: [
          ['@babel/plugin-proposal-class-properties', {
            loose: true
          }]
        ],
        // babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启
        cacheDirectory: true,
        // Save disk space when time isn't as important
        cacheCompression: true,
        compact: true,
      }
    }])
  ]
}

Общие плагины:

  • html-webpack-plugin: Создать html-файл и добавить пакет в html
  • webpack-parallel-uglify-plugin: сжать js (многопроцессное сжатие параллельной обработки)
  • happypack: Многопоточный загрузчик для повышения скорости сборки
  • hard-source-webpack-plugin: Обеспечивает промежуточный этап кэширования модулей, значительно повышая скорость упаковки.
  • webpack-merge: объединить конфигурацию веб-пакета
  • mini-css-extract-plugin: извлечь css
  • optimize-css-assets-webpack-plugin: сжать css
  • add-asset-html-webpack-plugin: добавить активы JavaScript или CSS в HTML, сгенерированный плагином html-webpack.

Доступны дополнительные плагины:plugins

Восемь, настройте devtool: исходная карта

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

Рабочая среда: по умолчаниюnull, вообще не ставить(none)илиnosources-source-map

Среда разработки: по умолчаниюeval, обычно устанавливается наeval,cheap-eval-source-map,cheap-module-eval-source-map

Стратегия такова:

  • Использование дешевого режима может значительно улучшить эффективность генерации SOWREMAP.Информация о столбцах отсутствует (будет отображаться в преобразованном коде, а не в исходном коде), обычно при отладке нам не нужна информация о столбцах, и даже если исходная карта не имеет столбцов, некоторые браузерные движки (например, v8) будут дать информацию о колонке.
  • **Использование метода eval может значительно повысить эффективность непрерывных сборок. ** Обратитесь к таблице сравнения скоростей, представленной в официальной документации, чтобы увидеть, что скорость компиляции режима eval очень высока.
  • Используйте модули для поддержки babel, инструмента прекомпиляции(Используется как загрузчик в webpack).

Если веб-пакет по умолчаниюminimizerбыл переопределен (например,terser-webpack-plugin), необходимо предоставитьsourceMap:trueвозможность включить поддержку исходной карты.

Еще можно посмотреть:devtool

Девять, производительность конфигурации

Когда упаковка является активом и точкой входа, превышающей определенный предел файлов,performanceКонтролируйте, как webpack уведомляет:

module.exports = {
  // 配置如何显示性能提示
  performance: {
    // 可选 warning、error、false
    // false:性能设置,文件打包过大时,不报错和警告,只做提示
    // warning:显示警告,建议用在开发环境
    // error:显示错误,建议用在生产环境,防止部署太大的生产包,从而影响网页性能
    hints: false
  }
}

10. Настройте другое

1. смотреть и смотреть варианты

watch

Следите за обновлениями файлов и перекомпилируйте их при обновлении:

module.export = {
  // 启用监听模式
  watch: true,
}

существуетwebpack-dev-serverа такжеwebpack-dev-middleware, режим монитора включен по умолчанию.

Или мы можем начать слушать в командной строке (--watch):

webpack --watch --config webpack.config.dev.js
watchOptions
module.export = {
  watch: true,
  // 自定义监视模式
  watchOptions: {
    // 排除监听
    ignored: /node_modules/,
    // 监听到变化发生后,延迟 300ms(默认) 再去执行动作,
    // 防止文件更新太快导致重新编译频率太高
    aggregateTimeout: 300,
    // 判断文件是否发生变化是通过不停的去询问系统指定文件有没有变化实现的
    // 默认 1000ms 询问一次
    poll: 1000
  }
}

2. externals

Исключите зависимости при упаковке, не входящие в объем упаковки, например, вы используете проект в своем проектеjquery, а вы ввели его в html, то при упаковке его повторно не нужно запаковывать:

<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous">
</script>

Конфигурация:

module.exports = {
  // 打包时排除 jquery 模块
  externals: {
    jquery: 'jQuery'
  }
};

3.target

Создайте цель, чтобы указать среду для веб-пакета:

module.exports = {
  // 编译为类浏览器环境里可用(默认)
  target: 'web'
};

4. cache

Кэшируйте сгенерированные модули и фрагменты webpack для повышения скорости сборки. В режиме разработки кеш установлен наtype: 'memory', отключенный в производственном режиме.cache: trueдаcache: {type: 'memory'}псевдоним.要禁用缓存传递false:

module.exports = {
  cache: false
}

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

5. name

Имя конфигурации, используемое для загрузки нескольких конфигураций:

module.exports = {
  name: 'admin-app'
};

11. Резюме

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

Прошлая серия веб-пакетов

Пять визуальных решений для анализа узких мест производительности упаковки webpack

Принцип снупинга: написание сборщика JavaScript от руки

Хотите увидеть предыдущую серию статей,Нажмите, чтобы перейти на домашнюю страницу блога github.

Ссылаться на:

webpack

The 100% correct way to split your chunks with Webpack

webpack 4: mode and optimization

12. Идти до конца

  1. ❤️ Получайте удовольствие, продолжайте учиться и всегда продолжайте программировать. 👨💻

  2. Если у вас есть какие-либо вопросы или уникальные идеи, пожалуйста, прокомментируйте или свяжитесь с бутылкой напрямую (общедоступный номер может ответить на 123)! 👀👇

  3. 👇Приглашаем обратить внимание: джентльмен с бутылкой переднего плана, обновляется ежедневно! 👇