@vue/cli-serviceの実装からcache-loaderのcacheIdentifierの算出方法を読み解く
@vue/cli-serviceの実装からcache-loaderのcacheIdentifierの算出方法を読み解く:
Vue.jsを使わないTypeScriptのプロジェクトで、ビルドを高速化するためにcache-loaderを導入してデフォルト設定で使っていたのですが、tsconfig.jsを変更した際にビルド結果が変わらないなど問題が発生してしまいました。
そこで、vue-cliで自動生成されるwebpackの設定ではcache-loaderにどのような設定をしているのか調べた結果、
具体的には下記の値です。
vue-cli@3.2.2
結論としては、ビルド結果に影響するような設定値やファイルを集めたオブジェクトを作り、hash-sumで計算したhash値を
@vue/cli-plugin-typescriptの場合、ts-loaderとtypescriptのpackage.jsonから取得した
https://github.com/vuejs/vue-cli/blob/v3.2.2/packages/%40vue/cli-plugin-typescript/index.js#L31
上記で使われている
https://github.com/vuejs/vue-cli/blob/v3.2.2/packages/%40vue/cli-service/lib/PluginAPI.js#L134
この実装によって、ソースコード以外にビルド結果に影響を及ぼすような設定が変更された場合にもcacheが無効化され、常にビルド結果が期待した内容になっているようです。
調べた実装を元に、素のwebpackプロジェクトでcache-loaderの
リポジトリは下記においてあります。
https://github.com/clomie/typescript-webpack-cache-identifier-example
はじめに
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計算に使用しています。https://github.com/vuejs/vue-cli/blob/v3.2.2/packages/%40vue/cli-plugin-typescript/index.js#L31
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計算対象に加えているようです。https://github.com/vuejs/vue-cli/blob/v3.2.2/packages/%40vue/cli-service/lib/PluginAPI.js#L134
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 } }
@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
コメント
コメントを投稿