やりたい事
- Nuxt.jsのビルド時間を短縮したい
- JSのファイルサイズを軽くしたい
やった事
- 1.Webpack Bundle Analyzerを使って、現状のファイルサイズを把握。
- 2.その中でどのファイルがネックになっているか調査する。
- 3.リファクタリングする。
※今回は一部のみ
0.各キーワード説明
Webpack Bundle Analyzerとは?
下記を可視化してくれる。
- webpackの速度改善の為、遅いloaderやpluginを知りたい
- バンドルファイルのサイズを減らしたいので、バンドルファイル内の各パッケージがどのくらいの容量を占めているか知りたい。
参考:https://github.com/webpack-contrib/webpack-bundle-analyzer
1.Webpack Bundle Analyzerを使って、現状のファイルサイズを把握。
$ yarn build --analyze
2.その中でどのファイルがネックになっているか調査する。
- ①Chart.jsが重い
- ②moment.jsが重い
- localeが無駄に多い
- ③lodash.jsが重い
3.リファクタリングする。
- ①Chart.jsが重い
- vue-chart.jsの中で使われているので、外すのは難しそうだった。
"dependencies": {
"bootstrap": "^3.4.1",
"bootstrap-social": "^5.1.1",
"bootstrap-vue": "^2.0.0-rc.24",
"chart.js": "^2.8.0",
"chosen-js": "^1.8.5",
"ckeditor": "^4.11.4",
"clipboard": "^2.0.4",
"datatables": "^1.10.13",
"datatables-all": "^1.10.13",
"firebase": "^6.0.1",
"font-awesome": "^4.7.0",
"hchs-vue-charts": "^1.2.8",
"icheck": "^1.0.2",
"ionicons": "^4.5.8",
"jquery-datetimepicker": "^2.5.21",
"jquery-ui-dist": "^1.12.1",
"jquery.flot": "^0.8.3",
"luxon": "^1.15.0",
"moment": "^2.24.0",
"sass": "^1.20.1",
"sass-loader": "^7.0.1",
"select2": "^4.0.7",
"sweetalert2": "^8.11.6",
"turbolinks": "^5.0.3",
"vue-chartjs": "^3.4.2",
"vue-datetime": "^1.0.0-beta.10",
"vue-js-modal": "^1.3.31",
"vue-nl2br": "^0.1.1",
"vue-resource": "^1.3.4",
"vue-spinner": "^1.0.3",
"vue-spinner-component": "^1.0.5",
"vuex": "^3.1.1",
"weekstart": "^1.0.0",
"yubinbango": "yubinbango/yubinbango"
},
- ②moment.jsが重い
- nuxt.config.jsにmomentの設定を追加
module.exports = {
mode: 'spa',
// 省略
build: {
parallel: true,
/*
* Run ESLint on save
*/
extend (config, { isDev, isClient }) {
// クライアントのバンドルの Webpack 設定のみを拡張する
if (isClient) {
config.devtool = '#source-map'
}
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/,
})
const vueLoader = config.module.rules.find(
({ loader }) => loader === 'vue-loader')
const { options: { loaders } } = vueLoader || { options: {} }
if (loaders) {
for (const loader of Object.values(loaders)) {
changeLoaderOptions(Array.isArray(loader) ? loader : [loader])
}
}
config.module.rules.forEach(rule => changeLoaderOptions(rule.use))
// For faster build. Use hard-source-webpack-plugin.
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
config.plugins.push(new HardSourceWebpackPlugin())
}
},
// ここを変更
vendeer: ['moment'],
plugins: [
new MomentLocalesPlugin({
localesToKeep: ['es-us', 'ja']
})
]
},
}
- ③lodash.jsが重い
- 現状、ディープコピーの箇所にしかlodash.jsが使われていなかった
<script>
import { mapActions, mapGetters } from 'vuex'
import cloneDeep from 'lodash'
export default {
name: 'agent',
layout: 'administrator/default',
data () {
return {
// 省略
},
}
},
async created () {
// 省略
},
computed: {
// 省略
},
methods: {
async setProgrammingCategory () {
let programmingCategory = this.programmingCategories.find(programmingCategory => Number(programmingCategory.id) === Number(this.programmingCategoryId))
if (!programmingCategory) {
this.$nextTick(() => this.$nuxt.$loading.start())
try {
await this.fetchProgrammingCategories()
} catch (e) {
console.log(e.message)
return
} finally {
this.$nuxt.$loading.finish()
}
programmingCategory = this.programmingCategories.find(programmingCategory => Number(programmingCategory.id) === Number(this.programmingCategoryId))
if (!programmingCategory) {
this.$router.push('/errors/404')
}
}
this.formData = cloneDeep(programmingCategory)
},
async update () {
// 省略
},
...mapActions('administrator', ['fetchProgrammingCategories', 'updateProgrammingCategory']),
},
}
</script>
- 修正点
lodashをimport _ from 'lodash'のように読み込んでしまうと、全てのlodash関数などがbundleされてしまいます。
それを回避するため、使用する関数のみをimportするように変更します。
<script>
import cloneDeep from 'lodash/cloneDeep'
</script>
改善結果
改善前
↓ ↓ ### 改善後 lodashとmoment.jsはほぼ消えた!改善前
↓ ↓ ### 改善後 約1MB軽量化!!まとめ
- ビルドの高速化するにあたって、moment.jsやlodash.jsが重くなるのはよくありそう
- 補足としては、そもそもmoment.jsよりday.jsの方が軽いので、そっちを使うと良いらしい!
参考記事
-
https://speakerdeck.com/bumptakayuki/nuxt-dot-jsfalsehirutowogao-su-hua-suruwei-niwan-zhang-tutahua
自分の発表資料も参考により具体的に書いてみました。