🔨
webpack/特定ファイルのビルドで別Loaderを使用する
動機
TypeScript + AWS Lambda のバックエンドをデプロイする際に、webpackのビルド時間を早くできないかと思い、 ts-loader
から esbuild-loader
へ移行を試みていました。
しかしながら、RDS(MySQL)のORMに TypeORM を使用していたため、 esbuild-loader がemitDecoratorMetadata
には対応しておらず、ビルドエラーを吐いたのでDecoratorを含むファイルはts-loaderで、含まないファイルはesbuild-loaderでビルドできないか調査しました。
解決法
リンクにあるgithub discussionの記事通りではあるのですが、webpack.config.js 内の test
propertyでビルド対象のファイルのパス(String)を取得できるので、あとはファイルのパスがルールに一致すれば esbuild-loader
を使用するよう webpackの oneOf
を使用し、正規表現でよしなに。
function hasDecorator(fileContent, offset = 0) {
const atPosition = fileContent.indexOf('@', offset)
if (atPosition === -1) {
return false
}
if (atPosition === 1) {
return true
}
if (["'", '"'].includes(fileContent.substr(atPosition - 1, 1))) {
return hasDecorator(fileContent, atPosition + 1)
}
return true
}
modules.exports = {
module: {
rules: [
{
test: /\.(ts)$/,
oneOf: [
{
test: (filePath) => {
if (!filePath) {
return false
}
try {
const fileContent = fs.readFileSync(filePath).toString()
return !hasDecorator(fileContent)
} catch (e) {
console.error(`uncaught error`)
return false
}
},
use: [
loader: 'esbuild-loader',
options: {
loader: 'ts',
target: 'es2017',
},
],
},
{
use: [
loader: 'ts-loader',
options: {
transpileOnly: true,
},
],
},
},
],
],
},
}
リンク
Discussion