これは Next.js Advent Calendar 2018 の 10 日目の投稿です。
前回、next-typescript プラグインを使って Next.js で TypeScript を利用する方法について書きました。
今回は、用意されているプラグインを使うのではなく、自分で webpack の構成をカスタマイズして TypeScript を使えるようにしてみます。
webpack をカスタマイズする
Next.js は、自分で webpack のバンドル構成を準備しなくても使い始めることができます。このように透過的に webpack を扱えるのは Next.js の強みの 1 つですが、場合によっては構成をカスタマイズしたい場合があります。例えば今回説明する「TypeScript のファイルの処理に任意のローダーをつかいたい」ような場合はまさにそのユースケースに当てはまると言えるでしょう。
webpack をカスタマイズする方法は Next.js が用意してくれているので、それを使って TypeScript に ts-loader を使うように設定してみます。
next.config.js
module.exports = {
pageExtensions: ["js", "jsx", "tsx"],
webpack: (config, { dir, defaultLoaders }) => {
config.resolve.extensions.push(".ts", ".tsx")
config.module.rules.push({
test: /\.tsx?$/,
include: [dir],
exclude: /node_modules/,
use: [
defaultLoaders.babel,
{
loader: "ts-loader"
}
]
})
return config
}
}
このとき、オブジェクトの webpack
キーに指定するコールバック関数の引数で渡される config
が webpack の configuration オブジェクトになります。なので、この config
をカスタマイズして返すようにします。
config
オブジェクトのカスタマイズには webpack の設定をそのまま使えるので、
resolve.extensions
に.ts
と.tsx
を追加module.rules
で TypeScript ファイルの読み込みにts-loader
を適用する
ように設定しています。この辺りは上記のコードを見てもらえればそのままなので特に説明は不要かと思います。
ポイントは pageExtensions
という設定です。ご存知の通り、Next.js では pages
ディレクトリ配下に設置されたファイルをルーティングとして扱う特殊な仕組みがあります。したがって、ルーティングのためのページコンポーネントの対象にするファイルの種類を拡張子で指定する必要があります。
それが、
...
pageExtensions: ["js", "jsx", "tsx"],
...
の行になります。
ここまでの設定で、あとは普通に TypeScript を使う場合同様に typescript
と ts-loader
をインストールし tsconfig.json
を設置すれば TypeScript で Next.js の開発をすることができます。試しに pages
に index.tsx
などを作って確認してみるとよいでしょう。
まとめ
webpack の構成を自分でカスタマイズすることで Next.js を TypeScript で書くための設定を見てきました。せっかく Next.js という (ある程度 webpack configuration free な) フレームワークを使っているので、ほとんどの場合は公式で用意してくれている next-typescript プラグインを使う方が良いでしょう。
ただ、同時に Next.js は minimalistic な思想で作られているので、自分でカスタマイズすることで柔軟な構成をすることが可能になっています。例えば今回の TypeScript の例でいうと、コンパイル時の型チェックを厳密にしたいといった場合や、awesome-typescript-loader などローダーの選択肢を増やしたい場合などにもすぐ対応できることは積極的に利用していく価値があります。
また、自分で webpack をカスタマイズしてみることで、next-typescript などのプラグインがその背後で何をやっているかが理解できることもメリットだと思います。実際にコードを見てみればわかりますが、まさに上記で自分で設定したことがプラグインの中で行われているのが見て取れると思いますし、トラブルシューティングの際にも役に立つと思います。