code spliting优化Vue打包步骤详解

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

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

核心思想

业务代码和基础库的分离

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

按需异步加载

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

实战

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

code spliting优化Vue打包步骤详解

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

code spliting优化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下了。

code spliting优化Vue打包步骤详解

code spliting优化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被打包进来了,那么问题来了,这样子好么?

code spliting优化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左右

code spliting优化Vue打包步骤详解

code spliting优化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。

code spliting优化Vue打包步骤详解

code spliting优化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。

code spliting优化Vue打包步骤详解

code spliting优化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打包步骤详解的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2766087.html

(0)
上一篇 2025年3月8日 11:08:55
下一篇 2025年3月3日 13:30:15

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • slot分发内容步骤详解

    这次给大家带来slot分发内容步骤详解,slot分发内容的注意事项有哪些,下面就是实战案例,一起来看一下。 一、什么是slot 在使用组件时,我们常常要像这样组合它们: 登录后复制 当需要让组件组合使用,混合父组件的内容与子组件的模板时,就…

    2025年3月8日
    200
  • props传递数据步骤详解

    这次给大家带来props传递数据步骤详解 ,props传递数据的注意事项有哪些,下面就是实战案例,一起来看一下。 在 Vue 中,父子组件的关系可以总结为 props向下传递,事件向上传递。父组件通过 props 给子组件下发数据,子组件通…

    2025年3月8日
    200
  • vue-i18n标准的使用步骤

    这次给大家带来vue-i18n标准的使用步骤,vue-i18n标准使用的注意事项有哪些,下面就是实战案例,一起来看一下。 需求 公司项目需要国际化,点击按钮切换中文/英文 1、安装 npm install vue-i18n –save 登…

    编程技术 2025年3月8日
    200
  • Vue做出内部组件轮播切换步骤详解

    这次给大家带来Vue做出内部组件轮播切换步骤详解,Vue做出内部组件轮播切换的注意事项有哪些,下面就是实战案例,一起来看一下。 对于那些不需要路由的内部组件,在切换的时候希望增加一个轮播过渡的效果,效果如下: 我们可以引入一个轮播组件,但是…

    2025年3月8日 编程技术
    200
  • Vue使用Sortable步骤详解

    这次给大家带来Vue使用Sortable步骤详解,Vue使用Sortable的注意事项有哪些,下面就是实战案例,一起来看一下。 之前开发一个后台管理系统,里面用到了Vue和Element-UI这个组件库,遇到一个挺有意思的问题,和大家分享一…

    编程技术 2025年3月8日
    200
  • JS实现动态进度条步骤分析

    这次给大家带来JS实现动态进度条步骤分析,JS实现动态进度条的注意事项有哪些,下面就是实战案例,一起来看一下。 本文实例为大家分享了js实现动态进度条效果的具体代码,供大家参考,具体内容如下 1.效果 2.源码 window.onload …

    2025年3月8日
    200
  • Nuxt.js实现服务端渲染步骤详解

    这次给大家带来Nuxt.js实现服务端渲染步骤详解,Nuxt.js实现服务端渲染的注意事项有哪些,下面就是实战案例,一起来看一下。 2016 年 10 月 25 日,zeit.co 背后的团队对外发布了一个 React 的服务端渲染应用框架…

    2025年3月8日 编程技术
    200
  • 实现js同源策略与跨域访问步骤详解

    这次给大家带来实现js同源策略与跨域访问步骤详解,实现js同源策略与跨域访问的注意事项有哪些,下面就是实战案例,一起来看一下。 1. 什么是同源策略 理解跨域首先必须要了解同源策略。同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。 …

    编程技术 2025年3月8日
    200
  • vue使用指定组件缓存步骤详解

    这次给大家带来vue使用指定组件缓存步骤详解,vue使用指定组件缓存的注意事项有哪些,下面就是实战案例,一起来看一下。 keep-alive 简介 keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染…

    编程技术 2025年3月8日
    200
  • Vue引用外部样式文件步骤详解

    这次给大家带来Vue引用外部样式文件步骤详解,Vue引用外部样式文件的注意事项有哪些,下面就是实战案例,一起来看一下。 问题描述 对于.vue的文件来说,也是由结构、行为、样式三部分组成,在样式部分有个scoped的属性,也就是当前页面有效…

    2025年3月8日
    200

发表回复

登录后才能评论