Сводка по обучению Webpack5.0 — Основы

JavaScript
Сводка по обучению Webpack5.0 — Основы

предисловие

Леса, которые использовались при разработке проекта Vue, я очень мало знаю о черном ящике Webpack, и я всегда смущаюсь, когда сталкиваюсь с проблемами, поэтому я изучил его более полно, когда вскоре был выпущен Webpack 5.0. В этой статье подводятся итоги обучения. Общий план выглядит следующим образом: Эта статья является базовой главой. Чтобы перейти к расширенной главе, нажмите на портал.Сводка по обучению Webpack5.0 — продвинутый уровень.

Webpack.png

Знакомство с вебпаком

Что такое вебпак?

Webpack — это интерфейсный инструмент для создания ресурсов, сборщик статических модулей.

  • Инструмент построения внешнего интерфейса: в основном поймите, какие ресурсы представляет собой этот внешний ресурс. Эти интерфейсные ресурсы являются веб-ресурсами, которые браузер не распознает. Например, sass, less, ts, включая расширенный синтаксис в js. Для правильной работы в браузере эти ресурсы должны быть скомпилированы один за другим. И webpack — это общий инструмент сборки, который может интегрировать эти инструменты компиляции.
  • Сборщик статических модулей: статические модули – это различные файлы ресурсов в процессе веб-разработки. На основе эталонных отношений веб-пакет строит граф зависимостей, а затем использует этот граф для упаковки всех статических модулей в один или несколько пакетов для вывода.

Зачем нам нужен вебпак

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

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

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

Использовать веб-пакет

Конфигурация ядра Webpack

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

entry

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

    // string方式: 单入口,打包形成一个chunk,输出一个buldle文件。chunk的名称默认是main.js
    entry: "./src/index.js",
    // array方式:多入口,所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件
    entry: ["./src/index.js", "./src/test.js"],
    // object:多入口,有几个入口文件就形成几个chunk,输出几个bundle文件。此时chunk的名称就是对象key值
    entry:{
        index:"./src/index.js",
        test:"./src/test.js",
    }

output

output: Указывает, где и как выводятся связанные пакеты ресурсов Webpack.

    output: {
        // 输出文件目录(将来所有资源输出的公共目录,包括css和静态文件等等)
        path: path.resolve(__dirname, "dist"), //默认
        // 入口文件名称(指定名称+目录)
        filename: "[name].js", // 默认
        // 所有资源引入公共路径前缀,一般用于生产环境,小心使用
        publicPath: "",
        /* 
        非入口文件chunk的名称。所谓非入口即import动态导入形成的chunk或者optimization中的splitChunks提取的公共chunk
        它支持和 filename 一致的内置变量
        */
        chunkFilename: "[contenthash:10].chunk.js",
        clean: true, // 打包前清空输出目录,相当于clean-webpack-plugin插件的作用,webpack5新增。
        /* 当用 Webpack 去构建一个可以被其他模块导入使用的库时需要用到library */
        library: {
            name: "[name]",//整个库向外暴露的变量名
            type: "window"//库暴露的方式
        }
    },

loader

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

rules: [
    {
        // 匹配哪些文件
        test: /\.css$/,
        // 使用哪些loader进行处理。执行顺序,从右至左,从下至上
        use: [
            // 创建style标签,将js中的样式资源(就是css-loader转化成的字符串)拿过来,添加到页面head标签生效
            "style-loader",
            // 将css文件变成commonjs一个模块加载到js中,里面的内容是样式字符串
            "css-loader",        
             {

                 // css 兼容处理 postcss,注意需要在package.json配置browserslist
                 loader: "postcss-loader",
                 options: {
                     postcssOptions: {
                         ident: "postcss",
                         // postcss-preset-env插件:帮postcss找到package.json中的browserslist配置,根据配置加载指定的兼容性样式      
                         plugins: [require("postcss-preset-env")()],
                     },
                 },
             },
        ],
    },
    {
        test: /\.js$/,
        // 注意需要在package.json配置browserslist,否则babel-loader不生效
        // js兼容处理 babel
        loader: "babel-loader", // 规则只使用一个loader时推荐写法
        options: {
            presets: [
                [
                    "@babel/preset-env",// 预设:指示babel做怎么样的兼容处理 
                    {
                        useBuiltIns: "usage", //按需加载
                        corejs: {
                            version: "3",
                        },
                        targets: "defaults",
                    }
                ]
            ]
        }
    },
    /* 
    Webpack5.0新增资源模块(asset module),它是一种模块类型,允许使用资源文件(字体,图标等)而无需     配置额外 loader。支持以下四个配置
    asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
    asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
    asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
    asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资     源体积限制实现。
    */
    // Webpack4使用file-loader实现
    {
        test: /\.(eot|svg|ttf|woff|)$/,
        type: "asset/resource",
        generator: {
            // 输出文件位置以及文件名
            filename: "fonts/[name][ext]"
        },
    },
    // Webpack4使用url-loader实现
    {
        //处理图片资源
        test: /\.(jpg|png|gif|)$/,
        type: "asset",
        generator: {
            // 输出文件位置以及文件名
            filename: "images/[name][ext]"
        },
        parser: {
            dataUrlCondition: {
                maxSize: 10 * 1024 //超过10kb不转base64
            }
        }
    },
],

