Обзор

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

что вы узнаете, прочитав эту историю?

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

Первый шаг

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

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

Производство:

мы должны установить режим в производстве, но почему?

В производственном режиме webpack оптимизируется автоматически, и на следующем рисунке мы видим, что размер пакета в производственной среде составляет 164 КБ, а в разработке - 1,24 МБ.

mode: 'production',

Второй шаг: исходная карта

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

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

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

Оппс! Где ошибка, почему я получил это? поэтому, поскольку мы не устанавливаем devtool, и если мы получили это в процессе производства, в большом проекте мы должны тратить время на поиск ошибки в приложении, но с source-map мы можем найти такую ​​ошибку в проекте:

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

  mode : 'production',
+ devtool: 'source-map',

Третий шаг: установить запись, вывод, плагин

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



После этого у нас может быть этот конфиг для плагинов,

Я использовал плагины MiniCssExtractPlugin, BundleAnalyzerPlugin, HtmlWebpackPlugin

new BundleAnalyzerPlugin(),
new MiniCssExtractPlugin({
    filename: `static/css/[name].[contenthash].css`,
    chunkFilename: `static/css/[id].[contenthash].css`
}),
new HtmlWebpackPlugin({
    meta: {
        viewport: 'width=device-width, initial-scale=1,viewport-fit=cover, shrink-to-fit=no',
        'theme-color': '#FF7714',
        'apple-mobile-web-app-status-bar-style': '#FF7714',
        'og:title': 'Food Delivery',
        'og:description': 'A simple Boilerplate of React Js',
        'content-type': {'http-equiv': 'content-type', content: 'text/html; charset=UTF-8'}
    },
    title: 'Food Delivery',
    template: 'public/index.html',
    minify: {
        collapseWhitespace: true,
        removeComments: true,
        removeRedundantAttributes: true,
        removeScriptTypeAttributes: true,
        removeStyleLinkTypeAttributes: true,
        useShortDoctype: true
    }
}),

Вы можете увидеть дополнительный код в htmlWebpackPlugin, потому что я хочу сделать pwa

theme-color и apple-mobile-web-app-status-bar-style предназначены для тегов pwa и open graph, когда мы хотим иметь хороший UX при совместном использовании нашей страницы и другой конфигурации в свойстве minify для лучшей минификации в строительство.

и miniCssExtractPlugin для нашего кода стилей.

После этого шага пришло время оптимизировать производство и размер пакета :)

Четвертый шаг: оптимизация конфигурации

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

хеширование устарело в веб-пакете 5, и вы должны заменить его детерминированным

optimization: {
   /**
    * for choose module id
    * this is deprecated in the webpack 5
    */
   moduleIds: 'hashed',

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

Базовый документ Webpack. У нас есть 3 типа файлов в здании, один из них - манифест и исполняемый. Вкратце, мы предполагаем, что в приложении много файлов фрагментов, но важный вопрос заключается в том, как они связаны друг с другом. ?

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

runtimeChunk: {
   name: entrypoint => `runtimechunk~${entrypoint.name}`
},

следующий уровень - свести к минимуму до истинного

minimize: true,

и следующим шагом будет добавление splitChunks, позвольте мне начать с образца

Предположим, у нас есть два блока:

блок A: react-dom, loadash, redux

блок B: react, react-dom, loadash, некоторый компонент

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

chunk A: redux
chunk B: реагирует, какой-то компонент
vendor-chunk-A-chunk-B: реагировать-дом, loadash

Это упрощает кэширование, но есть некоторые понятия, на которые мы должны обратить внимание: это поведение поставщика предназначено для зависимости ≥ 30 КБ, и для ниже этого порогового значения веб-пакет дублировал зависимость, потому что стоимость запроса выше

Конечно, мы можем изменить этот порог, установив minSize в splitchunk.

Для тестирования этой опции мы добавляем еще одну запись и еще один плагин Htmpwebpackplugin

entry: {
    app: [`./src/index.js`],
    user: ['./src/user.js']
},
new HtmlWebpackPlugin({
    template: `public/index.html`,
    favicon: `public/favicon.ico`,
    chunks: ["user"],
    filename: `user.html`,
})

Свойство чанка предназначено для фильтра и просто делайте для этого имени чанка.

вы можете увидеть этот анализ

Если вы обратите внимание, вы можете увидеть, что lodash дублируется, и, честно говоря, это не очень хорошо, поэтому для создания общего доступа поставщик, чтобы добавить только один lodash, мы добавляем splitChunks

splitChunks: {
    cacheGroups: {
        vendor: {
            name: "node_vendors",
            test: /[\\/]node_modules[\\/]/,
            chunks: "all",
        }
    }
}

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

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

После этого можно добавить TerserPlugin для минимизации

new TerserPlugin({
    terserOptions: {
        format: {
            comments: false,
        },
    },
    extractComments: false,
    // enable parallel running
    parallel: true,
}),

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

Надеюсь, моя история вам помогла 😅 если у вас есть хорошее предложение, вы можете прокомментировать :)

Удачи