«Серия Webpack» — подробное объяснение использования плагина SplitChunks

Webpack
«Серия Webpack» — подробное объяснение использования плагина SplitChunks

предисловие

Потому что плагин SplitChunks извлечет модуль и упакует его.jsдокумент. Сначала научитесь упаковывать и генерироватьjsИменование файла, в противном случае нелегко подтвердить сгенерированный пакетjsФайл не то, что вы хотите. Сгенерировано для упаковки в WebPackjs

jsИменование файлов, на рисунке нижеapp.jsФайл представляет собой упакованный файл записи js.

  • В проекте Vue с одной записью файл записи перед упаковкой, вvue.config.jsСредняя конфигурация

    module.exports = {
        configureWebpack:{
            entry:'./src/main.js',
        }
    }
    

    Файл ввода упаковки, вvue.config.jsСредняя конфигурация

    module.exports = {
        configureWebpack:{
           output:{
                filename: 'js/appCS.js'
            }, 
        }
    }
    

    Зачем добавлять на передний планjs/Посколькуjsфайлoutput:pathГенерируется в каталоге, указанном параметром, который по умолчанию является корневым каталогом./. Результат упаковки выглядит следующим образом

  • В проекте Vue с несколькими записями файл записи перед упаковкой, вvue.config.jsСредняя конфигурация

      module.exports = {
          configureWebpack:{
              entry: {
                  appCS: './src/main.js'
              },
          }
      }
    

    Упакованный входной файл, вvue.config.jsСредняя конфигурация

    module.exports = {
        configureWebpack:{
            output:{
                filename: 'js/[name].js'
            },
        }
    }
    

    [name]имя модуля файла записи. Результат упаковки выглядит следующим образом

    найдет большеapp.js, это связано с тем, что когда значением configureWebpack является объект, он будет объединен с окончательной конфигурацией через webpack-merge. удалятьapp.jsМожно настроить с помощью chainWebpack. Конфигурация выглядит следующим образом

    module.exports = {
        chainWebpack: config =>{
            config.entryPoints.delete('app').end().entry('appCS').add('./src/main.js')
        }
    }
    

    Результат упаковки выглядит следующим образом

2. output.chunkFilename

Эта опция дает упакованный не входjsИменование документа, изображение ниже не является портфолиоjsдокумент

Настроить в Vue.config.js.

module.exports = {
    configureWebpack:{
        output:{
            chunkFilename: 'CS.[name].js'
        },
    }
}

Результат упаковки выглядит следующим образом

Однакоoutput.chunkFilenameНе меняетсяchunk-0a4e15c9

webpackChunkName[request]

function load(component) {
    return () => import(/* webpackChunkName: "[request]" */ `views/${component}`)
}
const routes = [
    {
        {
            path: '/apiApply',
            name: 'apiApply',
            component: load('api_manage/api_apply'),
        }
    }
]

Результат упаковки выглядит следующим образом

src/views/api_manage/api_apply/index.vueФайл js, сгенерированный после упаковки этого компонента,api_manage-api_apply.48227bf7.js.

если не[request]Можно и так написать.

component: () =>import(/* webpackChunkName: "api_manage-api_apply"*/ 'src/views/api_manage/api_apply'),

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

ЭтиjsИменование файлов задается в плагине splitchunks.

