ホームページ  >  記事  >  ウェブフロントエンド  >  Vue のパッケージ化手順を最適化するためのコード分割の詳細な説明

Vue のパッケージ化手順を最適化するためのコード分割の詳細な説明

php中世界最好的语言
php中世界最好的语言オリジナル
2018-04-28 16:22:441824ブラウズ

今回は、Vue のパッケージ化を最適化するためのコード分割の手順について詳しく説明します。Vue のパッケージ化を最適化するためのコード分割の 注意事項 は何ですか?実際のケースを見てみましょう。

http1 の時代では、より一般的な

パフォーマンス最適化 の 1 つは、http リクエストの数をマージすることです。通常、多くの JS コードを一緒にマージしますが、JS パッケージのサイズが特に大きい場合は、オーバーキルのパフォーマンスを向上させるのは少し困難です。そして、すべてのコードを合理的に分割し、最初の画面と非最初の画面のコードを剥がし、ビジネス コードと基本ライブラリのコードを分割し、必要なときに特定のコード部分をロードする場合は、次回必要に応じてロードします。もう一度使用すると、キャッシュから読み取れます。第 1 に、ブラウザのキャッシュを有効に活用できるため、最初の画面の読み込み速度が向上し、ユーザー エクスペリエンスが大幅に向上します。

コアアイデア

ビジネスコードと基本ライブラリの分離

これは実際には理解しやすいですが、ビジネスコードは通常頻繁に更新され、基本ライブラリは通常ゆっくりと更新されます。ブラウザのキャッシュを最大限に活用して、基本的なライブラリ コードをロードします。

オンデマンドの非同期ロード

これは主に、最初の画面にアクセスするときに、すべてのルーティング コードをロードするのではなく、最初の画面に必要なロジックをロードするだけで済みます。

実践的な戦闘

最近、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: '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 入口 ここで、axios など、node_module の下にあるすべての参照モジュールがフィルタリングされていないことがわかりました。 app.js がパッケージ化されていたので、ここで分離を行います

entry: {
 vendor: ['vue', 'vue-router', 'vuetify', 'axios'],
 app: './src/main.js'
 },
次に、ここでモジュールを手動で入力することは不可能です。ここで、ベンターを自動的に分離する必要があるかもしれません。 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 の下にあるモジュールがすべて収集されていることがわかります。提供事業者。

ここで経験を得ることができます。つまり、プロジェクトでは、node_module の下のモジュールを具体的にパッケージ化して最適化できます。しかし、ここで注意してみると、codemirror コンポーネントは、node_module にもあるのに、パッケージ化されずに他の単一ページに繰り返しパッケージ化されるのはなぜでしょうか。実際、これは、commonChunk で name 属性を使用することは、実際には Follow のみを意味するためです。コンポーネントは非同期でロードされるため、ここではパッケージ化されません。ここで、dbmanage およびシステム ページのルーティング遅延ロードを削除し、直接導入に変更します。
// 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 がパッケージされていることが分かるので、これで良いのかな?

非同期

上面的问题答案是肯定的,不可以的,很明显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左右

可是,这里我们发现vuetify.js和vuetify.css实在太庞大了,导致我们的打包的代码很大,这里,我们考虑把它提取出来,这里为了避免重复打包,需要使用external,并将vue以及vuetify的代码采用cdn读取的方式,首先修改index.html

//css引入
<link href=&#39;https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons&#39; rel="stylesheet" type="text/css">
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" 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。

但是新问题又来了,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: '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
 })
 ])
}

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

推荐阅读:

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

bing Map使用步骤详解

以上がVue のパッケージ化手順を最適化するためのコード分割の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。