热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

codespliting优化Vue打包步骤详解

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


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

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

核心思想

业务代码和基础库的分离

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

按需异步加载

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

实战

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

codespliting优化Vue打包步骤详解 - 文章图片

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

codespliting优化Vue打包步骤详解 - 文章图片

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

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下了。

codespliting优化Vue打包步骤详解 - 文章图片

codespliting优化Vue打包步骤详解 - 文章图片

这里我们可以得到一个经验,就是在一个项目中可以专门针对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被打包进来了,那么问题来了,这样子好么?

codespliting优化Vue打包步骤详解 - 文章图片

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左右

codespliting优化Vue打包步骤详解 - 文章图片

codespliting优化Vue打包步骤详解 - 文章图片

可是,这里我们发现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。

codespliting优化Vue打包步骤详解 - 文章图片

codespliting优化Vue打包步骤详解 - 文章图片

但是新问题又来了,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。

codespliting优化Vue打包步骤详解 - 文章图片

codespliting优化Vue打包步骤详解 - 文章图片

做了上面这么多的优化之后,业务测的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
})
])
}

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

推荐阅读:

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

bing Map使用步骤详解

以上就是code spliting优化Vue打包步骤详解的详细内容,更多请关注其它相关文章!



推荐阅读
  • vue使用
    关键词: ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了在Oracle数据库中创建序列时如何选择cache或nocache参数。cache参数可以提高序列的存取速度,但可能会导致序列丢失;nocache参数可以避免序列丢失,但在高并发访问时可能导致性能问题。文章详细解释了两者的区别和使用场景。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
author-avatar
多米音乐_35794462
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有