Vue2项目生产环境的打包优化

Vue2项目生产环境的打包优化

前言

在这篇文章我们讨论Vue2项目生产环境的打包优化,并按步骤展示实际优化过程中的修改和前后对比。

背景

优化的主要难点还是从哪里开始去优化,如果不清楚自己的项目问题出现在哪里,就显得比较盲目,不知道优化哪里,那在优化之前我们先分析一下我的文件依赖。

Vue2 项目使用 Vue脚手架 @vue/cli 也就是 vue-cli-service 打包,我们用 --report 选项,来生成 report.html 报告页面来分析打包文件的体积:

vue-cli-service build --report

运行打包命令,会自动弹出效果如下,通过该关系图得出依赖之间的关系,与文件大小,可以找到优化的方向,此时打包体积为48.71M。
在这里插入图片描述

优化

我们优化的过程,第一步是删除一些已经不再使用的依赖,第二步是针对体积大的第三方库,实现按需引入

步骤一:删除viser-vue

viser-vue底层依赖@antv/g2等库一并被删除,目前总体积为46.9M,减小了2M
在这里插入图片描述

步骤二:element-ui 按需引入

本段落介绍如何实现Element-UI组件库在Vue2项目中按需引入,具体步骤如下

1. main.js 按需引入

初始状态,我们在Vue2项目全量引入了 Element-UI,但是实际只应用到它的几个组件,如 Form, Button, Select 等,于是我们改为按需引入。

// from main.js
import Vue from 'vue'
import ElementUI from 'element-ui
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI )

我们改为仅仅引入需要的组件,并注册使用它们。这样打包过程就不会将 Element-UI 整个包加载进来,因为 webpack自动开启 tree-shaking,所以打包的时候只会将 Form, FormItem, Radio, InputNumber, Select, Button, Tabs, TabPane, Option 这几个依赖打进包里

// from main.js
import Vue from 'vue'

// ext library
// import ElementUI from 'element-ui'
import {
  Form,
  FormItem,
  Radio,
  InputNumber,
  Select,
  Button,
  Tabs,
  TabPane,
  Option
} from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';

// Vue.use(ElementUI)
Vue.component(Form.name, Form)
Vue.component(FormItem.name, FormItem)
Vue.component(Radio.name, Radio)
Vue.component(InputNumber.name, InputNumber)
Vue.component(Select.name, Select)
Vue.component(Button.name, Button)
Vue.component(Tabs.name, Tabs)
Vue.component(TabPane.name, TabPane)
Vue.component(Option.name, Option)

2. 安装 babel-plugin-component

项目根目录安装 babel-plugin-component,在终端运行:

yarn add babel-plugin-component -D

在这里插入图片描述

安装成功之后在 package.json 文件的 devDependencies 出现:
在这里插入图片描述

{
	"devDependencies": {
		"babel-plugin-component": "^1.1.1"
	}
}

在这里插入图片描述

3. 修改babel.config.js

// from babel.config.js
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)

const plugins = ["@babel/plugin-syntax-import-meta"]
if (IS_PROD) {
  plugins.push('transform-remove-console')
}

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    [
      '@babel/preset-env',
      {
        'useBuiltIns': 'entry',
        'corejs': 3
      }
    ]
  ],
  plugins
}

修改成下面:

// from babel.config.js
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)

const plugins = [
  "@babel/plugin-syntax-import-meta",
  [
    "component",
    {
      "libraryName": "element-ui",
      "styleLibraryName": "theme-chalk"
    }
  ]
]
if (IS_PROD) {
  plugins.push('transform-remove-console')
}

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    [
      '@babel/preset-env',
      {
        'useBuiltIns': 'entry',
        'corejs': 3,
        'modules': false
      }
    ]
  ],
  plugins
}

在这里插入图片描述
Element-UI 改为按需引入后,我们重新运行 yarn build 打包项目,在 dist/report.html中看到打包后的结果如图所示:
在这里插入图片描述
我们看到 Element-UI 的打包体积减小到了376KB,项目打包后总体积只有45.14MB,我们成功减小了1.8MB的体积

步骤三:monaco-editor 按需引入

分析现状

monaco-editor 目前在js是占6.08M的体积
在这里插入图片描述
monaco-editor 目前在js是占11.13M的体积
在这里插入图片描述

看到 monaco-editor 引入之后占用这么大的体积,为了验证猜测,尝试卸载与其有关的库包括 monaco-editor, vue-monaco-editor, monaco-editor-webpack-plugin
运行

yarn remove monaco-editor
yarn remove vue-monaco-editor
yarn remove monaco-editor-webpack-plugin

运行 yarn build 得到 dist/report.html 截图如下:

在这里插入图片描述

