0

0

code spliting优化Vue打包步骤详解

php中世界最好的语言

php中世界最好的语言

发布时间:2018-04-28 16:22:44

|

1981人浏览过

|

来源于php中文网

原创

这次给大家带来code spliting优化Vue打包步骤详解,code spliting优化Vue打包的注意事项有哪些,下面就是实战案例,一起来看一下。

在http1的时代,比较常见的一种性能优化就是合并http的请求数量,通常我们会把许多js代码合并在一起,但是如果一个js包体积特别大的话对于性能提升来说就有点矫枉过正了。而如果我们对所有的代码进行合理的拆分,将首屏和非首屏的代码进行剥离,将业务代码和基础库代码进行拆分,在需要某段代码的时候再加载它,下次若再需要用则从缓存中读取,一来可以更好地使用浏览器缓存,再者就是可以提高首屏加载速度,很好提升用户的体验。

核心思想

业务代码和基础库的分离

这个其实很好理解,业务代码通常更新迭代很频繁,而基础库通常更新缓慢,这里做拆分的话可以充分利用浏览器缓存来加载基础库代码。

按需异步加载

这个主要解决首屏请求大小的问题,我们在访问首屏的时候只需要加载首屏所需的逻辑,而不是加载所有路由的代码。

实战

最近,采用vuetify改造了一个内部系统,一开始用了最常用的webpack配置,功能很快开发了,可是一打包,发现效果不是很明显,打出很多大包

这里我们看下打包分布,这里使用的是 webpack-bundle-analyzer,可以很清晰的看到 vue 和 vuetify等模块都有出现 被重复打包的情况。

这里我们先贴一下配置,一边一会儿分析时用:

const path = require('path')
const webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const generateHtml = new HtmlWebpackPlugin({
 title: '逍遥系统',
 template: './src/index.html',
 minify: {
 removeComments: true
 }
})
module.exports = {
 entry: {
 vendor: ['vue', 'vue-router', 'vuetify'],
 app: './src/main.js'
 },
 output: {
 path: path.resolve(dirname, './dist'),
 filename: '[name].[hash].js',
 chunkFilename:'[id].[name].[chunkhash].js'
 },
 resolve: {
 extensions: ['.js', '.vue'],
 alias: {
  'vue$': 'vue/dist/vue.esm.js',
  'public': path.resolve(dirname, './public')
 }
 },
 module: {
 rules: [
  {
  test: /\.vue$/,
  loader: 'vue-loader',
  options: {
   loaders: {
   }
   // other vue-loader options go here
  }
  },
  {
  test: /\.js$/,
  loader: 'babel-loader',
  exclude: /node_modules/
  },
  {
  test: /\.(png|jpg|gif|svg)$/,
  loader: 'file-loader',
  options: {
   objectAssign: 'Object.assign'
  }
  },
  {
  test: /\.css$/,
  loader: ['style-loader', 'css-loader']
  },
  {
  test: /\.styl$/,
  loader: ['style-loader', 'css-loader', 'stylus-loader']
  }
 ]
 },
 devServer: {
 historyApiFallback: true,
 noInfo: true
 },
 performance: {
 hints: false
 },
 devtool: '#eval-source-map',
 plugins: [
  new BundleAnalyzerPlugin(),
  new CleanWebpackPlugin(['dist']),
  generateHtml,
  new webpack.optimize.CommonsChunkPlugin({
  name: 'ventor'
  }),
 ]
}
if (process.env.NODE_ENV === 'production') {
 module.exports.devtool = '#source-map'
 // http://vue-loader.vuejs.org/en/workflow/production.html
 module.exports.plugins = (module.exports.plugins || []).concat([
 new webpack.DefinePlugin({
  'process.env': {
  NODE_ENV: '"production"'
  }
 }),
 new webpack.optimize.UglifyJsPlugin({
  sourceMap: true,
  compress: {
  warnings: false
  }
 }),
 new webpack.LoaderOptionsPlugin({
  minimize: true
 })
 ])
}

CommonChunkPlugin

ventor入口这里我们发现并没有筛选出所有引用的node_module下的模块 ,比如axios ,所以导致打包到了app.js里了,这里我们做下分离

entry: {
 vendor: ['vue', 'vue-router', 'vuetify', 'axios'],
 app: './src/main.js'
 },

那这里又出现个问题了,我不可能手动去手动录入模块,这时我们可能需要 自动化分离 ventor,这里我们需要引入 minChunks,在配置中我们就可以对所有mode_module下所引用的模块进行打包 修改配置如下