Во-вторых, параметры конфигурации плагина

  • chunksварианты, чтобы решить, какие модули извлекать.
    • По умолчаниюasync: извлекать только асинхронно загруженные модули и упаковывать их в файл.
      • Асинхронно загружаемые модули: черезimport('xxx')илиrequire(['xxx'],() =>{})загруженный модуль.
    • initial: Модуль извлечения синхронной и асинхронной загрузки загружается, если xxx загружается в проект асинхронно, но также загружается одновременно, этот модуль будет затем xxx извлекаться дважды, каждый из которых упакован в разные файлы.
      • Синхронно загружаемые модули: черезimport xxxилиrequire('xxx')загруженный модуль.
    • all: Модули, загруженные асинхронно или синхронно, извлекаются и упаковываются в файл.
  • minSizeОпция: указывает минимальный размер извлекаемого модуля перед сжатием, в байтах, по умолчанию 30000, и только если он превышает 30000 байт, он будет извлечен.
  • maxSizeПараметры: Извлекаемый пакет модулей в результирующем размере файла не может превышать значение maxSize, в случае превышения его следует разделить и упаковать, сгенерировав новый файл. Байты, 0 по умолчанию, чтобы не ограничивать размер.
  • minChunksОпции: Указывает, что модуль должен быть извлечен минимальное количество цитат, цитаты, чем или равно значением Minchunks, можно извлечь.
  • maxAsyncRequests
  • maxInitialRequestsОпция: Когда загружен упакованный файл ввода, количество файлов JS (включая файлы ввода), может быть загружено одновременно, по умолчанию 4.
  • Поговорим о приоритетахmaxInitialRequests / maxAsyncRequests <maxSize <minSize.
  • automaticNameDelimiterОпция: Пакет разделения сгенерированного имени файла JS, по умолчанию~.
  • nameОпция: имя пакета для генерации файла JS.
  • cacheGroupsВарианты, основной фокус,.里面每一项代表一个提取模块的方案。 НижеcacheGroupscacheGroups
    • test
    • priority
    • reuseExistingChunkОпции:true/false. дляtrue, если извлекаемый модуль в данный момент упаковывается и генерируетсяjsФайл существует, модуль будет использоваться повторно, а не для извлечения текущего пакета для создания нового модуля.jsдокумент.
    • enforceОпции:true/false. дляtrue, игнорироватьminSize,minChunks,maxAsyncRequestsа такжеmaxInitialRequestsВарианты внешней конфигурации.

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

Сначала взгляните на конфигурацию SplitChunks по умолчанию в Vue Cli3.. Настроено так в исходном коде Vue Cli3

Конфигурация по умолчанию после завершения выглядит следующим образом:

module.exports = {
    configureWebpack:config =>{
        return {
            optimization: {
                splitChunks: {
                    chunks: 'async',
                    minSize: 30000,
                    maxSize: 0,
                    minChunks: 1,
                    maxAsyncRequests: 6,
                    maxInitialRequests: 4,
                    automaticNameDelimiter: '~',
                    cacheGroups: {
                        vendors: {
                            name: `chunk-vendors`,
                            test: /[\\/]node_modules[\\/]/,
                            priority: -10,
                            chunks: 'initial'
                        },
                        common: {
                            name: `chunk-common`,
                            minChunks: 2,
                            priority: -20,
                            chunks: 'initial',
                            reuseExistingChunk: true
                        }
                    }
                }
            }
        }
    }
};

Сначала установите плагин webpack-bundle-analyzer, который может визуально анализировать упакованные файлы.

npm install webpack-bundle-analyzer --save-dev

существуетvue.config.jsВнедрить плагины в

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports={
    configureWebpack:config =>{
        return {
            plugins:[
                new BundleAnalyzerPlugin()
            ]
        }
    }
}

После упаковки он автоматически откроется в браузереhttp://127.0.0.1:8888/, как показано ниже

Найдет некоторыеchunk-vendors.jsдокумент. даcacheGroupsФайл js, упакованный программой поставщика.

Можно использоватьnameварианты измененияchunk-vendors.jsНазвание файла, код выглядит следующим образом

vendors: {
    name: `app-chunk-vendors`,
    test: /[\\/]node_modules[\\/]/,
    priority: -10,
    chunks: 'initial'
},

После упаковки вы найдетеchunk-vendors.jsФайл сталapp-chunk-vendors.jsфайл, содержимое которого остается неизменным.

3. Разделение входного файла

сначала удалитьcacheGroupsВнутри программы, а затем упаковать ее.

cacheGroups: {
    vendors: false,
    common: false
}

app.a502ce9a.jsа такжеchunk-be34ce9a.ceff3b64.jsЭти два файла js создаются проектомmain.jsЭтот файл пакета входа сгенерирован.

