Поиск оптимальной конфигурации webpack4 на практике

Node.js внешний интерфейс CSS Webpack

В настоящее время автор готовится датьfle-cliобновитесь доwebpack4версии, я посчитал необходимым поделиться со всеми опытом процесса исследования, поэтому решил написать эту статью. (не знаюfle-cli?Смотри сюда)

Webpack4 — это большая тенденция, и обновление неизбежно, так почему же это только сейчас?

Причины следующие:

  • Только что выпущенная версия все еще нестабильна и имеет высокие потенциальные риски, но текущая версия была обновлена ​​до 4.8.3, которая в основном стабильна;
  • Инструменты сообщества webpack не совсем поспевают за ритмом, и многие инструменты приходится разрабатывать самим и кропотливо (на самом деле, в основном ленивые ха-ха);
  • Есть более или менее проблемы с самим webpack и инструментами сообщества, а стоимость обслуживания высока без временных затрат.

Однако сейчас автор считает, что вышеизложенное созрело, и настало время для волны апгрейдов.

предисловие

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

настроить

mode

Режим – это новый параметр для webpack4. Он имеет три значения: development, production и none, что может помочь нам загрузить некоторые конфигурации по умолчанию. None означает, что конфигурация по умолчанию не загружена. Соответствующая конфигурация по умолчанию указана ниже для справки, чтобы избежать повторной настройки.

development

Сосредоточьтесь на повышении скорости сборки кода и опыте разработки

module.exports = {
  cache: true,
  devtools: "eval",
  plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") })
  ]
}

prodution

Обеспечивает оптимизацию кода, такую ​​как сжатие, расширение области действия и т. д.

var UglifyJsPlugin = require('uglifyjs-webpack-plugin')

module.exports = {
  plugins: [
    new UglifyJsPlugin(/* ... */),
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
  ]
}

optimization

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

minimizer

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


var UglifyJsPlugin = require('uglifyjs-webpack-plugin')
var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
  optimization: {
    minimizer: [
      // 自定义js优化配置,将会覆盖默认配置
      new UglifyJsPlugin({
        exclude: /\.min\.js$/, // 过滤掉以".min.js"结尾的文件,我们认为这个后缀本身就是已经压缩好的代码,没必要进行二次压缩
        cache: true,
        parallel: true, // 开启并行压缩,充分利用cpu
        sourceMap: false,
        extractComments: false, // 移除注释
        uglifyOptions: {
          compress: {
            unused: true,
            warnings: false,
            drop_debugger: true
          },
          output: {
            comments: false
          }
        }
      }),
      // 用于优化css文件
      new OptimizeCssAssetsPlugin({
        assetNameRegExp: /\.css$/g,
        cssProcessorOptions: {
          safe: true,
          autoprefixer: { disable: true }, // 这里是个大坑,稍后会提到
          mergeLonghand: false,
          discardComments: {
            removeAll: true // 移除注释
          }
        },
        canPrint: true
      })
    ]
  }
}

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

OptimizeCssAssetsPluginЭтот плагин в основном используется для оптимизации вывода файлов css и используется по умолчанию.cssnano, его стратегия оптимизации в основном включает в себя: отказ от повторяющихся определений стиля, отсечение избыточных параметров в правилах стиля, удаление ненужных префиксов браузера и т. д. Дополнительные правила оптимизации см.здесь. Ранее мы упоминали, что здесь есть большая яма, я думаю, вы ее заметили, да, это та, через которую мы прошли.autoprefixerДобавлен префикс для удаления. Автор проверил много информации, но до сих пор не может найти удовлетворительного ответа.У меня нет другого выбора, кроме как стиснуть зубы и обратиться к исходному коду, чтобы найти ответ, поэтому у меня такая конфигурация.autoprefixer: { disable: true }, отключить обработку префиксов браузера cssnano.

runtimeChunk

Выделение кода, который компилируется и запускается webpack, который мы ранее называлиmanifestПреимущество блока кода в том, что нам удобно делать персистентное кэширование файлов. Он может устанавливать различные типы значений, см.здесьsingleТо есть упаковать все куски работающего кода в файл,multipleЭто упаковать файл для рабочего кода каждого фрагмента.

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

var HtmlWebpackPlugin = require('html-webpack-plugin')
var InlineManifestWebpackPlugin = require('inline-manifest-webpack-plugin')

module.exports = {
  entry: {
    app: 'src/index.js'
  },
  optimization: {
    runtimeChunk: 'single'
    // 等价于
    // runtimeChunk: {
    //   name: 'runtime'
    // }
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'fle-cli',
      filename: 'index.html',
      template: 'xxx',
      inject: true,
      chunks: ['runtime', 'app'], // 将runtime插入html中
      chunksSortMode: 'dependency',
      minify: {/* */}
    }),
    new InlineManifestWebpackPlugin('runtime')
  ]
}

Эта конфигурация приведет кruntimeБлок кода, в отличие от старой версии, нам не нужно добавлять в html шаблон<%= htmlWebpackPlugin.files.webpackManifest %>, просто добавьте время выполнения в чанки. Здесь следует отметить, что порядок плагина InlineManifestWebpackPlugin должен быть после HtmlWebpackPlugin, иначе компиляция завершится ошибкой.

splitChunks

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

Давайте сначала посмотрим на конфигурацию по умолчанию:

splitChunks: {
  chunks: "async",
  minSize: 30000,
  minChunks: 1,
  maxAsyncRequests: 5,
  maxInitialRequests: 3,
  automaticNameDelimiter: '~',
  name: true,
  cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      priority: -10
    },
    default: {
      minChunks: 2,
      priority: -20,
      reuseExistingChunk: true
    }
  }
}

Конфигурация по умолчанию работает только наАсинхронная загрузкаБлок кода, он ограничивает минимальный размер разделяемого файла, который составляет 30 КБ (обратите внимание, что это размер до сжатия), это обязательное условие, а затем он имеет две группы: принадлежащий модулю node_modules, или указанный как минимум 2 входных файла, они будут упакованы в отдельный файл.

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

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

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

splitChunks: {
  cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      name: 'vendors',
      minSize: 30000,
      minChunks: 1,
      chunks: 'initial',
      priority: 1 // 该配置项是设置处理的优先级,数值越大越优先处理
    },
    commons: {
      test: /[\\/]src[\\/]common[\\/]/,
      name: 'commons',
      minSize: 30000,
      minChunks: 3,
      chunks: 'initial',
      priority: -1,
      reuseExistingChunk: true // 这个配置允许我们使用已经存在的代码块
    }
  }
}

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

Второй момент - выделение общих модулей. Автор считает, что для элегантной структуры проекта его общий код (или повторно используемый код) должен быть размещен в одном корневом каталоге. Исходя из этого, можно поставитьsrc/commonОбщий код извлечен.

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

конец статьи

Изначально я хотел рассказать о настройке части плагина css, из-за ограничений по объему в этой статье больше объяснять не буду, заинтересованные братья и сестры могут посмотреть исходный код здесь:webpack4-test.

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