Help us understand the problem. What is going on with this article?

【Vue.js】Vuetify と TypeScript を使用した環境を構築してサンプルプロジェクトを立ち上げるまでの手順

More than 1 year has passed since last update.

はじめに

Vue.js 用のマテリアルデザインフレームワークであるVuetifyと JavaScript の静的型付けのスーパーセットである TypeScript を使用したプロジェクトの環境を構築しサンプルを立ちあげるまでの手順です。

Vue-CLI のインストール

Vue-CLI でひな型を作成するのが簡単なのでインストールします。

# Vue-CLI をグローバルインストールします。
$ yarn global add @vue/cli

# 動作確認を兼ねてバージョン確認
$ vue -V
3.1.3

プロジェクトの作成

$ vue create vue-typescript-vuetify-starter

? Please pick a preset:Manually select featuresを選択します。
以下のように Check the features needed for your project:TypeScript を選択します。
image.png

正常にプロジェクトが作成されると以下のように表示されます。

# 略

🎉  Successfully created project vue-typescript-vuetify-starter.
👉  Get started with the following commands:

 $ cd vue-typescript-vuetify-starter
 $ yarn serve

Vuetify パッケージの追加

# プロジェクトのディレクトリに移動します。
cd vue-typescript-vuetify-starter
# Vuetify を追加します
vue add vuetify

vuetifyプラグインを追加すると色々とファイルが追加・上書きされています。
差分:https://github.com/sano-suguru/vue-typescript-vuetify-starter/commit/3318e1f5480ea6119d9d54924ba7f7214e74f1a7

$ git status

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   package.json
        modified:   public/index.html
        modified:   src/App.vue
        modified:   src/components/HelloWorld.vue
        modified:   src/main.ts
        modified:   yarn.lock

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        src/assets/logo.svg
        src/plugins/

ファイルの修正

アプリをビルドし立ち上げます。

$ yarn serve

ビルドは終了しますが、以下のようにERRORWARNINGが発生します。
image.png

順番に修正します。修正箇所については GitHub へのリンクを張りました。

TypeScript コンパイラオプションの追加

  • tsconfig.jsoncompilerOptions.types"vuetify"を追加します。

tsconfig.jsonの修正箇所へのリンク - GitHub

※以下のように、vuetifyの型定義を用意しろとエラーメッセージが表示されていますが、上記の方法で OK です。

Could not find a declaration file for module 'vuetify/lib'.
Try `npm install @types/vuetify` if it exists or add a new declaration (.d.ts) file containing `declare module 'vuetify/lib';`
tsconfig.json
 {
   "compilerOptions": {
     "target": "esnext",
     "module": "esnext",
     "strict": true,
     "jsx": "preserve",
     "importHelpers": true,
     "moduleResolution": "node",
     "experimentalDecorators": true,
     "esModuleInterop": true,
     "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env",
      "vuetify"
    ],
    "paths": {
      "@/*": [
         "src/*"
       ]
     },
     "lib": [
       "esnext",
       "dom",
       "dom.iterable",
       "scripthost"
     ]
   },
   "include": [
     "src/**/*.ts",
     "src/**/*.tsx",
     "src/**/*.vue",
     "tests/**/*.ts",
     "tests/**/*.tsx"
   ],
   "exclude": [
     "node_modules"
   ]
 }

コンポーネントの修正

  • <script>タグのlang属性をtsに変更
  • 単一ファイルコンポーネントのインポートは拡張子.vueまで記述
  • コンポーネントをclassコンポーネント化
  • カンマ,、セミコロン;の追加

言語属性を TypeScript に変更すると単一ファイルコンポーネントは拡張子まで記述が必要になります。
Vue-CLI で Vuetify を追加した際にコンポーネントがクラスから通常のものに上書きされているのでクラス化します。
カンマ,、セミコロン;についてはtslint.jsonを修正しても良いですが、今回はVue-CLIで作成したデフォルトの規約に合わせます。

App.vueの修正箇所へのリンク - GitHub

App.vue
<template>
  <v-app>
    <v-toolbar app>
      <v-toolbar-title class="headline text-uppercase">
        <span>Vuetify</span>
        <span class="font-weight-light">MATERIAL DESIGN</span>
      </v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn flat href="https://github.com/vuetifyjs/vuetify/releases/latest" target="_blank">
        <span class="mr-2">Latest Release</span>
      </v-btn>
    </v-toolbar>

    <v-content>
      <HelloWorld/>
    </v-content>
  </v-app>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';
