26
17

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.

TechCommitAdvent Calendar 2019

Day 17

Nuxt.jsのビルド時間を短縮する為に頑張った話

Last updated at Posted at 2019-12-16

やりたい事

  • 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
スクリーンショット 2019-12-16 23.47.31.png

2.その中でどのファイルがネックになっているか調査する。

スクリーンショット 2019-12-16 23.52.50.png
  • ①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>

改善結果

改善前

スクリーンショット 2019-12-17 0.15.06.png ↓ ↓ ### 改善後 lodashとmoment.jsはほぼ消えた! スクリーンショット 2019-12-17 0.15.15.png

改善前

スクリーンショット 2019-12-17 0.16.05.png ↓ ↓ ### 改善後 約1MB軽量化!! スクリーンショット 2019-12-17 0.16.15.png

まとめ

  • ビルドの高速化するにあたって、moment.jsやlodash.jsが重くなるのはよくありそう
  • 補足としては、そもそもmoment.jsよりday.jsの方が軽いので、そっちを使うと良いらしい!

参考記事

26
17
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
26
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?