はじめに
Vue.jsを使わないTypeScriptのプロジェクトで、ビルドを高速化するためにcache-loaderを導入してデフォルト設定で使っていたのですが、tsconfig.jsを変更した際にビルド結果が変わらないなど問題が発生してしまいました。
そこで、vue-cliで自動生成されるwebpackの設定ではcache-loaderにどのような設定をしているのか調べた結果、cacheIdentifier
を設定していたため、この値がどのように算出されているのか実装を追ってみました。
具体的には下記の値です。
/* 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'
}
]
}
対象バージョン
実装
結論としては、ビルド結果に影響するような設定値やファイルを集めたオブジェクトを作り、hash-sumで計算したhash値をcacheIdentifier
に使用しているようです。
@vue/cli-plugin-typescriptの場合、ts-loaderとtypescriptのpackage.jsonから取得したversion
と、tsconfig.jsonの中身をhash計算に使用しています。
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計算対象に加えているようです。
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値を設定する簡単なサンプルを組んでみました。
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