entry: {
 //vendor: ['vue', 'vue-router', 'vuetify', 'axios'], //删除
 app: './src/main.js'
 }
new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: ({ resource }) => (
   resource &&
   resource.indexOf('node_modules') >= 0 &&
   resource.match(/\.js$/)
  )
 }),

经过上面几步的优化,我们再看看文件分布,会发现node_module下的模块都收归到了vendor下了。

这里我们可以得到一个经验,就是在一个项目中可以专门针对node_module下的模块进行打包优化。但是这里细心的你可能发现codemirror组件不也是node_module中的么,但为啥没被打包进去反而重复打包到其他单页面了呢,其实这里是因为在commonChunk中使用name属性其实也就意味着只会沿着entry入口去找寻所依赖的包,由于我们的组件采用的是异步加载,故这里就不会去打包了,我们做个实验验证下,现在我们去掉dbmanage和system页面的路由懒加载改为直接引入

// const dbmanage = () => import(/* webpackChunkName: "dbmanage" */'../views/dbmanage.vue')
// const system = () => import(/* webpackChunkName: "system" */'../views/system.vue')
import dbmanage from '../views/dbmanage.vue'
import system from '../views/system.vue'

这时我们重新打包可以发现,codemirror被打包进来了,那么问题来了,这样子好么?

async

上面的问题答案是肯定的,不可以的,很明显ventor是我们的入口代码即首屏,我们完全没有必要去加载这个codemirror组件,我们先把刚才的路由修改恢复回去,但是这时又有了新问题,我们的codemirror被同时打包进了两个单页面,并且还有些自己封装的components,例如MTable或是MDataTable等也出现了重复打包。并且codemirror特别大,同时加载到两个单页面也会造成很大的性能问题,简单说就是,我们在访问第一个单页面加载了codemirror之后,在第二个页面其实就不应该再加载了。 要解决这个问题,这里我们可以使用 CommonsChunkPlugin 的 async 并在 minChunnks 里的count方法来判断数量,只要是 重用次数 超过两个包括两个的异步加载模块(即 import () 产生的chunk )我们都认为是 可以 打成公共的 ,这里我们增加一项配置。

new webpack.optimize.CommonsChunkPlugin({
 async: 'used-twice',
 minChunks: (module, count) => (
 count >= 2
 ),
})

再次打包,我们发现所有服用的组件被重新打到了 0.used-twice-app.js中了,这样各个单页面大小也有所下降,平均小了近10k左右

可是,这里我们发现vuetify.js和vuetify.css实在太庞大了,导致我们的打包的代码很大,这里,我们考虑把它提取出来,这里为了避免重复打包,需要使用external,并将vue以及vuetify的代码采用cdn读取的方式,首先修改index.html

//css引入


//js引入


//去掉main.js中之前对vuetifycss的引入
//import 'vuetify/dist/vuetify.css'

再修改webpack配置,新增externals

externals: {
 'vue':'Vue',
 "vuetify":"Vuetify"
 }

再重新打包,可以看到vue相关的代码已经没有了,目前也只有used-twice-app.js比较大了,app.js缩小了近200kb。

但是新问题又来了,codemirror很大,而used-twice又是首屏需要的,这个打包在首屏肯定不是很好,这里我们要将system和dbmanage页面的codemirror组件改为异步加载,单独打包,修改如下:

// import MCode from "../component/MCode.vue"; //注释掉
components: {
  MDialog,
  MCode: () => import(/* webpackChunkName: "MCode" */'../component/MCode.vue')
 },

重新打包下,可以看到 codemirror被抽离了,首屏代码进一步得到了减少,used-twice-app.js代码缩小了近150k。

做了上面这么多的优化之后,业务测的js基本都被拆到了50kb一下(忽略map文件),算是优化成功了。

总结

可能会有朋友会问,单独分拆vue和vuetify会导致请求数增加,这里我想补充下,我们的业务现在已经切换成http2了,由于多路复用,并且加上浏览器缓存,我们分拆出的请求数其实也算是控制在合理的范畴内。

这里最后贴一下优化后的webpack配置,大家一起交流学习下哈。