plugin

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

// CleanWebpackPlugin帮助你在打包时自动清除dist文件,学习时使用比较方便
// const { CleanWebpackPlugin } = require("clean-webpack-plugin"); //从webpack5开始,webpack内置了该功能,只要在ouput中配置clear为true即可

// HtmlWebpackPlugin帮助你创建html文件,并自动引入打包输出的bundles文件。支持html压缩。
const HtmlWebpackPlugin = require("html-webpack-plugin");

// 该插件将CSS提取到单独的文件中。它会为每个chunk创造一个css文件。需配合loader一起使用
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

// 该插件将在Webpack构建过程中搜索CSS资源,并优化\最小化CSS
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");

// vue-loader V15版本以上,需要引入VueLoaderPlugin插件,它的作用是将你定义过的js、css等规则应用到vue文件中去。
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: "vue-loader"
            },
            {
                test: /\.css$/,
                use: [
                    // MiniCssExtractPlugin.loader的作用就是把css-loader处理好的样式资源(js文件内),单独提取出来 成为css样式文件
                    MiniCssExtractPlugin.loader,//生产环境下使用,开发环境还是推荐使用style-loader
                    "css-loader",
                ],
            },
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({
            template:"index.html"
        }),
        new MiniCssExtractPlugin({
            filename: "css/built.css",
        }),
        new OptimizeCssAssetsWebpackPlugin(),
        new VueLoaderPlugin(),
    ]
}

mode

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

Опции описывать
development Будет установлено значение process.env.NODE_ENV в DefinePlugin для разработки.Включает допустимые имена для модулей и фрагментов.
production установит значение process.env.NODE_ENV в DefinePlugin для производства. Включите детерминированные запутанные имена для модулей и фрагментов, FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin и TerserPlugin.
none Не используйте параметры оптимизации по умолчанию
  • DefinePlugin: Определите глобальную переменную Process.env.node_env, чтобы отличить текущее состояние программы.
  • FlagDependencyUsagePlugin: пометить неиспользуемые зависимости.
  • FlagIncludedChunksPlugin: Отметьте фрагменты, чтобы предотвратить их многократную загрузку.
  • ModuleConcatenationPlugin: хостинг области, функция предварительной компиляции, продвижение или предварительная компиляция всех модулей в замыкание, повышение скорости выполнения кода в браузере.
  • NoEmitOnErrorsPlugin: запретить программе сообщать об ошибках и продолжить компиляцию, даже если есть ошибки.
  • TerserPlugin: сжатие кода js.

Другие распространенные конфигурации

