100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Vue打包优化之code spliting_vue.js

Vue打包优化之code spliting_vue.js

时间:2019-12-18 10:30:30

相关推荐

Vue打包优化之code spliting_vue.js

web前端|js教程

javascript,spliting,vue.js

web前端-js教程

这篇文章主要介绍了详解Vue打包优化之code spliting,现在分享给大家,有需要的朋友参考一下

phpo2o网站源码,ubuntu 怎么卸载脚本,win7咋安装tomcat,java爬虫网络异常,php编程教程免费视频学习,seo送个查询lzw

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

cpa源码怎么办,vscode文件感叹号,ubuntu 16 亮度,tomcat及负载均衡,爬虫post登录,php获取url路径,seo推广解决方案分类,伪原网站源码,织梦淘宝客免费模板lzw

核心思想

ssh框架erp项目源码下载,vscode离线安装拓展,ubuntu m,tomcat深入剖析,如何使用sqlite存储数据,奢侈品网页设计,aspcms数据库文件,阿里云服务器网络,bootstrap图表插件下载,前端框架实训报告ppt,爬虫编程语言,dump php,seo伪静态,springboot 新建,灵动标签内怎么使用当前页面标题,国内 扁平化 网站,pdf网页在线阅读代码,论坛静态模板,织梦后台添加的变量怎么删除,最好的web页面播放器,学生信息管理系统下载,dedecms程序模板lzw

业务代码和基础库的分离

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

按需异步加载

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

实战

最近,采用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: abel-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 monsChunkPlugin({ name: ventor }), ]}if (process.env.NODE_ENV === production) { module.exports.devtool = #source-map // http://vue-/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 monsChunkPlugin({ name: vendor, minChunks: ({ resource }) => ( resource && resource.indexOf( ode_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.vueimport system from ../views/system.vue

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

async

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

new monsChunkPlugin({ 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: abel-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 monsChunkPlugin({ name: ventor, minChunks: ({ resource }) => ( resource && resource.indexOf( ode_modules) >= 0 && resource.match(/\.js$/) ) }), new monsChunkPlugin({ 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 }) ])}

vue.js中created方法的使用详解

如何修改Vue.js中scoped模式下的子组件内部标签样式

Vue中computed与methods的区别详解_vue.js

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。