最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Vue打包優(yōu)化之code spliting

 更新時(shí)間:2018年04月09日 16:54:47   作者:林淙源tinylin  
這篇文章主要介紹了詳解Vue打包優(yōu)化之code spliting,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

在http1的時(shí)代,比較常見(jiàn)的一種性能優(yōu)化就是合并http的請(qǐng)求數(shù)量,通常我們會(huì)把許多js代碼合并在一起,但是如果一個(gè)js包體積特別大的話對(duì)于性能提升來(lái)說(shuō)就有點(diǎn)矯枉過(guò)正了。而如果我們對(duì)所有的代碼進(jìn)行合理的拆分,將首屏和非首屏的代碼進(jìn)行剝離,將業(yè)務(wù)代碼和基礎(chǔ)庫(kù)代碼進(jìn)行拆分,在需要某段代碼的時(shí)候再加載它,下次若再需要用則從緩存中讀取,一來(lái)可以更好地使用瀏覽器緩存,再者就是可以提高首屏加載速度,很好提升用戶的體驗(yàn)。

核心思想

業(yè)務(wù)代碼和基礎(chǔ)庫(kù)的分離

這個(gè)其實(shí)很好理解,業(yè)務(wù)代碼通常更新迭代很頻繁,而基礎(chǔ)庫(kù)通常更新緩慢,這里做拆分的話可以充分利用瀏覽器緩存來(lái)加載基礎(chǔ)庫(kù)代碼。

按需異步加載

這個(gè)主要解決首屏請(qǐng)求大小的問(wèn)題,我們?cè)谠L問(wèn)首屏的時(shí)候只需要加載首屏所需的邏輯,而不是加載所有路由的代碼。

實(shí)戰(zhàn)

最近,采用vuetify改造了一個(gè)內(nèi)部系統(tǒng),一開(kāi)始用了最常用的webpack配置,功能很快開(kāi)發(fā)了,可是一打包,發(fā)現(xiàn)效果不是很明顯,打出很多大包

這里我們看下打包分布,這里使用的是 webpack-bundle-analyzer,可以很清晰的看到 vue 和 vuetify等模塊都有出現(xiàn) 被重復(fù)打包的情況。

這里我們先貼一下配置,一邊一會(huì)兒分析時(shí)用:

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: '逍遙系統(tǒng)',
 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入口這里我們發(fā)現(xiàn)并沒(méi)有篩選出所有引用的node_module下的模塊 ,比如axios ,所以導(dǎo)致打包到了app.js里了,這里我們做下分離

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

那這里又出現(xiàn)個(gè)問(wèn)題了,我不可能手動(dòng)去手動(dòng)錄入模塊,這時(shí)我們可能需要 自動(dòng)化分離 ventor,這里我們需要引入 minChunks,在配置中我們就可以對(duì)所有mode_module下所引用的模塊進(jìn)行打包 修改配置如下

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$/)
  )
 }),

經(jīng)過(guò)上面幾步的優(yōu)化,我們?cè)倏纯次募植迹瑫?huì)發(fā)現(xiàn)node_module下的模塊都收歸到了vendor下了。

這里我們可以得到一個(gè)經(jīng)驗(yàn),就是在一個(gè)項(xiàng)目中可以專門(mén)針對(duì)node_module下的模塊進(jìn)行打包優(yōu)化。但是這里細(xì)心的你可能發(fā)現(xiàn)codemirror組件不也是node_module中的么,但為啥沒(méi)被打包進(jìn)去反而重復(fù)打包到其他單頁(yè)面了呢,其實(shí)這里是因?yàn)樵赾ommonChunk中使用name屬性其實(shí)也就意味著只會(huì)沿著entry入口去找尋所依賴的包,由于我們的組件采用的是異步加載,故這里就不會(huì)去打包了,我們做個(gè)實(shí)驗(yàn)驗(yàn)證下,現(xiàn)在我們?nèi)サ鬱bmanage和system頁(yè)面的路由懶加載改為直接引入

// 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'

