4
3

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 5 years have passed since last update.

@vue/cli-serviceの実装からcache-loaderのcacheIdentifierの算出方法を読み解く

Posted at

はじめに

Vue.jsを使わないTypeScriptのプロジェクトで、ビルドを高速化するためにcache-loaderを導入してデフォルト設定で使っていたのですが、tsconfig.jsを変更した際にビルド結果が変わらないなど問題が発生してしまいました。

そこで、vue-cliで自動生成されるwebpackの設定ではcache-loaderにどのような設定をしているのか調べた結果、cacheIdentifierを設定していたため、この値がどのように算出されているのか実装を追ってみました。

具体的には下記の値です。

vue inspect --mode production --rule js
/* config.module.rule('js') */
{
  test: /\.jsx?$/,
  exclude: [
    function () { /* omitted long function */ }
  ],
  use: [
    {
      loader: 'cache-loader',
      options: {
        cacheDirectory: '/path/to/node_modules/.cache/babel-loader',
        cacheIdentifier: '3f3945d2' // <- これ
      }
    },
    {
      loader: 'thread-loader'
    },
    {
      loader: 'babel-loader'
    }
  ]
}

対象バージョン

vue-cli@3.2.2

実装

結論としては、ビルド結果に影響するような設定値やファイルを集めたオブジェクトを作り、hash-sumで計算したhash値をcacheIdentifierに使用しているようです。

@vue/cli-plugin-typescriptの場合、ts-loaderとtypescriptのpackage.jsonから取得したversionと、tsconfig.jsonの中身をhash計算に使用しています。

vue-cli/packages/@vue/cli-plugin-typescript/index.js から抜粋
  addLoader({
    loader: 'cache-loader',
    options: api.genCacheConfig('ts-loader', {
      'ts-loader': require('ts-loader/package.json').version,
      'typescript': require('typescript/package.json').version,
      modern: !!process.env.VUE_CLI_MODERN_BUILD
    }, 'tsconfig.json')
  })

上記で使われているapi.getCacheConfigの実装を追っていくと、渡されたファイルに加え、@vue/cli-service, cache-loaderのpackage.jsonから取得したversion、vue.config.jsのchainWebpack, configureWebpackの内容もhash計算対象に加えているようです。

vue-cli/packages/@vue/cli-service/lib/PluginAPI.js から抜粋
genCacheConfig (id, partialIdentifier, configFiles) {
  const fs = require('fs')
  const cacheDirectory = this.resolve(`node_modules/.cache/${id}`)

  const variables = {
    partialIdentifier,
    'cli-service': require('../package.json').version,
    'cache-loader': require('cache-loader/package.json').version,
    env: process.env.NODE_ENV,
    test: !!process.env.VUE_CLI_TEST,
    config: [
      this.service.projectOptions.chainWebpack,
      this.service.projectOptions.configureWebpack
    ]
  }

  if (configFiles) {
    // (中略) ファイルを読んでvariableに追加する処理
  }

  const cacheIdentifier = hash(variables)
  return { cacheDirectory, cacheIdentifier }
}

この実装によって、ソースコード以外にビルド結果に影響を及ぼすような設定が変更された場合にもcacheが無効化され、常にビルド結果が期待した内容になっているようです。

@vue/cli-serviceの実装を参考にしたwebpack.config.js

調べた実装を元に、素のwebpackプロジェクトでcache-loaderのcacheIdentifierにhash値を設定する簡単なサンプルを組んでみました。

webpack.config.js
const fs = require('fs')
const hash = require('hash-sum')

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')

const cacheIdentifier = hash([
  require('typescript/package.json').version,
  require('ts-loader/package.json').version,
  require('cache-loader/package.json').version,
  require('./tsconfig.json'),
  fs.readFileSync('./webpack.config.js', 'utf-8'),
  process.env.NODE_ENV
])

module.exports = {
  mode: process.env.NODE_ENV || 'production',
  entry: ['./src/index.ts'],
  output: {
    path: __dirname + '/dist',
    filename: 'app.js'
  },
  resolve: {
    extensions: ['.js', '.json', '.ts']
  },
  module: {
    rules: [
      {
        test: /\.[jt]s$/,
        use: [
          {
            loader: 'cache-loader',
            options: {
              cacheDirectory: __dirname + '/node_modules/.cache/ts-loader',
              cacheIdentifier
            }
          },
          { loader: 'thread-loader' },
          {
            loader: 'ts-loader',
            options: {
              transpileOnly: true,
              happyPackMode: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new ForkTsCheckerWebpackPlugin({
      tslint: false,
      formatter: 'codeframe',
      checkSyntacticErrors: true
    })
  ]
}

リポジトリは下記においてあります。
https://github.com/clomie/typescript-webpack-cache-identifier-example

4
3
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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?