const path = require('path')
const webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const generateHtml = new HtmlWebpackPlugin({
 title: '逍遥系统',
 template: './src/index.html',
 minify: {
 removeComments: true
 }
})
module.exports = {
 entry: {
 app: './src/main.js'
 },
 output: {
 path: path.resolve(dirname, './dist'),
 filename: '[name].[hash].js',
 chunkFilename:'[id].[name].[chunkhash].js'
 },
 resolve: {
 extensions: ['.js', '.vue'],
 alias: {
  'vue$': 'vue/dist/vue.esm.js',
  'public': path.resolve(dirname, './public')
 }
 },
 externals: {
 'vue':'Vue',
 "vuetify":"Vuetify"
 },
 module: {
 rules: [
  {
  test: /\.vue$/,
  loader: 'vue-loader',
  options: {
   loaders: {
   }
   // other vue-loader options go here
  }
  },
  {
  test: /\.js$/,
  loader: 'babel-loader',
  exclude: /node_modules/
  },
  {
  test: /\.(png|jpg|gif|svg)$/,
  loader: 'file-loader',
  options: {
   objectAssign: 'Object.assign'
  }
  },
  {
  test: /\.css$/,
  loader: ['style-loader', 'css-loader']
  },
  {
  test: /\.styl$/,
  loader: ['style-loader', 'css-loader', 'stylus-loader']
  }
 ]
 },
 devServer: {
 historyApiFallback: true,
 noInfo: true
 },
 performance: {
 hints: false
 },
 devtool: '#eval-source-map',
 plugins: [
  new CleanWebpackPlugin(['dist']),
  generateHtml
 ]
}
if (process.env.NODE_ENV === 'production') {
 module.exports.devtool = '#source-map'
 module.exports.plugins = (module.exports.plugins || []).concat([
 new BundleAnalyzerPlugin(),
 new webpack.optimize.CommonsChunkPlugin({
  name: 'ventor',
  minChunks: ({ resource }) => (
  resource &&
  resource.indexOf('node_modules') >= 0 &&
  resource.match(/\.js$/)
  )
 }),
 new webpack.optimize.CommonsChunkPlugin({
  async: 'used-twice',
  minChunks: (module, count) => (
  count >= 2
  ),
 }),
 new webpack.DefinePlugin({
  'process.env': {
  NODE_ENV: '"production"'
  }
 }),
 new webpack.optimize.UglifyJsPlugin({
  sourceMap: true,
  compress: {
  warnings: false
  }
 }),
 new webpack.LoaderOptionsPlugin({
  minimize: true
 })
 ])
}

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Haiper
Haiper

一个感知模型驱动的AI视频生成和重绘工具,提供文字转视频、图片动画化、视频重绘等功能

下载

vue2.0实现注册登录步骤详解

bing Map使用步骤详解

相关专题

更多
php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

4

2025.12.31

视频文件格式
视频文件格式

本专题整合了视频文件格式相关内容,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

不受国内限制的浏览器大全
不受国内限制的浏览器大全

想找真正自由、无限制的上网体验?本合集精选2025年最开放、隐私强、访问无阻的浏览器App,涵盖Tor、Brave、Via、X浏览器、Mullvad等高自由度工具。支持自定义搜索引擎、广告拦截、隐身模式及全球网站无障碍访问,部分更具备防追踪、去谷歌化、双内核切换等高级功能。无论日常浏览、隐私保护还是突破地域限制,总有一款适合你!

7

2025.12.31

出现404解决方法大全
出现404解决方法大全

本专题整合了404错误解决方法大全,阅读专题下面的文章了解更多详细内容。

42

2025.12.31

html5怎么播放视频
html5怎么播放视频

想让网页流畅播放视频?本合集详解HTML5视频播放核心方法!涵盖<video>标签基础用法、多格式兼容(MP4/WebM/OGV)、自定义播放控件、响应式适配及常见浏览器兼容问题解决方案。无需插件,纯前端实现高清视频嵌入,助你快速打造现代化网页视频体验。

4

2025.12.31

关闭win10系统自动更新教程大全
关闭win10系统自动更新教程大全

本专题整合了关闭win10系统自动更新教程大全,阅读专题下面的文章了解更多详细内容。

3

2025.12.31

阻止电脑自动安装软件教程
阻止电脑自动安装软件教程

本专题整合了阻止电脑自动安装软件教程,阅读专题下面的文章了解更多详细教程。

3

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

2

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP代码整洁之道
PHP代码整洁之道

共7课时 | 6.4万人学习

http状态码大全
http状态码大全

共47课时 | 106.7万人学习

phpcms开发教程
phpcms开发教程

共70课时 | 24.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号