這時(shí)我們重新打包可以發(fā)現(xiàn),codemirror被打包進(jìn)來(lái)了,那么問(wèn)題來(lái)了,這樣子好么?

async

上面的問(wèn)題答案是肯定的,不可以的,很明顯ventor是我們的入口代碼即首屏,我們完全沒(méi)有必要去加載這個(gè)codemirror組件,我們先把剛才的路由修改恢復(fù)回去,但是這時(shí)又有了新問(wèn)題,我們的codemirror被同時(shí)打包進(jìn)了兩個(gè)單頁(yè)面,并且還有些自己封裝的components,例如MTable或是MDataTable等也出現(xiàn)了重復(fù)打包。并且codemirror特別大,同時(shí)加載到兩個(gè)單頁(yè)面也會(huì)造成很大的性能問(wèn)題,簡(jiǎn)單說(shuō)就是,我們?cè)谠L問(wèn)第一個(gè)單頁(yè)面加載了codemirror之后,在第二個(gè)頁(yè)面其實(shí)就不應(yīng)該再加載了。 要解決這個(gè)問(wèn)題,這里我們可以使用 CommonsChunkPlugin 的 async 并在 minChunnks 里的count方法來(lái)判斷數(shù)量,只要是 重用次數(shù) 超過(guò)兩個(gè)包括兩個(gè)的異步加載模塊(即 import () 產(chǎn)生的chunk )我們都認(rèn)為是 可以 打成公共的 ,這里我們?cè)黾右豁?xiàng)配置。

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

再次打包,我們發(fā)現(xiàn)所有服用的組件被重新打到了 0.used-twice-app.js中了,這樣各個(gè)單頁(yè)面大小也有所下降,平均小了近10k左右

可是,這里我們發(fā)現(xiàn)vuetify.js和vuetify.css實(shí)在太龐大了,導(dǎo)致我們的打包的代碼很大,這里,我們考慮把它提取出來(lái),這里為了避免重復(fù)打包,需要使用external,并將vue以及vuetify的代碼采用cdn讀取的方式,首先修改index.html

//css引入
<link  rel="stylesheet" type="text/css">
<link  rel="external nofollow" rel="stylesheet">
//js引入
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.js"></script>

//去掉main.js中之前對(duì)vuetifycss的引入
//import 'vuetify/dist/vuetify.css'

再修改webpack配置,新增externals

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

再重新打包,可以看到vue相關(guān)的代碼已經(jīng)沒(méi)有了,目前也只有used-twice-app.js比較大了,app.js縮小了近200kb。

但是新問(wèn)題又來(lái)了,codemirror很大,而used-twice又是首屏需要的,這個(gè)打包在首屏肯定不是很好,這里我們要將system和dbmanage頁(yè)面的codemirror組件改為異步加載,單獨(dú)打包,修改如下:

// import MCode from "../component/MCode.vue"; //注釋掉

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

重新打包下,可以看到 codemirror被抽離了,首屏代碼進(jìn)一步得到了減少,used-twice-app.js代碼縮小了近150k。

做了上面這么多的優(yōu)化之后,業(yè)務(wù)測(cè)的js基本都被拆到了50kb一下(忽略map文件),算是優(yōu)化成功了。

總結(jié)

可能會(huì)有朋友會(huì)問(wèn),單獨(dú)分拆vue和vuetify會(huì)導(dǎo)致請(qǐng)求數(shù)增加,這里我想補(bǔ)充下,我們的業(yè)務(wù)現(xiàn)在已經(jīng)切換成http2了,由于多路復(fù)用,并且加上瀏覽器緩存,我們分拆出的請(qǐng)求數(shù)其實(shí)也算是控制在合理的范疇內(nèi)。