module.exports = {
    // 解析模块的规则:
    resolve: {
        // 配置 解析模块路径别名:可简写路径。
        alias: {
            "@": path.resolve(__dirname, "src")
        },
        // 配置 省略文件路径的后缀名。默认省略js和json。也是webpack默认认识的两种文件类型
        extensions: [".js", ".json", ".css"], // 新加css文件
        // 告诉webpack解析模块是去找哪个目录
        // 该配置明确告诉webpack,直接去上一层找node_modules。
        modules: [path.resolve(__dirname, "../node_modules")],
    },
    // devServer(开发环境下配置):
    devServer: {
        // 运行代码的目录
        contentBase: path.resolve(__dirname, "build"),
        // 为每个静态文件开启gzip压缩
        compress: true,
        host: "localhost",
        port: 5000,
        open: true, // 自动打开浏览器
        hot: true, //开启HMR功能
        // 设置代理
        proxy: {
            // 一旦devServer(5000端口)接收到/api/xxx的请求,就会用devServer起的服务把请求转发到另外一个服务器(3000)
            // 以此来解决开发中的跨域问题
            api: {
                target: "htttp://localhost:3000",
                // 发送请求时,请求路径重写:将/api/xxx  --> /xxx (去掉/api)
                pathRewrite: {
                    "^api": "",
                },
            },
        },
    },

    // optimization(生产环境下配置)
    optimization: {
        // 提取公共代码
        splitChunks: {
            chunks: "all",
        },
        minimizer: [
            // 配置生产环境的压缩方案:js和css
            new TerserWebpackPlugin({
                // 多进程打包
                parallel: true,
                terserOptions: {
                    // 启动source-map
                    sourceMap: true,
                },
            }),
        ],
    },
};

оптимизация упаковки веб-пакета

Оптимизация среды разработки

1. Используйте исходную карту

исходная карта: технология, которая предоставляет исходный код для сопоставления кода после сборки.Если код после сборки неверен, ошибка исходного кода может быть прослежена через сопоставление. Оптимизация отладки кода.
Включить конфигурацию исходной карты очень просто: devtool:"source-map". Есть много типов значений исходной карты, кратко объясненных.
Параметры исходной карты обычно состоят из: [inline-|eval-][cheap-[module-]]source-map

  • встроенный: встроенный, чанк генерирует общую исходную карту
  • eval: встроенный, каждый файл генерирует исходную карту
  • дешевый: внешний, позиция ошибки может быть точной только до линии.
  • Cheap-module: Показать исходную карту сторонних библиотек.

Разница между инлайном и внешним: инлайн не генерирует файл map.js, а напрямую внедряет его в чанк в виде data-url, инлайн строит быстрее.

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

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

    devServer: {
        contentBase: path.resolve(__dirname, "dist"),
        hot: true,//开启HMR功能
    },
    // 注意:Webpack升级到5.0后,target默认值值会根据package.json中的browserslist改变,导致devServer的自动更新失效。所以development环境下直接配置成web。
    target: "web",

После включения HMR необходимо, чтобы некоторые конфигурации вступили в силу.

  • Файл стиля: загрузчик стилей реализован внутри, поэтому, если загрузчик стилей настроен в загрузчике, функцию HMR можно использовать напрямую.
  • vue-файл: внутренняя реализация vue-loader, аналогичным образом настройте vue-loader для прямого использования HMR.
  • js: вам нужно изменить исходный код, чтобы получать уведомления об обновлениях, код выглядит следующим образом
import test from "./test.js"
if(module.hot){
    module.hot.accept("./test.js",()=>{
        console.log('Accepting the updated test module!');
    })
}

При изменении тестового файла событие обновления будет передаваться слой за слоем, пока не будет передано в файл входа. В процессе доставки, если где-либо будет получено событие обновления, то есть метод module.hot.accept выше, доставка будет остановлена ​​и будет выполнен callback. Если он не был получен, Webpack в конечном итоге будет уведомлен об обновлении всей страницы.

Оптимизация производственной среды

1. один из

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

rules:[
    {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "eslint-loader",
    },
    {
        //  以下loader一种文件只会匹配一个 
        oneOf: [
            // 不能有两个配置处理同一种类型文件,如果有,另外一个规则要放到外面。
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: "babel-loader",
                    },
                ],
            },
            {
                test: /\.css$/,
                use: [
                    "style-loader",
                    "css-loader",
                ],
            },
        ],
    },
]

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

2. Кэш

Существует два способа кеширования файлов при компиляции и упаковке: один заключается в том, что загрузчик, разбирающий сам файл, имеет функцию кэширования (например, babel-loader, vue-loader), а второй — использовать специальный загрузчик (cache-loader, vue-loader). загрузчик).
После включения кеша для неизмененных файлов webpack читает напрямую из кеша без повторной компиляции, что значительно ускоряет сборку.

