この記事は TypeScript Advent Calendar 2018 の13日目です。
2019/07/31追記
(ずっと前に)Nuxtが公式にTypeScriptをサポートしました。以下の煩わしい設定は一切不要で、以下の簡単な手順でプロジェクトにTypeScriptを導入できるようになりました。
2018/12/15追記
次のバージョンでTypeScriptのビルドオプションが追加されるようです。
Nuxt × TypeScript
はじめまして。Advent Calendar初参戦の @simochee (しもちぃ)と申します。
Nuxt、最近流行っていますね。
そんなNuxtをTypeScriptで使おうと公式コミュニティのテンプレートを見に行ったら、もう半年以上更新されておらず若干不安になります。
(というか未だにNuxt 1.3.0だし)
ということで、NuxtでTypeScriptを使うための(個人的な)おすすめ環境をご紹介します。
なお、この記事ではNuxt 2.xでの使用を想定しています。
Requirements
以下のツールが動作するような環境を目指します。
- TypeScript
- TSLint
- (オマケ)Storybook
Dependences
依存するパッケージの一覧です。
- TypeScript
typescript
ts-loader
fork-ts-checker-webpack-plugin
- TSLint
tslint
vue-tslint-loader
# dependencies
$ yarn add typescript
# devDependencies
$ yarn add -D ts-loader fork-ts-checker-webpack-plugin tslint vue-tslint-loader
nuxt.config.js
nuxt.config.js
はbuild.extend
とbuild.plugins
、extensions
を書き足します。
const ForkTsChecker = require('fork-ts-checker-webpack-plugin');
...
export default {
build: {
extend(config, { isDev }) {
// ts-loaderの設定
const tsLoader = {
loader: 'ts-loader',
options: {
// .vueファイルもTypeScriptとして認識させる
appendTsSuffixTo: [/\.vue$/],
transpileOnly: true
},
exclude: [/vendor/, /\.nuxt/]
};
// Loaderを追加
config.module.rules.push({ test: /\.tsx?$/, ...tsLoader });
config.resolve.extensions.push('.ts');
config.module.rules.map((rule) => {
if (rule.loader === 'vue-loader') rule.options.loaders = { ts: tsLoader };
return rule;
});
// TSLint
config.module.rules.push({
enforce: 'pre',
test: /\.(tsx?|vue)$/,
exclude: /(node_modules|\.nuxt)/,
use: [
{
// vue-tslint-loaderでLintさせる
loader: 'vue-tslint-loader',
options: {
configFile: 'tslint.yml',
// 本番ビルド時にエラーが発生したら落ちるようにする
emitErrors: !isDev
}
}
]
});
},
plugins: [
// 型チェックはForkTsCheckerに任せる
new ForkTsChecker({
vue: true
}),
]
},
...
extensions: ['js', 'ts'],
...
}
これで、VueファイルでTypeScriptを使う準備が整いました。
Vueファイル
TypeScriptを使ってページコンポーネントを書いてみましょう。
とは言っても、<script>
にlang="ts"
を付ければ普通にTypeScriptを書けます。
<script lang="ts">
import { SampleObj } from './interfaces.d.ts';
export defualt {
data() {
return {
sample: {} as SampleObj
}
}
};
</script>
vue-property-decorator
せっかくなので、Decoratorを使ってVueをClassベースに書くことができるライブラリ、vue-property-decorator
を使ってみましょう。
(オマケ)Storybook
ついでに、StorybookでNuxt(Vue)とTypeScriptが使える環境もご紹介します。
Dependences
@storybook/vue
webpack-merge
ts-loader
vue-style-loader
css-loader
postcss-loader
config.js
config.js
では、Nuxtのプラグインとグローバルなスタイル(nuxt.config.js
のcss
プロパティ)を読み込んであげましょう。
// グローバルのCSSを追加
import '@/assets/styles/main.sass';
// Nuxtのプラグインを追加
const plugins = require.context('../plugins', true, /\.ts$/);
plugins.keys().forEach(plugins);
// Storyを追加
const req = require.context('../stories', true, /\.stor(y|ies)\.tsx?$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
webpack.config.js
const merge = require('webpack-merge');
module.exports = (storybookBaseConfig, configType, config) => {
return merge(config, {
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/]
}
},
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
// postcssのプラグインを追加
}
}
]
}
]
},
resolve: {
alias: {
'@': path.resolve(__dirname, '../src')
},
extensions: ['.js', '.ts']
}
});
};
以上で、./stories/**/*.stor(y|ies).tsx?
にマッチするStoryが読み込まれます。