详情页面如下:
在这里插入图片描述
总打包体积已经降至22.32MB,减少了足足23MB,由此验证了推断,monaco-editor按需加载确实是一个成效明显的优化方向。

应用场景

首先我们分析monaco-editor在项目中的应用场景,我们用monaco编辑器只需编辑维护 python, jsonmarkdown 类型的代码,主题也只用到了 vsvs-dark,那接下来我们按照这两个思路去优化看看成效如何

解决方案

MonacoWebpackPlugin 帮助我们用 webpack 加载 monaco 编辑器时,做以下几件事:
1. 自动注入 getWorkerUrl 全局变量
2. 处理 worker 的编译配置
3. 自动引入控件和语言包
我们可以配置 monaco-editor-webpack-plugin,可用于通过仅选择某些语言或仅选择某些编辑器功能来生成较小的编辑器包,实现按需加载的需求。

new MonacoWebpackPlugin({
 languages:["javascript","css","html","json"],
 features:["coreCommands","find"]
})
MonacoWebpackPlugin 选项定义

可以将选项传递给 MonacoWebpackPlugin,可通过仅选择某些语言 languages 或仅选择某些编辑器功能 features 来生成较小的编辑器包,选项如下:

  • filename (string) - 工作脚本的自定义文件名模板,遵循与loader-utils’ interpolateName 一样的选项。用于添加基于内容的哈希,以便可以使用长效缓存标头来提供文件

    • 默认值: '[name].worker.js'
  • publicPath (string) - 工作脚本的自定义公共路径,覆盖此插件生成的文件将要提供的公共路径。 如果您想从当前源加载资源,请使用 “/”

    • 默认值: ''
  • languages (string[]) - 仅包含受支持语言的子集

  • 默认情况下,将包含 monaco-editor 所有语言

    一些语言共享 Web Worker,如果需要include以下语言,您还必须 include 负责实例化其共享 Web Worker 的语言:

    LanguageInstantiator
    javascripttypescript
    handlebarshtml
    scss, lesscss

    要查看所有可用语言的列表,您可以运行:

    import metadata from 'monaco-editor/esm/metadata'; console.log(metadata.languages);
    
  • features (string[]) - 用来设置仅包含编辑器功能的子集,默认情况包含 monaco-editor 的所有功能。除了列举所需包含的功能外,还可以排除特定的功能,需在其功能前面加上感叹号
    要查看所有可用功能的列表,您可以运行:

    import metadata from 'monaco-editor/esm/metadata';
    console.log(metadata.features);
    
  • globalAPI (boolean) - 指定编辑器 API 是否应通过全局monaco对象公开
    -默认值:false

配置MonacoWebpackPlugin
1. 配置语言 languages

MonacoWebpackPlugin默认包含的语言有:

[`abap`, `apex`, `azcli`, `bat`, `bicep`,
`cameligo`, `clojure`, `coffee`, `cpp`, `csharp`, `csp`,
`css`, 'dart', 'dockerfile', 'ecl', 'elixir', 'flow9',
'fsharp', 'go', 'graphql', 'handlebars', 'hcl', 'html',
'ini', 'java', 'javascript', 'json', 'julia', 'kotlin',
'less', 'lexon', 'liquid', 'lua', 'm3', 'markdown', 'mips',
'msdax', 'mysql', 'objective-c', 'pascal', 'pascaligo',
'perl', 'pgsql', 'php', 'pla', 'postiats', 'powerquery',
'powershell', 'protobuf', 'pug', 'python', 'qsharp', 'r',
'razor', 'redis', 'redshift', 'restructuredtext', 'ruby',
'rust', 'sb', 'scala', 'scheme', 'scss', 'shell', 'solidity',
'sophia', 'sparql', 'sql', 'st', 'swift', 'systemverilog',
'tcl', 'twig', 'typescript', 'vb', 'xml', 'yaml']

我们在应用场景中讲到,本项目只需要 python, markdownjson 类型语言,其他语言都是不需要的,因此将 vue.config.jsMonacoWebpackPlugin.languages 选项配置如下:
修改成以下:

// from vue.config.js
new MonacoWebpackPlugin({
 languages:["python","markdown","json"]
})
report

在这里插入图片描述
运行yarn build重新打包,观察到打包后的总体积从45.14MB降至30.96MB,减少了足足15MB的体积。

2. 配置功能 features

首先我们需要了解 MonacoWebpackPlugin 默认包含的控件有:

