ほとんど自分のためのメモに近いのですが、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
prettier
と eslint
を設定する
yarn add -D @nuxt/typescript-build
yarn add @nuxt/typescript-runtime
個人的にNuxtのソースファイルはsrc
ディレクトリに入れるのが好きなので、
assets
, components
, layouts
, middleware
, pages
, plugins
, static
, store
のディレクトリは src
に移動。
nuxt.config
に srcDir: 'src'
を追加。
nuxt.config.js
を 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を作成
{
"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用に書き換える
ルールはお好みで
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 の nuxt
を nuxt-ts
に変更する
{
"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のときとほとんど同じような記述ができる
<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の設定で、保存時にエラーをチェックして整形してくれるようにする
{
"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に追加
...
"browserslist": [
"last 2 version",
"android >= 5",
"IE 11"
],
"_moduleAliases": {
"~/*": "./src/*",
"@/*": "./src/*"
}
...
tsconfig.jsonの編集
"baseUrl": "./src"
型定義
@types
ディレクトリを作成
*.d.ts
の形式のファイルを入れる
例)markdownをimportする際に必要 md.d.ts
declare module '*.md' {
const content: string
export default content
}
assets から 画像ファイルを import する場合、以下のような型定義を読み込んでおく
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
// ページ遷移時にスクロールトップ
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
を編集
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分くらいでできるのではないでしょうか。