NuxtJS(使用Apollo)的TypeScript支持

请用中文进行重新转述,仅提供一个选项:

题目

这次,我打算修改服务器端(使用Golang)的实现,以便根据请求返回相应的结果。但在此之前,我认为在原始JavaScript中进行调试会变得困难,所以应该先进行TypeScript的适配。

由于缺乏详细的说明,因此是否有参考价值尚未确定。如果在所述环境下进行这样的修正,您可以将其视为一个支持TypeScript的案例。

相关文章索引

    • 第12回「GraphQLにおけるRelayスタイルによるページング実装再考(Window関数使用版)」

 

    • 第11回「Dataloadersを使ったN+1問題への対応」

 

    • 第10回「GraphQL(gqlgen)エラーハンドリング」

 

    • 第9回「GraphQLにおける認証認可事例(Auth0 RBAC仕立て)」

 

    • 第8回「GraphQL/Nuxt.js(TypeScript/Vuetify/Apollo)/Golang(gqlgen)/Google Cloud Storageの組み合わせで動画ファイルアップロード実装例」

 

    • 第7回「GraphQLにおけるRelayスタイルによるページング実装(後編:フロントエンド)」

 

    • 第6回「GraphQLにおけるRelayスタイルによるページング実装(前編:バックエンド)」

 

    • 第5回「DB接続付きGraphQLサーバ(by Golang)をローカルマシン上でDockerコンテナ起動」

 

    • 第4回「graphql-codegenでフロントエンドをGraphQLスキーマファースト」

 

    • 第3回「go+gqlgenでGraphQLサーバを作る(GORM使ってDB接続)」

 

    • 第2回「NuxtJS(with Apollo)のTypeScript対応」

 

    第1回「frontendに「nuxtjs/apollo」、backendに「go+gqlgen」の組み合わせでGraphQLサービスを作る」

开发环境

操作系统 – Linux(Ubuntu)

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"

# 前端

Nuxt.js是一个用于构建高度可扩展且现代化的Vue.js应用程序的框架。

$ cat yarn.lock | grep "@nuxt/vue-app"
    "@nuxt/vue-app" "2.11.0"
"@nuxt/vue-app@2.11.0":
  resolved "https://registry.yarnpkg.com/@nuxt/vue-app/-/vue-app-2.11.0.tgz#05aa5fd7cc69bcf6a763b89c51df3bd27b58869e"

包管理器 – Yarn

$ yarn -v
1.19.2

IDE – WebStorm

集成开发环境 – WebStorm

WebStorm 2019.3
Build #WS-193.5233.80, built on November 25, 2019

请参阅

https://typescript.nuxtjs.org/ja/guide/ -> https://typescript.nuxtjs.org/zh/guide/
https://github.com/nuxt-community/nuxt-property-decorator -> https://github.com/nuxt-community/nuxt-property-decorator

实践

从上一篇文章完成的源代码中查看差异可能更加直观,比一步一步地写出每个步骤要容易理解呢。

引入TypeScript

■ 包文件.

添加了一些在参考网站中提到的模块。
不仅仅是为了简单地支持TypeScript,还添加了vue-apollo来支持GraphQL使用Apollo。

