LoginSignup
69

More than 3 years have passed since last update.

3分でつくる2019年版 Nuxt.js TypeScript 開発環境設定

Last updated at Posted at 2019-07-18

ほとんど自分のためのメモに近いのですが、3分でNuxt.js+TypeScriptの開発環境を整える覚書です。

--- [2019/08/22 追記] ---
※ Nuxt 2.8での設定方法です!
Nuxt 2.9 から Nuxt TypeScript に変わりました!
公式のマイグレーション方法はこちら https://typescript.nuxtjs.org/migration.html


--- [2019/09/05 追記] ---
Nuxt 2.9 仕様に記事の内容を変更しました!


Create Nuxt App でベースはセットアップ

create-nuxt-app my-app

prettiereslint を設定する

yarn add -D @nuxt/typescript-build
yarn add @nuxt/typescript-runtime

個人的にNuxtのソースファイルはsrcディレクトリに入れるのが好きなので、
assets, components, layouts, middleware, pages, plugins, static, store のディレクトリは src に移動。

nuxt.configsrcDir: 'src' を追加。

nuxt.config.jsnuxt.config.ts に変更。

nuxt.config.ts
import { Configuration } from '@nuxt/types'

const config: Configuration = {
  // Config設定の記述
  // ...
  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module',
    '@nuxt/typescript-build' // <- 追加
  ],
  // ...
}

export default config

tsconfig.jsonを作成

tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "esnext.asynciterable",
      "dom"
    ],
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noImplicitAny": false,
    "noEmit": true,
    "baseUrl": "./src",
    "paths": {
      "~/*": ["./*"],
      "@/*": ["./*"]
    },
    "typeRoots": ["/src/@types"],
    "types": [
      "@types/node",
      "@nuxt/types",
      "@nuxtjs/axios"
    ]
  },
  "exclude": [
    "node_modules"
  ]
}

ESLintの設定

yarn add -D @nuxtjs/eslint-config-typescript

.eslintrc.jsをTypeScript用に書き換える
ルールはお好みで

eslintrc.js
module.exports = {
  root: true,
  parser: 'vue-eslint-parser',
  env: {
    browser: true,
    node: true
  },
  parserOptions: {
    // parser: '@typescript-eslint/parser'
  },
  extends: [
    '@nuxtjs',
    '@nuxtjs/eslint-config-typescript', // <= これを追加
    'plugin:nuxt/recommended',
    'plugin:prettier/recommended',
    'prettier',
    'prettier/vue'
  ],
  plugins: [
    'prettier'
  ],
  // add your custom rules here
  rules: {
    'no-unused-vars': 'off',
    '@typescript-eslint/no-unused-vars': 'error',
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    "vue/singleline-html-element-content-newline": "off",
    "vue/no-v-html": "off",
    "vue/html-closing-bracket-spacing": "off",
    "vue/max-attributes-per-line": [2, {
      "singleline": 5,
      "multiline": {
        "max": 1,
        "allowFirstLine": false
      }
    }]
  }
}

nuxt-ts に変更

NPM Scripts の nuxtnuxt-ts に変更する

package.json
{
  "scripts": {
    "dev": "nuxt-ts",
    "build": "nuxt-ts build",
    "generate": "nuxt-ts generate",
    "start": "nuxt-ts start",
    "lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore ."
  },
  "dependencies": {
    "@nuxt/typescript-runtime",
    "nuxt"
  },
  "devDependencies": {
    "@nuxt/typescript-build"
  }
}

Vue.extend での開発

jsのときとほとんど同じような記述ができる

sample.vue
<script lang="ts">
import Vue, { PropType } from 'vue'
import Hoge from '~/components/Hoge.vue'

// Taskの型定義
type Task = {
  id: number
  name: string
  check: boolean
}

// Dataの型定義
type Data = {
  tasks: Task[]
  name: string
}

export default Vue.extend({
  components: {
    Hoge
  },
  props: {
    dataTask: {
      // ArrayやObjectの場合、詳細な型定義はPropTypeを使う
      type: Array as PropType<Task[]>,
      required: true
    }
  },
  data(): Data {
    return {
      tasks: this.dataTask
      name: 'サンプル'
    }
  }
})
</script>