@Component({
  components: {
    HelloWorld,
  },
})
export default class App extends Vue {}
</script>

HelloWorld.vueの修正箇所へのリンク - GitHub

HelloWorld.vue
<template>
  <v-container>
    <v-layout text-xs-center wrap>
      <v-flex xs12>
        <v-img :src="require('../assets/logo.svg')" class="my-3" contain height="200"></v-img>
      </v-flex>

      <v-flex mb-4>
        <h1 class="display-2 font-weight-bold mb-3">Welcome to Vuetify</h1>
        <p class="subheading font-weight-regular">
          For help and collaboration with other Vuetify developers,
          <br>please join our online
          <a
            href="https://community.vuetifyjs.com"
            target="_blank"
          >Discord Community</a>
        </p>
      </v-flex>

      <v-flex mb-5 xs12>
        <h2 class="headline font-weight-bold mb-3">What's next?</h2>

        <v-layout justify-center>
          <a
            v-for="(next, i) in whatsNext"
            :key="i"
            :href="next.href"
            class="subheading mx-3"
            target="_blank"
          >{{ next.text }}</a>
        </v-layout>
      </v-flex>

      <v-flex xs12 mb-5>
        <h2 class="headline font-weight-bold mb-3">Important Links</h2>

        <v-layout justify-center>
          <a
            v-for="(link, i) in importantLinks"
            :key="i"
            :href="link.href"
            class="subheading mx-3"
            target="_blank"
          >{{ link.text }}</a>
        </v-layout>
      </v-flex>

      <v-flex xs12 mb-5>
        <h2 class="headline font-weight-bold mb-3">Ecosystem</h2>

        <v-layout justify-center>
          <a
            v-for="(eco, i) in ecosystem"
            :key="i"
            :href="eco.href"
            class="subheading mx-3"
            target="_blank"
          >{{ eco.text }}</a>
        </v-layout>
      </v-flex>
    </v-layout>
  </v-container>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
@Component
export default class HelloWorld extends Vue {
  private ecosystem = [
    {
      text: 'vuetify-loader',
      href: 'https://github.com/vuetifyjs/vuetify-loader',
    },
    {
      text: 'github',
      href: 'https://github.com/vuetifyjs/vuetify',
    },
    {
      text: 'awesome-vuetify',
      href: 'https://github.com/vuetifyjs/awesome-vuetify',
    },
  ];
  private importantLinks = [
    {
      text: 'Documentation',
      href: 'https://vuetifyjs.com',
    },
    {
      text: 'Chat',
      href: 'https://community.vuetifyjs.com',
    },
    {
      text: 'Made with Vuetify',
      href: 'https://madewithvuetifyjs.com',
    },
    {
      text: 'Twitter',
      href: 'https://twitter.com/vuetifyjs',
    },
    {
      text: 'Articles',
      href: 'https://medium.com/vuetify',
    },
  ];
  private whatsNext = [
    {
      text: 'Explore components',
      href: 'https://vuetifyjs.com/components/api-explorer',
    },
    {
      text: 'Select a layout',
      href: 'https://vuetifyjs.com/layout/pre-defined',
    },
    {
      text: 'Frequently Asked Questions',
      href: 'https://vuetifyjs.com/getting-started/frequently-asked-questions',
    },
  ];
}
</script>

<style>

</style>

その他

  • main.ts vuetify.tsにセミコロン;を追加

vue add vuetifyで追加されたコードにはセミコロンがついていないので修正します。

main.tsの修正箇所へのリンク - GitHub

main.ts
import Vue from 'vue';
import './plugins/vuetify';
import App from './App.vue';

Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App),
}).$mount('#app');

vuetify.tsの修正箇所へのリンク - GitHub

vuetify.ts
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
import 'vuetify/src/stylus/app.styl';

Vue.use(Vuetify, {
  iconfont: 'md',
});

終りに

上記の修正でエラーが全て消えて正常にコンパイルができます。
全て修正済みのソースのリポジトリ:vue-typescript-vuetify-starter

image.png

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away