diff --git a/frontend/package.json b/frontend/package.json
index 67223cb..b0b174f 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -5,7 +5,7 @@
   "author": "sky0621",
   "private": true,
   "scripts": {
-    "dev": "nuxt",
+    "dev": "nuxt --port 3000",
     "build": "nuxt build",
     "start": "nuxt start",
     "generate": "nuxt generate",
@@ -13,9 +13,13 @@
   },
   "dependencies": {
     "@nuxtjs/apollo": "^4.0.0-rc17",
-    "nuxt": "^2.0.0"
+    "@typescript-eslint/parser": "^2.12.0",
+    "nuxt": "^2.0.0",
+    "nuxt-property-decorator": "^2.5.0",
+    "vue-apollo": "^3.0.2"
   },
   "devDependencies": {
+    "@nuxt/typescript-build": "^0.5.2",
     "@nuxtjs/eslint-config": "^1.0.1",
     "@nuxtjs/eslint-module": "^1.0.0",
     "@nuxtjs/vuetify": "^1.0.0",

■ nuxt.config.js文件

diff --git a/frontend/nuxt.config.js b/frontend/nuxt.config.js
index 8454218..14392a5 100644
--- a/frontend/nuxt.config.js
+++ b/frontend/nuxt.config.js
@@ -3,7 +3,7 @@ import colors from 'vuetify/es5/util/colors'
 export default {
   mode: 'universal',
   /*
-   ** Headers of the page
+   ** Headers of the pagebuildModules
    */
   head: {
     titleTemplate: '%s - ' + process.env.npm_package_name,
@@ -37,7 +37,8 @@ export default {
   buildModules: [
     // Doc: https://github.com/nuxt-community/eslint-module
     '@nuxtjs/eslint-module',
-    '@nuxtjs/vuetify'
+    '@nuxtjs/vuetify',
+    '@nuxt/typescript-build'
   ],
   /*
    ** Nuxt.js modules
@@ -68,8 +69,8 @@ export default {
   apollo: {
     clientConfigs: {
       default: {
-        // Goサーバを 8080 ポートで起動する予定のため
-        httpEndpoint: 'http://localhost:8080/query'
+        // Goサーバを 5050 ポートで起動する予定のため
+        httpEndpoint: 'http://localhost:5050/query'
       }
     },
     // 任意だけど、これがないとGraphQL的なエラー起きた時に原因が掴みづらいため
@@ -80,9 +81,14 @@ export default {
    ** Build configuration
    */
   build: {
+    babel: {
+      plugins: [
+        ['@babel/plugin-proposal-decorators', { legacy: true }],
+        ['@babel/plugin-proposal-class-properties', { loose: true }]
+      ]
+    }
     /*
      ** You can extend webpack config here
      */
-    extend(config, ctx) {}
   }
 }

■ tsconfig.json 的中文本土化版本

diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..391e78e
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,34 @@
+{
+  "compilerOptions": {
+    "target": "es2018",
+    "module": "esnext",
+    "experimentalDecorators": true,
+    "moduleResolution": "node",
+    "lib": [
+      "esnext",
+      "esnext.asynciterable",
+      "dom"
+    ],
+    "esModuleInterop": true,
+    "allowJs": true,
+    "sourceMap": true,
+    "strict": true,
+    "noEmit": true,
+    "baseUrl": ".",
+    "paths": {
+      "~/*": [
+        "./*"
+      ],
+      "@/*": [
+        "./*"
+      ]
+    },
+    "types": [
+      "@types/node",
+      "@nuxt/types"
+    ]
+  },
+  "exclude": [
+    "node_modules"
+  ]
+}

■ vue-shim.d.ts (用中文解释)

这是一个 vue-shim.d.ts 文件。

diff --git a/frontend/vue-shim.d.ts b/frontend/vue-shim.d.ts
new file mode 100644
index 0000000..eb40980
--- /dev/null
+++ b/frontend/vue-shim.d.ts
@@ -0,0 +1,4 @@
+declare module "*.vue" {
+  import Vue from 'vue'
+  export default Vue
+}

■ .eslintrc.js的中文翻译

diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js
index 6b8177c..f30bc4f 100644
--- a/frontend/.eslintrc.js
+++ b/frontend/.eslintrc.js
@@ -5,7 +5,7 @@ module.exports = {
     node: true
   },
   parserOptions: {
-    parser: 'babel-eslint'
+    parser: '@typescript-eslint/parser'
   },
   extends: [
     '@nuxtjs',

■ 页面/主页.vue

diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue
index 7587e44..c8a8896 100644
--- a/frontend/pages/index.vue
+++ b/frontend/pages/index.vue
@@ -4,10 +4,13 @@
   </div>
 </template>

-<script>
+<script lang="ts">
+import { Vue, Component } from 'nuxt-property-decorator'
+import 'vue-apollo'
 import TodoCard from '~/components/TodoCard.vue'

-export default {
+@Component({
   components: { TodoCard }
-}
+})
+export default class IndexPage extends Vue {}
 </script>

■ 组件/待办卡片.vue

diff --git a/frontend/components/TodoCard.vue b/frontend/components/TodoCard.vue
index 5bdbc66..d740996 100644
--- a/frontend/components/TodoCard.vue
+++ b/frontend/components/TodoCard.vue
@@ -25,20 +25,32 @@
   </div>
 </template>

-<script>
+<script lang="ts">
+import { Vue, Component } from 'nuxt-property-decorator'
+import 'vue-apollo'
 import todos from '~/apollo/queries/todos.gql'
-export default {
-  data() {
-    return {
-      todos: []
-    }
-  },

+interface User {
+  id: String
+  name: String
+}
+
+interface Todo {
+  id: String
+  text: String
+  done: Boolean
+  user: User
+}
+
+@Component({
   apollo: {
     todos: {
       prefetch: true,
       query: todos
     }
   }
+})
+export default class TodoCard extends Vue {
+  todos: Todo[] = []
 }
 </script>

在支持TypeScript之后的代码。

实际上,我觉得看到经过处理后的源代码更容易理解。
既然我们已经选择了TypeScript化,所以我改用基于类的编写方式。

<template>
  <div>
    <TodoCard />
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'nuxt-property-decorator'
import 'vue-apollo'
import TodoCard from '~/components/TodoCard.vue'

@Component({
  components: { TodoCard }
})
export default class IndexPage extends Vue {}
</script>
<template>
  <div>
    <v-row>
      <v-col cols="12" sm="6" offset-sm="3">
        <v-card>
          <v-list two-line subheader>
            <v-list-item v-for="todo in todos" :key="todo.id" link>
              <v-list-item-avatar>
                <v-icon>mdi-gift-outline</v-icon>
              </v-list-item-avatar>
              <v-list-item-content>
                <v-list-item-title>{{ todo.text }}</v-list-item-title>
                <v-list-item-subtitle>{{ todo.done }}</v-list-item-subtitle>
              </v-list-item-content>
              <v-list-item-content>
                <v-list-item-title>
                  {{ todo.user.name }}
                </v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list>
        </v-card>
      </v-col>
    </v-row>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'nuxt-property-decorator'
import 'vue-apollo'
import todos from '~/apollo/queries/todos.gql'

interface User {
  id: String
  name: String
}

interface Todo {
  id: String
  text: String
  done: Boolean
  user: User
}

@Component({
  apollo: {
    todos: {
      prefetch: true,
      query: todos
    }
  }
})
export default class TodoCard extends Vue {
  todos: Todo[] = []
}
</script>

总结

这样一来,我在本地成功进行了与上一次相同的操作确认。
这次,虽然我自己定义了作为通过GraphQL获得的响应的类型的接口,但从GraphQL模式自动生成可能更好,所以我以后可能会尝试这方面的工作。
还有,nuxt-config.js等文件最终仍然保留为JS,如果可能的话,我也想将它们改为TS。

本次所有的源代码如下:
https://github.com/sky0621/study-graphql/tree/v0.2.0

广告
将在 10 秒后关闭
bannerAds