LoginSignup
15
14

More than 3 years have passed since last update.

ぼくのかんがえたさいきょうのNuxt×TypeScript環境

Last updated at Posted at 2018-12-12

この記事は TypeScript Advent Calendar 2018 の13日目です。

2019/07/31追記

(ずっと前に)Nuxtが公式にTypeScriptをサポートしました。以下の煩わしい設定は一切不要で、以下の簡単な手順でプロジェクトにTypeScriptを導入できるようになりました。

2018/12/15追記

次のバージョンでTypeScriptのビルドオプションが追加されるようです。

feat: TypeScript support via build option

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.jsbuild.extendbuild.pluginsextensionsを書き足します。

nuxt.config.js(抜粋)
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を書けます。

sample.vue(抜粋)
<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.jscssプロパティ)を読み込んであげましょう。

config.js(抜粋)
// グローバルの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

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が読み込まれます。

15
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14