クラスコンポーネントでの開発

yarn add nuxt-property-decorator

nuxt-property-decorator には vue-class-component, vue-property-decorator, vuex-class がラップされている

nuxt.configに追加

  build: {
    babel: {
      plugins: [
        ["@babel/plugin-proposal-decorators", { legacy: true }],
        ["@babel/plugin-proposal-class-properties", { loose: true }]
      ]
    }
  }

VSCode

VSCodeの設定で、保存時にエラーをチェックして整形してくれるようにする

/.vscode/settings.json
{
  "javascript.format.insertSpaceBeforeFunctionParenthesis": true,
  "typescript.format.insertSpaceBeforeFunctionParenthesis": true,
  "eslint.enable": true,
  "editor.formatOnSave": false,
  "eslint.run": "onType",
  "vetur.format.defaultFormatter.js": "prettier",
  "vetur.format.defaultFormatter.css": "prettier",
  "vetur.format.defaultFormatter.less": "prettier",
  "vetur.format.defaultFormatter.postcss": "prettier",
  "vetur.format.defaultFormatter.scss": "prettier",
  "vetur.format.defaultFormatter.stylus": "stylus-supremacy",
  "vetur.format.defaultFormatter.ts": "prettier",
  "vetur.validation.style": true,
  "vetur.validation.template": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

package.jsonに追加

package.json
...
  "browserslist": [
    "last 2 version",
    "android >= 5",
    "IE 11"
  ],
  "_moduleAliases": {
    "~/*": "./src/*",
    "@/*": "./src/*"
  }
...

tsconfig.jsonの編集

tsconfig.json
"baseUrl": "./src"

型定義

@types ディレクトリを作成
*.d.ts の形式のファイルを入れる

例)markdownをimportする際に必要 md.d.ts

md.d.ts
declare module '*.md' {
  const content: string
  export default content
}

assets から 画像ファイルを import する場合、以下のような型定義を読み込んでおく

files.d.ts
declare module '*.png'
declare module '*.jpg'
declare module '*.gif'
declare module '*webp'

Nuxt 2.9から config に router の設定を書くのが非推奨になった

nuxt.config ではなく、/app/router.scrollBehavior.js を作成してそこに設定を記述する。
https://nuxtjs.org/api/configuration-router/#scrollbehavior

srcDirディレクトリ/app/router.scrollBehavior.js
// ページ遷移時にスクロールトップ
export default function(to, from, savedPosition) {
  return { x: 0, y: 0 }
}

おまけ

SassとPugをインストール

yarn add -D node-sass sass-loader pug pug-plain-loader

Stroybook インストール

npx -p @storybook/cli sb init --type vue
yarn add -D path fork-ts-checker-webpack-plugin

TypeScript用にStorybookの webpack.config.js を編集

storybook/webpack.config.js
const path = require('path');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [/\.vue$/],
              transpileOnly: true
            },
          }
        ]
      },
      {
        test: /\.scss$/,
        use: [
          "style-loader", 
          "css-loader",
          {
            loader: "sass-loader",
            options: {
              importLoaders: 0,
              alias: {
                'assets': path.resolve(__dirname, '../app/assets')
              }
            }
          },
          {
            loader: "sass-resources-loader",
            options: {
              resources: [
                path.resolve(__dirname, '../app/assets/styles/variables/*.scss'),
                path.resolve(__dirname, '../app/assets/styles/common.scss')
              ]
            }
          }
        ]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'file-loader'
      },
      {
        test: /\.pug$/,
        loader: 'pug-plain-loader'
      }
    ]
  },
  plugins: [
    new ForkTsCheckerWebpackPlugin()
  ],
  resolve: {
    extensions: ['.ts', '.js', '.vue', '.json'],
    alias: {
      'static': path.resolve(__dirname, '../app/static'),
      'assets': path.resolve('../app/assets'),
      '@': path.resolve(__dirname, '../app'),
      '~': path.resolve(__dirname, '../app')
    }
  }
};

コピペするとここまでが3分くらいでできるのではないでしょうか。

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
69