{
    test: /\.js$/,
    use: [
        //使用cache-loader,放在babel-loader前可对babel编译后的js文件做缓存。
        "cache-loader",
        {
            loader: "babel-loader",
            options: {
                presets: [
                    [
                        "@babel/preset-env",// 预设:指示babel做怎么样的兼容处理 
                    ]
                ],
                // 开启babel缓存,第二次构建时,会读取之前的缓存。
                cacheDirectory: true,
            }
        }

}

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

cache: {
      type: 'filesystem', //保存位置,开发环境下默认为memory类型,生产环境cache配置默认是关闭的。
      buildDependencies: {
        config: [__filename]
      }

}

3. Мультипроцессная упаковка (поток-загрузчик)

Как правило, вам нужно использовать thread-loader только тогда, когда компиляция занимает много времени, потому что запуск и связь этого загрузчика дороги, Если времени мало, использование этого загрузчика не будет стоить потерь.

// "thread-loader"放在babel-loader前,就会在babel-loader工作时进行多进程工作。
{
    loader: "thread-loader",
    options: {
        workers: 2, // 启动进程个数,默认是电脑cpu核数-1
    },
},
{
    loader: "babel-loader",
    options: {
        presets: [
            [
                "@babel/preset-env",
            ],
        ],
    },
},
В-четвертых, внешнее расширение (внешние)

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

module.export = {
  externals: {
    // 把导入语句里的 jquery 替换成运行环境里的全局变量 jQuery
    jquery: 'jQuery'
  }
}

// 源代码
 import $ from "jquery"

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

5. DLL

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

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

код для этого шага

1 Создайте новый файл webpack.dll.js, чтобы заранее упаковать библиотеку динамической компоновки.

// webpack.dll.js
module.exports = {
    // JS 执行入口文件
    entry: {
        // 把 vue 相关模块的放到一个单独的动态链接库
        vendor: ['vue', 'axios'],
        // 其他模块放到另一个动态链接库
        other: ['jquery', 'lodash'],
    },
    output: {
        // 输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称("vendor"和"other")
        filename: '[name].dll.js',
        // 输出的文件都放到 dist 目录下的dll文件夹中
        path: path.resolve(__dirname, 'dist', "dll"),
        // 存放动态链接库的向外暴露的变量名,例如对应 vendor 来说就是 _dll_vendor
        library: '_dll_[name]',
    },
    plugins: [
        //  打包生成一个mainfest.json文件。告诉webpack哪些库不参与后续的打包,已经通过dll事先打包好了。
        new webpack.DllPlugin({
            // 动态链接库的库名,需要和 output.library 中保持一致
            // 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
            // 例如 vendor.manifest.json 中就有 "name": "_dll_vendor"
            name: '_dll_[name]',
            // 描述动态链接库的 manifest.json 文件输出时的文件名称
            path: path.join(__dirname, 'dist', "dll", '[name].manifest.json'),
        }),
    ],
};
  1. Вставьте упакованную библиотеку динамических ссылок в страницу шаблона index.html.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Webpack</title>
    <script src="./dll/vendor.dll.js"></script>
    <script src="./dll/other.dll.js"></script>
</head>
<body>
    <div id="app"></div>
</body>
</html>

  1. Используйте плагин webpack.DllReferencePlugin в конфигурации Webpack основной программы, прочитайте файл manifest.json, сгенерированный webpack.DllPlugin, и получите от него зависимости.
// webpack.config.js
module.exports = {
    mode: "production",
    plugins: [
        new HtmlWebpackPlugin({
            template: "./index.html"
        }),
        // 告诉 Webpack 使用了哪些动态链接库
        new webpack.DllReferencePlugin({
            // manifest文件告诉webpack哪些库已经通过dll事先打包好了,后续构建直接去动态链接库里获取。
            manifest: path.resolve(__dirname, "dist", "./dll/vendor.manifest.json"),
        }),
        new webpack.DllReferencePlugin({
            manifest: path.resolve(__dirname, "dist", "./dll/other.manifest.json"),
        }),
    ],
}
6. Сотрясение дерева

Встряхивание дерева: удаление мертвого кода из контекстов JavaScript. Думайте обо всем приложении как о дереве, зеленые листья представляют исходный код и библиотеку, которые фактически используются, а серые листья представляют неиспользуемый код, который является увядшими листьями. Чтобы избавиться от этих мертвых бесполезных листьев, вам нужно встряхнуть дерево, чтобы оно упало. Отсюда и название Tree Shaking.

// 入口文件index.js
import test from "./test.js"
console.log(test.add(2, 3));

// 测试文件test.js
const add = (x, y) => x + y
const print = (msg) => {
    console.log(msg);
}
export default { add, print }

// 最终打包输出的bundle:main.js文件
!function(){"use strict";console.log(2+3)}();

Как видно из приведенного выше примера, несмотря на то, что тестовый файл введен в index.js, поскольку метод печати, предоставляемый тестовым файлом, не используется, он удален в окончательной упаковке.
Это пока невозможно в Webpack4, который удаляет только модули, которые никогда не используются. В приведенном выше примере, если тест не используется в файле index.js, это будет встряхивание дерева. Причина этого в том, что по умолчанию Webpack4 считает, что код всех файлов имеет побочные эффекты. Как сообщить Webpack, есть ли у вашего кода побочные эффекты, через поле sideEffects в package.json.

// 所有文件都有副作用
{
 "sideEffects": true
}
// 所有文件都没有副作用,
{
 "sideEffects": false
}
// 只有这些文件有副作用,所有其他文件都可以 Tree Shaking,但会保留这些文件
{
 "sideEffects": [
  "./src/file1.js",
  "./src/file2.js"
 ]
}

Например, в стандартной настройке Webpack 5.0 файл стиля считается имеющим побочные эффекты, поэтому, хотя файл стиля не используется (файл стиля точно не используется), он не будет удален, но если sideEffects: false установлен, он будет выполняться.Tree Shaking удаляет код.
Сказав так много, как настроить Tree Shaking? На самом деле никакой специальной настройки не требуется, пока установлен режим «производство», Webpack автоматически включит встряхивание дерева. Следует отметить два момента:

  • Исходный код должен использовать статический модульный синтаксис ES6. Причина в том, что WebPack анализирует зависимости между кодами через статический анализ в течение времени сборки. Однако динамический импорт, такой как требуемый синтаксис, знал, какой модуль импортируется только тогда, когда оно выполняется, поэтому дрожание дерева не может быть сделано.
  • Трехсторонняя библиотека не может сделать тряску дерева. Причина предположения состоит в том, что WebPack не может гарантировать, будет ли импорт сторонней библиотеки повлиять на программу.
7. Разделение кода

По умолчанию Webpack упаковывает и выводит все зависимые файлы в файл bundle.js (одна запись).Когда приложение становится более сложным, файл bundle.js становится все больше и больше, а скорость загрузки браузера становится все быстрее и быстрее. Медленно, поэтому вам нужно использовать разделение кода, чтобы отдельно упаковать разные коды в разные выходные данные. В основном есть два метода

1. Упаковать общий код в куски отдельно с помощью оптимизации

optimization: {
    splitChunks: {
        // 选择哪些 chunk 进行优化,默认async,即只对动态导入形成的chunk进行优化。
        chunks: 'all', 
        // 提取chunk最小体积
        minSize: 20000,
        // 要提取的chunk最少被引用次数
        minChunks: 1,
        // 对要提取的chunk进行分组
        cacheGroups: {
            // 匹配node_modules中的三方库,将其打包成一个chunk
            defaultVendors: {
                test: /[\\/]node_modules[\\/]/,
                // chunk名称
                name: 'vendors',
                priority: -10,
            },
            default: {
                // 将至少被两个chunk引入的模块提取出来打包成单独chunk
                minChunks: 2,
                name: 'default',
                priority: -20,
            },
        },
    },
},

Во-вторых, импортировать динамический импорт
Этот метод рекомендуется, если вы хотите разделить пакеты в соответствии с бизнесом. import Динамически импортированные модули Webpack упакует их как отдельные куски.

import( /* webpackChunkName: 'test' */ './test.js').then((result) => {
    console.log(result);
}).catch(() => {
    console.log('加载失败!');
});

Эпилог

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