這里最后貼一下優(yōu)化后的webpack配置,大家一起交流學(xué)習(xí)下哈。

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: '逍遙系統(tǒng)',
 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
 })
 ])
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue filter 完美時(shí)間日期格式的代碼

    vue filter 完美時(shí)間日期格式的代碼

    這篇文章主要介紹了vue filter 完美時(shí)間日期格式的方法,文中給大家提到了vue filter方法-時(shí)間格式化 的代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2019-08-08
  • Vue項(xiàng)目el-upload?上傳文件及回顯照片和下載文件功能實(shí)現(xiàn)

    Vue項(xiàng)目el-upload?上傳文件及回顯照片和下載文件功能實(shí)現(xiàn)

    本次需求是上傳多種固定格式的文件,且回顯的時(shí)候,圖片可以正常顯示,文件可以進(jìn)行下載,主要采用element的el-upload組件實(shí)現(xiàn),對(duì)Vue項(xiàng)目el-upload?上傳文件及回顯照片和下載文件功能實(shí)現(xiàn)感興趣的朋友跟隨小編一起看看吧
    2023-12-12
  • 如何使用vue實(shí)現(xiàn)跨域訪問(wèn)第三方http請(qǐng)求

    如何使用vue實(shí)現(xiàn)跨域訪問(wèn)第三方http請(qǐng)求

    這篇文章主要介紹了如何使用vue實(shí)現(xiàn)跨域訪問(wèn)第三方http請(qǐng)求,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-03-03
  • vue項(xiàng)目base64轉(zhuǎn)img方式

    vue項(xiàng)目base64轉(zhuǎn)img方式

    這篇文章主要介紹了vue項(xiàng)目base64轉(zhuǎn)img方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue 添加和編輯用同一個(gè)表單,el-form表單提交后清空表單數(shù)據(jù)操作

    vue 添加和編輯用同一個(gè)表單,el-form表單提交后清空表單數(shù)據(jù)操作

    這篇文章主要介紹了vue 添加和編輯用同一個(gè)表單,el-form表單提交后清空表單數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • Vue3中的pinia使用方法總結(jié)(建議收藏版)

    Vue3中的pinia使用方法總結(jié)(建議收藏版)

    Pinia是Vue的存儲(chǔ)庫(kù),它允許您跨組件/頁(yè)面共享狀態(tài),Pinia的成功可以歸功于他管理存儲(chǔ)數(shù)據(jù)的獨(dú)特功,下面這篇文章主要給大家介紹了關(guān)于Vue3中pinia使用方法的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • mint-ui在vue中的使用示例

    mint-ui在vue中的使用示例

    Mint UI 是 由餓了么前端團(tuán)隊(duì)推出的 一個(gè)基于 Vue.js 的移動(dòng)端組件庫(kù),這篇文章主要介紹了mint-ui在vue中的使用示例,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下
    2018-04-04
  • Vue3中ref與toRef的區(qū)別淺析

    Vue3中ref與toRef的區(qū)別淺析

    我們知道ref可以用于創(chuàng)建一個(gè)響應(yīng)式數(shù)據(jù),而toRef也可以創(chuàng)建一個(gè)響應(yīng)式數(shù)據(jù),這篇文章主要給大家介紹了關(guān)于Vue3中ref與toRef區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • 關(guān)于Vue中的全局導(dǎo)航守衛(wèi)(beforeEach、afterEach)

    關(guān)于Vue中的全局導(dǎo)航守衛(wèi)(beforeEach、afterEach)

    這篇文章主要介紹了關(guān)于Vue中的全局導(dǎo)航守衛(wèi)(beforeEach、afterEach),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • vue中的路由傳值與重調(diào)本路由改變參數(shù)

    vue中的路由傳值與重調(diào)本路由改變參數(shù)

    這篇文章主要介紹了vue中的路由傳值與重調(diào)本路由改變參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09

最新評(píng)論

堆龙德庆县| 项城市| 阿瓦提县| 华安县| 湘潭县| 平昌县| 高平市| 榕江县| 九台市| 当阳市| 青铜峡市| 日喀则市| 神农架林区| 阆中市| 龙泉市| 陆川县| 安多县| 阳高县| 新泰市| 布拖县| 迭部县| 虹口区| 凤凰县| 赫章县| 文山县| 富裕县| 图们市| 阳山县| 京山县| 普安县| 宜州市| 濮阳市| 绥宁县| 明光市| 无为县| 寻乌县| 鹤岗市| 太谷县| 澳门| 宣武区| 沽源县|