91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解Vue打包優化之code spliting

發布時間:2020-10-01 08:58:25 來源:腳本之家 閱讀:197 作者:林淙源tinylin 欄目:web開發

在http1的時代,比較常見的一種性能優化就是合并http的請求數量,通常我們會把許多js代碼合并在一起,但是如果一個js包體積特別大的話對于性能提升來說就有點矯枉過正了。而如果我們對所有的代碼進行合理的拆分,將首屏和非首屏的代碼進行剝離,將業務代碼和基礎庫代碼進行拆分,在需要某段代碼的時候再加載它,下次若再需要用則從緩存中讀取,一來可以更好地使用瀏覽器緩存,再者就是可以提高首屏加載速度,很好提升用戶的體驗。

核心思想

業務代碼和基礎庫的分離

這個其實很好理解,業務代碼通常更新迭代很頻繁,而基礎庫通常更新緩慢,這里做拆分的話可以充分利用瀏覽器緩存來加載基礎庫代碼。

按需異步加載

這個主要解決首屏請求大小的問題,我們在訪問首屏的時候只需要加載首屏所需的邏輯,而不是加載所有路由的代碼。

實戰

最近,采用vuetify改造了一個內部系統,一開始用了最常用的webpack配置,功能很快開發了,可是一打包,發現效果不是很明顯,打出很多大包

詳解Vue打包優化之code spliting

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

詳解Vue打包優化之code spliting

這里我們先貼一下配置,一邊一會兒分析時用:

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

詳解Vue打包優化之code spliting

詳解Vue打包優化之code spliting

這里我們可以得到一個經驗,就是在一個項目中可以專門針對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被打包進來了,那么問題來了,這樣子好么?

詳解Vue打包優化之code spliting

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

詳解Vue打包優化之code spliting

詳解Vue打包優化之code spliting

可是,這里我們發現vuetify.js和vuetify.css實在太龐大了,導致我們的打包的代碼很大,這里,我們考慮把它提取出來,這里為了避免重復打包,需要使用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中之前對vuetifycss的引入
//import 'vuetify/dist/vuetify.css'

再修改webpack配置,新增externals

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

再重新打包,可以看到vue相關的代碼已經沒有了,目前也只有used-twice-app.js比較大了,app.js縮小了近200kb。

詳解Vue打包優化之code spliting

詳解Vue打包優化之code spliting

但是新問題又來了,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。

詳解Vue打包優化之code spliting

詳解Vue打包優化之code spliting

做了上面這么多的優化之后,業務測的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
 })
 ])
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

洛南县| 曲周县| 象山县| 白玉县| 镇江市| 临清市| 兴安县| 荆门市| 新乡县| 象山县| 嘉义县| 宝兴县| 扎赉特旗| 棋牌| 定陶县| 大安市| 隆化县| 巩留县| 金溪县| 高碑店市| 咸宁市| 梨树县| 嵊泗县| 高台县| 鹤山市| 尼木县| 哈巴河县| 右玉县| 辽宁省| 辰溪县| 云南省| 九龙坡区| 来宾市| 汉阴县| 米泉市| 文山县| 北海市| 扬中市| 丰原市| 崇阳县| 边坝县|