21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vuetify2を使ったプロジェクトのビルドが遅いので高速化する

Last updated at Posted at 2020-04-03

Vuetify+Vue CLIで構築したプロジェクトで、
Vuetify2.xにアップグレードしたらnpm run serveの開始時間が著しく長くなってしまったので改善します。

原因

Vuetify2.0よりデフォルトで有効となったA-la-carte(treeshaking)が原因です。

A-la-carteとは

Vuetifyの数多くのコンポーネントのうち、「プログラム中で使われているもの」だけを成果物に含める機能です。使っていないコンポーネントをimportしないので、ビルドサイズが減少します。

しかしながら、これはビルド時間を増大させます。

A-la-carteを使わない場合、vuetifyの全てのコンポーネントはnode_modules/vuetify/dist/vuetify.min.jsから読み込まれます。これは既にimportの解決やminifyが済んでいるプリコンパイル済みソースであるため、これをビルド成果物に含めるための処理は極めて軽いです。

ところが、A-la-carteを用いる場合、node_modules/vuetify/lib/*(要するにVuetifyのビルド前のソースそのもの)からコンポーネントが読み込まれます。これは、Vuetify内部のimportの解決もこちらのコンパイルタイムで行わなければならないことを意味します。Vuetifyはソース数が非常に多く、これは大変な処理負荷となります。

さらに、scssなどもトランスパイルしなければならないため、これも少なからずビルド時間が増大する原因となります。A-la-carteを用いなければcssはnode_modules/vuetify/dist/vuetify.min.cssより読み込まれるので負荷はありません。

npm run serveがなぜ重いか

ところが、実際のnpm run build時にはそこまで大きくコンパイル時間が伸びることはありません(当然伸びるのは伸びるのですが)。これは、vuetify-loaderと呼ばれるWebpackプラグインによって、不要なものが削ぎ落とされているからです。必要なものだけビルドするので、使っているコンポーネント数に比例してしかビルド時間は伸びないはずです。

しかし、npm run serveにおいてはそれがうまくいかず、非常にビルド時間が伸びてしまいます。これは、Webpack4のtreeshaking(vuetify-loaderはこの機能に依存しています)がproductionビルドでしか有効にならないためです。そのため、developmentビルドでは使っているコンポーネント数に関係なく全てのコンポーネントがビルドされ、非常に時間がかかります(特に開始時)。

解決策

解決策の方針としては以下のようになります。

  • developmentビルド時は、ビルド時間を削減するためにA-la-carte(treeshaking)を利用しないようにする
  • productionビルド時は、ビルドサイズを削減するためにvuetify-loaderを用いたA-la-carteを利用する

ソースの変更

以下はVue CLI3の例ですが、Webpackを生で使っている場合でも大きくは変わらないと思います。

vue-cli-plugin-vuetifyの無効化

package.jsonより、vue-cli-plugin-vuetifyvue-cli-plugin-vuetify-essentialsの削除

package.json
  "devDependencies": {
    ...,
-   "vue-cli-plugin-vuetify": "^1.1.2",
-   "vue-cli-plugin-vuetify-essentials": "^0.8.3",
    ...
  }

vuetifyのインポートの変更

Vue CLIインストールであればplugins/vuetify.jsでvuetifyを以下のようにインポートしていると思います。

plugins/vuetify.js
import Vue from 'vue';
import Vuetify, { VList } from 'vuetify/lib';

Vue.use(Vuetify);

export default new Vuetify({ /* vuetifyのオプション */ });

これと同様にして、plugins/vuetify-dev.jsを以下の内容で作成します。

plugins/vuetify-dev.js
import Vue from 'vue';
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';

Vue.use(Vuetify);

export default new Vuetify({ /* vuetifyのオプション */ });

さらに、main.jsでVuetifyをインポートしている部分を変更します。

main.js
  import Vue from 'vue';
- import vuetify from './plugins/vuetify';
+ const vuetify = process.env.NODE_ENV === "production"
+   ? require('./plugins/vuetify').default
+   : require('./plugins/vuetify-dev').default;
  import ...

  /* (中略) */

  new Vue({
    vuetify,
    render: h => h(App)
  }).$mount('#app');

vuetify-loaderの手動ロード

vue-cli-plugin-vuetifyを消してしまったので、vuetify-loaderを手動でWebpackに読み込ませます。
vue.config.jsを以下のように編集します。

vue.config.js
+ const vuetifyOptional = process.env.NODE_ENV === "production"
+   ? [new (require('vuetify-loader/lib/plugin'))()]
+   : [];
  
  module.exports = {
    ...,
+   configureWebpack: {
+     plugins: [
+       ...vuetifyOptional,
+     ],
+   },
-   transpileDependencies: ["vuetify"],
+   transpileDependencies: vuetifyOptional.length > 0 ? ["vuetify"] : [],
    ...,
  }

動作確認

npm run servenpm run buildをして正しくビルドできることを確認して下さい。


参考文献

https://vuetifyjs.com/ja/getting-started/quick-start/
https://vuetifyjs.com/ja/customization/a-la-carte/

21
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?