Напримерapp.js文件中有element-ui、moment、jquery、vue、router、store、jsencrypt等内容。 Это вmain.jsвведен в

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import JsEncrypt from 'jsencrypt';
import $ from 'jquery';
import ElementUI from 'element-ui';
Vue.use(ElementUI);
import treeSelect from 'fxft-tree-select';
Vue.use(treeSelect);
import moment from 'moment';
Vue.prototype.moment = moment;
//注册全局变量、全局函数
import base from 'service/base';
Vue.use(base);
//注册打印插件
import print from  'service/print';
Vue.use(print);
const vm = new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')
window.vm = vm;

Упаковка сгенерированаindex.html

<body>
    <div id=app></div>
    <script src=/js/app.a502ce9a.js></script>
</body>

показыватьapp.js是项目一开始就要加载的,会影响首屏的加载时间。 тогда ты можешьmain.js

import JsEncrypt from 'jsencrypt';
import treeSelect from 'fxft-tree-select';
Vue.use(treeSelect);
//注册全局变量、全局函数
import base from 'service/base';
Vue.use(base);
//注册打印插件
import print from  'service/print';
Vue.use(print);

app.jsОни ушли.

Почемуchunk-be34ce9a.jsтакже изmain.jsупакованный? Потому чтоmain.jsЕсть разделы кода:

//注册全局变量、全局函数
import base from 'service/base';
Vue.use(base);

смотреть вservice/base.jsВ файле

import('./Export2Excel').then(res => {
    res.export_json_to_excel(defaultOpition);
})

Export2Excel.jsзагружается асинхронно, вservice/Export2Excel.jsсередина

import { saveAs } from 'file-saver'
import XLSX from 'xlsx'

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

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

Если вы хотите отnode_modulesЗагруженный модуль, все упакованные в файл JS, как это сделать? Vue CLI3 помогла нам сделать.

cacheGroups: {
    vendors: {
        name: `chunk-vendors`,
        test: /[\\/]node_modules[\\/]/,
        priority: -10,
        chunks: 'initial'
    },
}

Его ядроtestварианты, подходящие элементы изnode_modulesМодули загружаются и извлекаются из сборки пакетаchunk-vendors.jsдокумент. После упаковки поиск по графику анализаnode_modulesнашел, что есть еще много файлов, содержащих изnode_modulesНагруженные модули, а ожидания не одинаковы.

ЭтоchunksОпционы в беде, стоимостьinitialУказывает, сколько раз, если XXX загружается или одновременно загружается в проект, то сколько раз модуль XXX будет извлекаться и упаковываться в разные файлы. Библиотека Core-JS загружается в каждый файл проекта, поэтому она будет извлечена несколько раз.

Покаchunksallnode_modulesЗагруженный модуль, все упакованные в файл JS.

Обнаружено, что размер chunk-vendors.js немного велик, с 1,91 МБ, который по-прежнему является файлом js, который необходимо загрузить при инициализации проекта.Если размер слишком велик, время загрузки первый экран будет слишком длинным. Для оптимизации есть два метода

Первое использование внешних для оптимизации смотрите в другой моей статье.

elementотchunk-vendors.jsИзвлечено, чтобы быть вcacheGroupsСредняя конфигурация:

element: {
    chunks: 'all',
    name: `element-ui`,
    test: /[\\/]element-ui[\\/]/,
    priority: 0,
},

из которых примечаниеpriorityвариант, чтобы извлечь элемент отдельно,priorityЗначение должно быть выше, чем в схеме поставщиковpriorityзначение большое, иначе он не может быть извлечен.

После упаковки вы можете увидеть, что элемент упакован, чтобы генерировать новыйelement-ui.jsРазмер файла chunk-vendors.js становится 1,27 МБ, что меньше исходных 1,91 МБ. Кроме того, вы можете самостоятельно извлекать сторонние зависимости, такие как xlsx, moment и jquery.

4. Разделение и слияние не входных файлов

На диаграмме анализа, кроме файла ввода, много js-файлов, и большинство этих файлов запакованы и сгенерированы компонентами в проекте.

Если вы реализуете ленивую загрузку маршрутов, используйте/*webpackChunkName:"[request]"*/, то в пакете, сгенерированном компонентомjsИмя документа, вы можете узнать этоjsКакой компонент генерирует упакованный файл.