['accessibilityHelp', 'anchorSelect', 'bracketMatching', 'caretOperations',
'clipboard', 'codeAction', 'codelens', 'colorPicker', 'comment', 'contextmenu',
'coreCommands', 'cursorUndo', 'dnd', 'documentSymbols', 'find', 'folding',
'fontZoom', 'format', 'gotoError', 'gotoLine', 'gotoSymbol', 'hover',
'iPadShowKeyboard', 'inPlaceReplace', 'indentation', 'inlayHints',
'inlineCompletions', 'inspectTokens', 'linesOperations', 'linkedEditing',
'links', 'multicursor', 'parameterHints', 'quickCommand', 'quickHelp',
'quickOutline', 'referenceSearch', 'rename', 'smartSelect', 'snippets',
'suggest', 'toggleHighContrast', 'toggleTabFocusMode', 'transpose',
'unusualLineTerminators', 'viewportSemanticTokens', 'wordHighlighter',
'wordOperations', 'wordPartOperations']

在这里插入图片描述
在这里插入图片描述
目前 monaco-editor 的体积占6.07MB

这一步我们将 vue.config.js 修改成以下:

// from vue.config.js
new MonacoWebpackPlugin({
 languages:["python","markdown","json"],
 features: ["find"]
})

在这里插入图片描述
重新运行 yarn build打包项目,我们看到 dist/report.html 截图发现,monaco-editor 的打包体积仅仅降低了0.1MB,因此这个配置功能 features 的优化就忽略不计吧,最后撤回了修改,全量引入了功能控件 features

步骤四:tailwindcss 按需引入

我们观察到 tailwindcss 目前是占4.41MB的体积
在这里插入图片描述

分析

我们可以从生产版本中删除未使用的 CSS,以获得最佳性能。对此,官网给出的答案是修改purge选项,原文请查看optimizing-for-production

官网文档介绍到,在为生产环境构建时,应始终使用 Tailwind 的 purge 选项来对未使用的样式进行摇树优化并优化最终构建大小。

修改

新增 purge 选项在 tailwind.config.js 文件

purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}']

此列表应包括项目中按名称引用任何样式的所有文件。

修改如下:

// tailwind.config.js
module.exports = {
  purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

优化之后,我们重新运行yarn build,重新打包项目,我们观察到 tailwindcss 的体积现在只剩下21.75KB,项目的总体积从30.96MB降至26.57MB,减少了4.39MB
在这里插入图片描述

dist/report.html 截图,已经看不到tailwindcss了,因为体积确实大大减小了
在这里插入图片描述

步骤五:tinymce 按需引入

我们观察到 tinymce 目前是占3.31MB
在这里插入图片描述

还未找到有效方案

步骤六:butterfly-dag 按需引入

在这里插入图片描述
我们观察到 butterfly-dag 目前是占2.07MB的体积
首先按照官网介绍的进行尝试,引入 pack/index.js 而不是整个项目,但是编译报错了
在这里插入图片描述

环境

  1. ml-matrix@6.11.0
  2. butterfly-dag@4.3.29
  3. vue@2.7.8

全部引入(修改之前)

import { Node, Tips } from 'butterfly-dag'
按需引入(修改之后)
import { Node, Tips } from 'butterfly-dag/pack/index.js'

尝试解决方案

vue.config.js 加入以下配置,但是没能解决:

"plugins": [
"@babel/plugin-proposal-private-methods",
"@babel/plugin-proposal-private-property-in-object"
]

总结

体积从48.71MB降至26.57MB,降低了22.2MB,只有初始值的55%。

对于Vue项目打包速度优化,可以尝试以下几种方法: 1. 使用CDN:将一些常用的第三方库(如VueVuex、Vue Router等)从本地打包中移除,改为通过CDN引入。这样可以减少打包体积和加快打包速度。 2. 按需引入组件:在使用UI组件库时,可以考虑按需引入组件,而不是全部引入。这可以通过babel-plugin-component等工具来实现,减少不必要的打包和编译时间。 3. 代码拆分:将大型的代码块拆分成更小的模块,利用Webpack的代码分割功能(如异步加载、按需加载)来实现懒加载。这样可以减少初始加载时间,提升用户体验。 4. 优化图片:对于项目中的图片资源,可以使用压缩工具来减小图片大小,如使用imagemin-webpack-plugin等插件进行图片压缩。 5. 缓存和持久化:合理利用浏览器缓存和服务端缓存,减少不必要的请求和加载时间。另外,可以考虑使用localStorage或IndexedDB等技术进行数据持久化,减少数据加载时间。 6. 使用Tree Shaking:通过配置Webpack的tree shaking功能,可以剔除项目中未使用的代码,减少打包体积和提升加载速度。 7. 配置合理的Webpack:根据项目需求,合理配置Webpack的各项参数,如使用cache-loader、thread-loader等插件来提升构建速度。 需要注意的是,优化策略要根据具体项目情况进行选择,不同的项目可能有不同的瓶颈和优化空间。可以通过Webpack Bundle Analyzer等工具来分析打包结果,找出优化的重点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值