Фигураbase_info_manage-group_info_set-ability_bind_set.85b419a1.jsнаходится в проектеviews/base_info_manage/group_info_set/bility_bind_set/index.vueЭтот компонент упакован.

base_info_manage-group_info_set-ability_bind_set-edit.08f91768.jsнаходится в проектеviews/base_info_manage/group_info_set/bility_bind_set/edit.vueЭтот компонент упакован.

Также найтиchunk-5c1416e3.1cbcb0ec.jsbase_info_manage-group_info_set-ability_bind_set-edit.08f91768.js的内容相似,只少了src/api的内容。 а такжеapi/common.js,api/ability_bind_set.js,edit.vue,mixinsПодождите, пока модуль будет перепакован несколько раз.

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

существуетcacheGroupsСредняя конфигурация

api: {
    name: 'api',
    test: /[\\/]api[\\/]/,
    priority: 0,
},

При извлечении нескольких make-файлов пакетов модулейnameНужны опции.

После упаковки посмотрите на схему анализа и вы обнаружите, чтоapi/common.js,api/ability_bind_set.jsОн был извлеченapi.05ad5193.jsбинго

Затем извлеките модуль mixins вcacheGroupsСредняя конфигурация

mixins: {
    name: 'mixins',
    test: /[\\/]mixins[\\/]/,
    priority: 0,
},

См. рис. Анализ, полученный после извлечения модулей упаковки примесей.mixins.8d1d6f50.jsсередина.

Затем извлекитеedit.vueМодуль вcacheGroupsСредняя конфигурация

base_info_manage: {
    name: 'base_info_manage',
    test: /[\\/]base_info_manage[\\/]/,
    minChunks: 2,
    priority: 0,
},

вminChunks

edit.vueмодуль был извлечен вbase_info_manage.d5c14c01.jsсередина.

если ты чувствуешьbase_info_manage.d5c14c01.jsФайл слишком большой, есть два способа справиться с ним.

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

base_info_manage: {
    name: 'base_info_manage',
    test: /[\\/]base_info_manage[\\/]/,
    minChunks: 2,
    priority: 0,
    maxSize: 102400
},

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

Второй — нажатьbase_info_manageподпапки в папке, чтобы продолжить извлечение, например.base_info_manageВ папке есть подфайл с именемgroup_info_set. существуетcacheGroupsСредняя конфигурация

group_info_set: {
    name: 'group_info_set',
    test: /[\\/]base_info_manage[\\/]group_info_set[\\/]/,
    minChunks: 2,
    priority: 10,
},

После упаковки посмотрите на схему анализа и вы обнаружите, чтоbase_info_manage.jsсерединаgroup_info_setКоллекция модулей была извлечена вgroup_info_set.jsв файле.base_info_manage.d5c14c01.jsФайлы также уменьшены соответственно.

Кроме того, вы можете поставитьsrc/api,src/mixins,src/serviceСодержимое пакета объединяется и упаковывается для создания файла js, который заменяет ранее упакованный и сгенерированныйmixins.8d1d6f50.jsа такжеapi.05ad5193.js

common: {
    test: /[\\/]api[\\/]|[\\/]mixins[\\/]|[\\/]src[\\/]service[\\/]/,
    priority: 0,
    name: 'common',
},

Больше нечего сказать, вы можете использовать плагин SplitChunks в своем собственном проекте, чтобы управлять Webpack для упаковки и создания того, что вы хотите, как описано выше.jsФайл доdist/jsjs

V. Резюме

Суть использования плагина SplitChunks для управления содержимым js-файлов, упакованных и сгенерированных Webpack, заключается в предотвращении повторной упаковки модулей, в разделении чрезмерно больших js-файлов и в объединении разбросанных js-файлов. Конечная цель — уменьшить размер запрашиваемого ресурса и количество запросов. Поскольку они противоречат друг другу, чтобы использовать плагин SplitChunks в соответствии с реальной ситуацией в проекте, необходимо помнить о среднем пути.