{"id":47812,"date":"2023-05-22T15:19:25","date_gmt":"2023-01-15T02:24:13","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/"},"modified":"2024-04-30T05:24:59","modified_gmt":"2024-04-29T21:24:59","slug":"%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/","title":{"rendered":"\u4f7f\u7528&#8221;Nuxt.js\/Apollo&#8221;\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a&#8221;gqlgen&#8221;\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1"},"content":{"rendered":"<h1>\u8bf7\u7528\u4e2d\u6587\u8fdb\u884c\u4ee5\u4e0b\u7684\u91ca\u4e49\uff0c\u53ea\u9700\u8981\u4e00\u4e2a\u9009\u9879\uff1a<\/h1>\n<p>\u304a\u984c \u2192 \u8bdd\u9898<\/p>\n<p>\u6211\u5011\u5c07\u901a\u904e\u4e00\u500b\u7c21\u55ae\u7684ToDo\u61c9\u7528\u7a0b\u5f0f\uff08\u5118\u7ba1\u5728\u9019\u7bc7\u6587\u7ae0\u4e2d\u53ea\u80fd\u9032\u884c\u201c\u65b0ToDo\u8a3b\u518a\u201d\u548c\u201c\u986f\u793a\u6240\u6709\u5df2\u767b\u8a18\u7684ToDo\u201d\uff09\u4f5c\u70ba\u4e3b\u984c\uff0c\u4f86\u78ba\u8a8d\u4f7f\u7528GraphQL\u901a\u4fe1\u908f\u8f2f\u7684\u6548\u679c\u3002\u8acb\u6ce8\u610f\uff0c\u672c\u6b21\u6211\u5011\u5c07\u4e0d\u4f7f\u7528\u95dc\u4fc2\u8cc7\u6599\u5eab\u9032\u884c\u6301\u4e45\u5316\uff0c\u800c\u662f\u7531\u5f8c\u7aef\u8fd4\u56de\u56fa\u5b9a\u503c\u3002<\/p>\n<h1>\u524d\u63d0\u6761\u4ef6<\/h1>\n<p>\u5bf9\u4e8eNuxt.js\u548cGo\uff0c\u6709\u4e2a\u4eba\u6216\u516c\u53f8\u7684\u5f00\u53d1\u7ecf\u9a8c\uff0c\u524d\u7aef-&gt;\u540e\u7aef\u7684\u8fde\u63a5\u662f\u901a\u8fc7REST\uff08\u4f8b\u5982\u4f7f\u7528Axios\uff09\u6765\u5b9e\u73b0\u7684\uff0c\u4f46\u662f\u5e0c\u671b\u5c1d\u8bd5\u4f7f\u7528GraphQL\u7684\u4eba\u53ef\u4ee5\u53c2\u8003\u3002<br \/>\n\u7136\u800c\uff0c\u4e0d\u9700\u8981\u5199\u5173\u4e8e&#8221;GraphQL\u5230\u5e95\u662f\u4ec0\u4e48\uff1f&#8221;\u6216&#8221;\u4e0eREST\u76f8\u6bd4\u7684\u4f18\u7f3a\u70b9\u662f\u4ec0\u4e48\uff1f&#8221;\u8fd9\u4e9b\u5185\u5bb9\uff08\u56e0\u4e3a\u5df2\u7ecf\u6709\u5f88\u591a\u6587\u7ae0\u4e86\uff09\u3002<\/p>\n<p>\u6b64\u5916\uff0c\u6839\u636e\u9898\u76ee\u8981\u6c42\uff0c\u4ee5\u6700\u7b80\u7ed3\u6784\u8fdb\u884c\u5b9e\u73b0\u3002\u4e0d\u8003\u8651\u6d41\u884c\u7684Clean Architecture\u548cDDD\u6240\u9075\u5faa\u7684\u5305\u7ed3\u6784\u7b49\u3002\u8fd9\u65b9\u9762\uff0c\u6211\u4e4b\u524d\u5199\u8fc7\u4e00\u7bc7\u7c7b\u4f3c\u7684\u6587\u7ae0\u3002\u4e0d\u8fc7\u5e76\u4e0d\u4ec5\u4ec5\u53ea\u6709\u8fd9\u7bc7\u6587\u7ae0\uff0c\u5982\u679c\u641c\u7d22\u4e00\u4e0b\uff0c\u4f1a\u6709\u5f88\u591a\u66f4\u597d\u7684\u6587\u7ae0\u51fa\u73b0\u3002\u4f7f\u7528Golang\u5b9e\u73b0\u7684Clean Architecture\uff08\u4f7f\u7528Echo\u3001Gorm\u548cwire\uff09\u3002<\/p>\n<h1>\u76f8\u5173\u6587\u7ae0\u7d22\u5f15 (Guanlian Wenzhang Suoyin)<\/h1>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c12\u56de\u300cGraphQL\u306b\u304a\u3051\u308bRelay\u30b9\u30bf\u30a4\u30eb\u306b\u3088\u308b\u30da\u30fc\u30b8\u30f3\u30b0\u5b9f\u88c5\u518d\u8003(Window\u95a2\u6570\u4f7f\u7528\u7248)\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c11\u56de\u300cDataloaders\u3092\u4f7f\u3063\u305fN+1\u554f\u984c\u3078\u306e\u5bfe\u5fdc\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c10\u56de\u300cGraphQL(gqlgen)\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff19\u56de\u300cGraphQL\u306b\u304a\u3051\u308b\u8a8d\u8a3c\u8a8d\u53ef\u4e8b\u4f8b\uff08Auth0 RBAC\u4ed5\u7acb\u3066\uff09\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff18\u56de\u300cGraphQL\/Nuxt.js(TypeScript\/Vuetify\/Apollo)\/Golang(gqlgen)\/Google Cloud Storage\u306e\u7d44\u307f\u5408\u308f\u305b\u3067\u52d5\u753b\u30d5\u30a1\u30a4\u30eb\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u5b9f\u88c5\u4f8b\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff17\u56de\u300cGraphQL\u306b\u304a\u3051\u308bRelay\u30b9\u30bf\u30a4\u30eb\u306b\u3088\u308b\u30da\u30fc\u30b8\u30f3\u30b0\u5b9f\u88c5\uff08\u5f8c\u7de8\uff1a\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\uff09\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff16\u56de\u300cGraphQL\u306b\u304a\u3051\u308bRelay\u30b9\u30bf\u30a4\u30eb\u306b\u3088\u308b\u30da\u30fc\u30b8\u30f3\u30b0\u5b9f\u88c5\uff08\u524d\u7de8\uff1a\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\uff09\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff15\u56de\u300cDB\u63a5\u7d9a\u4ed8\u304dGraphQL\u30b5\u30fc\u30d0(by Golang)\u3092\u30ed\u30fc\u30ab\u30eb\u30de\u30b7\u30f3\u4e0a\u3067Docker\u30b3\u30f3\u30c6\u30ca\u8d77\u52d5\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff14\u56de\u300cgraphql-codegen\u3067\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u3092GraphQL\u30b9\u30ad\u30fc\u30de\u30d5\u30a1\u30fc\u30b9\u30c8\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff13\u56de\u300cgo+gqlgen\u3067GraphQL\u30b5\u30fc\u30d0\u3092\u4f5c\u308b\uff08GORM\u4f7f\u3063\u3066DB\u63a5\u7d9a\uff09\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u7b2c\uff12\u56de\u300cNuxtJS(with Apollo)\u306eTypeScript\u5bfe\u5fdc\u300d<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\u7b2c\uff11\u56de\u300cfrontend\u306b\u300cnuxtjs\/apollo\u300d\u3001backend\u306b\u300cgo+gqlgen\u300d\u306e\u7d44\u307f\u5408\u308f\u305b\u3067GraphQL\u30b5\u30fc\u30d3\u30b9\u3092\u4f5c\u308b\u300d<\/ul>\n<h1>\u5f00\u53d1\u73af\u5883<\/h1>\n<h2>\u64cd\u4f5c\u7cfb\u7edf &#8211; Linux\uff08Ubuntu\uff09<\/h2>\n<pre class=\"post-pre\"><code>$ cat \/etc\/os-release\r\nNAME=\"Ubuntu\"\r\nVERSION=\"18.04.2 LTS (Bionic Beaver)\"\r\n<\/code><\/pre>\n<h2>\u524d\u7aef\u6280\u672f<br \/>\n\u524d\u7aef\u5f00\u53d1<br \/>\n\u524d\u7aef\u8bbe\u8ba1<\/h2>\n<h3>Nuxt.js\uff1a\u52a9\u529b\u4e8e\u6784\u5efa Vue.js \u5e94\u7528\u7a0b\u5e8f\u7684\u6846\u67b6\u3002<\/h3>\n<pre class=\"post-pre\"><code>$ cat yarn.lock | grep \"@nuxt\/vue-app\"\r\n    \"@nuxt\/vue-app\" \"2.10.2\"\r\n<\/code><\/pre>\n<h3>\u5305\u7ba1\u7406\u5668 &#8211; Yarn<\/h3>\n<pre class=\"post-pre\"><code>$ yarn -v\r\n1.19.1\r\n<\/code><\/pre>\n<h3>IDE &#8211; WebStorm<\/h3>\n<p>\u96c6\u6210\u5f00\u53d1\u73af\u5883 &#8211; WebStorm<\/p>\n<pre class=\"post-pre\"><code>WebStorm 2019.2.4\r\nBuild #WS-192.7142.35, built on October 29, 2019\r\n<\/code><\/pre>\n<h2># \u540e\u7aef<\/h2>\n<h3>\u8bf4\u8bdd &#8211; \u8fdb\u884c<\/h3>\n<pre class=\"post-pre\"><code>$ go version\r\ngo version go1.13.3 linux\/amd64\r\n<\/code><\/pre>\n<h3>\u5305\u7ba1\u7406\u5668-Go\u6a21\u5757<\/h3>\n<h3>IDE &#8211; Goland<br \/>\n\u96c6\u6210\u5f00\u53d1\u73af\u5883 &#8211; Goland<\/h3>\n<pre class=\"post-pre\"><code>GoLand 2019.2.5\r\nBuild #GO-192.7142.48, built on November 8, 2019\r\n<\/code><\/pre>\n<h1>\u8bf7\u5f15\u7528<\/h1>\n<h2>GraphQL (\u7528\u4e2d\u6587: \u56fe\u7075\u6570\u636e\u67e5\u8be2\u8bed\u8a00)<\/h2>\n<h2>\u524d\u7aef\u6280\u672f<\/h2>\n<h2>\u540e\u7aef<\/h2>\n<h1>\u5b9e\u8df5<\/h1>\n<p>\u5728GitHub\u4e0a\u521b\u5efa\u4e00\u4e2a\u9002\u5f53\u7684\u4ee3\u7801\u5e93\u5e76\u8fdb\u884c\u672c\u5730git\u514b\u9686\u64cd\u4f5c\u3002<br \/>\n\u8fd9\u662f\u6839\u636e\u6211\u7684\u73af\u5883\u6240\u505a\u7684\u8bbe\u7f6e\u3002<\/p>\n<pre class=\"post-pre\"><code>$ pwd\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\r\n<\/code><\/pre>\n<h2>\u524d\u7aef<\/h2>\n<h3>\u4f7f\u7528 create-nuxt-app \u547d\u4ee4\u521b\u5efa\u4e00\u4e2a\u7528\u4e8e\u524d\u7aef\u7684 Nuxt.js \u9879\u76ee\u3002<\/h3>\n<p>\u5de5\u5177\u7684\u9009\u62e9\u8bf7\u53c2\u8003\u4ee5\u4e0b\u53c2\u8003\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">UI\u306fVuetify.js<\/ul>\n<\/li>\n<\/ul>\n<p>SSR\u3068SPA\u306f\u3069\u3063\u3061\u3067\u3082\u3044\u3044\u3051\u3069\u30c7\u30d5\u30a9\u306eSSR<br \/>\n\u4eca\u56de\u306f\u30c6\u30b9\u30c8\u307e\u3067\u8003\u3048\u3066\u306a\u3044\u306e\u3067\u30c6\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u306f\u7121\u3057<br \/>\n\u30b5\u30fc\u30d0\u30fc\u30b5\u30a4\u30c9\u3068\u306e\u63a5\u7d9a\u306fGraphQL\u306a\u306e\u3067Axios\u306a\u3069\u306f\u7121\u3057<\/p>\n<pre class=\"post-pre\"><code>$ yarn create nuxt-app frontend\r\nyarn create v1.19.1\r\n\u3000\u3000\u3000\u30fb\u30fb\u30fb\r\nsuccess Installed \"create-nuxt-app@2.11.1\" with binaries:\r\n      - create-nuxt-app\r\n\r\ncreate-nuxt-app v2.11.1\r\n\u2728  Generating Nuxt.js project in frontend\r\n? Project name frontend\r\n? Project description My ace Nuxt.js project\r\n? Author name sky0621\r\n? Choose the package manager Yarn\r\n? Choose UI framework Vuetify.js\r\n? Choose custom server framework None (Recommended)\r\n? Choose Nuxt.js modules (Press &lt;space&gt; to select, &lt;a&gt; to toggle all, &lt;i&gt; to invert selection)\r\n? Choose linting tools ESLint, Prettier\r\n? Choose test framework None\r\n? Choose rendering mode Universal (SSR)\r\n? Choose development tools (Press &lt;space&gt; to select, &lt;a&gt; to toggle all, &lt;i&gt; to invert selection)\r\nyarn run v1.19.1\r\n$ eslint --ext .js,.vue --ignore-path .gitignore . --fix\r\nDone in 2.90s.\r\n\r\n?  Successfully created project frontend\r\n<\/code><\/pre>\n<p>\u76ee\u524d\u7684\u76ee\u5f55\u7ed3\u6784\u5982\u4e0b\u3002<\/p>\n<pre class=\"post-pre\"><code>$ pwd\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\r\n$\r\n$ tree -L 2\r\n.\r\n\u251c\u2500\u2500 frontend\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 assets\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 components\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 layouts\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 middleware\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 node_modules\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 nuxt.config.js\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 package.json\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 pages\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 plugins\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 README.md\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 static\r\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 store\r\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 yarn.lock\r\n\u2514\u2500\u2500 README.md\r\n<\/code><\/pre>\n<p>\u5e76\u4e14\uff0c\u4e3a\u4e86\u4fdd\u9669\u8d77\u89c1\uff0c\u4e5f\u628a\u8f6f\u4ef6\u5305\u7684devDependencies\u5217\u5165\u3002<\/p>\n<pre class=\"post-pre\"><code>$ cat frontend\/package.json \r\n{\r\n\u3000\u3000\u30fb\u30fb\u30fb\r\n  \"dependencies\": {\r\n    \"nuxt\": \"^2.0.0\"\r\n  },\r\n  \"devDependencies\": {\r\n    \"@nuxtjs\/vuetify\": \"^1.0.0\",\r\n    \"@nuxtjs\/eslint-config\": \"^1.0.1\",\r\n    \"@nuxtjs\/eslint-module\": \"^1.0.0\",\r\n    \"babel-eslint\": \"^10.0.1\",\r\n    \"eslint\": \"^6.1.0\",\r\n    \"eslint-plugin-nuxt\": \"&gt;=0.4.2\",\r\n    \"eslint-config-prettier\": \"^4.1.0\",\r\n    \"eslint-plugin-prettier\": \"^3.0.1\",\r\n    \"prettier\": \"^1.16.4\"\r\n  }\r\n}\r\n<\/code><\/pre>\n<h3>nuxtjs\/apollo\u7684\u5b89\u88c5\u5f15\u5165<\/h3>\n<h4>\u589e\u52a0\u8f6f\u4ef6\u5305<\/h4>\n<pre class=\"post-pre\"><code>$ cd frontend\/\r\n$\r\n$ pwd\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/frontend\r\n$\r\n$ yarn add @nuxtjs\/apollo\r\nyarn add v1.19.1\r\n[1\/4] Resolving packages...\r\n[2\/4] Fetching packages...\r\ninfo fsevents@2.1.2: The platform \"linux\" is incompatible with this module.\r\n\u3000\u3000\u30fb\u30fb\u30fb\r\nDone in 15.54s.\r\n<\/code><\/pre>\n<h4>\u5411nuxt-config.js\u6587\u4ef6\u6dfb\u52a0\u914d\u7f6e\u4fe1\u606f<\/h4>\n<pre class=\"post-pre\"><code>$ git diff frontend\/nuxt.config.js\r\ndiff --git a\/frontend\/nuxt.config.js b\/frontend\/nuxt.config.js\r\nindex 25a0fe4..afc0db4 100644\r\n--- a\/frontend\/nuxt.config.js\r\n+++ b\/frontend\/nuxt.config.js\r\n@@ -42,7 +42,7 @@ export default {\r\n   \/*\r\n    ** Nuxt.js modules\r\n    *\/\r\n-  modules: [],\r\n+  modules: ['@nuxtjs\/apollo'],\r\n   \/*\r\n    ** vuetify module configuration\r\n    ** https:\/\/github.com\/nuxt-community\/vuetify-module\r\n@@ -64,6 +64,18 @@ export default {\r\n       }\r\n     }\r\n   },\r\n+\r\n+  apollo: {\r\n+    clientConfigs: {\r\n+      default: {\r\n+        \/\/ Go\u30b5\u30fc\u30d0\u3092 8080 \u30dd\u30fc\u30c8\u3067\u8d77\u52d5\u3059\u308b\u4e88\u5b9a\u306e\u305f\u3081\r\n+        httpEndpoint: 'http:\/\/localhost:8080\/'\r\n+      }\r\n+    },\r\n+    \/\/ \u4efb\u610f\u3060\u3051\u3069\u3001\u3053\u308c\u304c\u306a\u3044\u3068GraphQL\u7684\u306a\u30a8\u30e9\u30fc\u8d77\u304d\u305f\u6642\u306b\u539f\u56e0\u304c\u63b4\u307f\u3065\u3089\u3044\u305f\u3081\r\n+    errorHandler: '~\/plugins\/apollo-error-handler.js'\r\n+  },\r\n+\r\n   \/*\r\n    ** Build configuration\r\n    *\/\r\n<\/code><\/pre>\n<h4>GraphQL\u9519\u8bef\u5904\u7406\u63d2\u4ef6<\/h4>\n<pre class=\"post-pre\"><code>$ cat frontend\/plugins\/apollo-error-handler.js \r\nexport default (error, context) =&gt; {\r\n  console.log(error)\r\n  context.error({ statusCode: 304, message: 'Server error' })\r\n}\r\n<\/code><\/pre>\n<p>\u53c2\u8003\u4ee5\u4e0b\u94fe\u63a5\u7684\u5185\u5bb9\uff1ahttps:\/\/github.com\/nuxt-community\/apollo-module<\/p>\n<h3>\u524d\u7aef\u542f\u52a8<\/h3>\n<p>\u5148\u8bd5\u7740\u542f\u52a8\u4e00\u4e0b\uff0c\u770b\u770b\u76ee\u524d\u4e3a\u6b62\u80fd\u8fbe\u5230\u4ec0\u4e48\u7a0b\u5ea6\u3002<\/p>\n<pre class=\"post-pre\"><code>$ pwd\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/frontend\r\n$\r\n$ yarn run dev\r\nyarn run v1.19.1\r\n$ nuxt\r\n\r\n WARN  Address localhost:8080 is already in use.                                                                                                                                                                                                           11:40:12\r\n\r\n\u2139 Trying a random port...                                                                                                                                                                                                                                  11:40:12\r\n\r\n   \u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\r\n   \u2502                                             \u2502\r\n   \u2502   Nuxt.js v2.10.2                           \u2502\r\n   \u2502   Running in development mode (universal)   \u2502\r\n   \u2502                                             \u2502\r\n   \u2502   Listening on: http:\/\/localhost:44171\/     \u2502\r\n   \u2502                                             \u2502\r\n   \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\r\n\r\n\u2139 Preparing project for development                                                                                                                                                                                                                        11:40:13\r\n\u2139 Initial build may take a while                                                                                                                                                                                                                           11:40:13\r\n\u2714 Builder initialized                                                                                                                                                                                                                                      11:40:13\r\n\u2714 Nuxt files generated                                                                                                                                                                                                                                     11:40:13\r\n\r\n\u25cf Client \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 building (35%) 215\/225 modules 10 active\r\n node_modules\/vuetify\/dist\/vuetify.js\r\n\r\n\u25cf Server \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 building (19%) 81\/81 modules 0 active\r\n\r\n\r\n\r\n ERROR  Failed to compile with 1 errors                                                                                                                                                                                                    friendly-errors 11:40:31\r\n\r\n\r\n ERROR  in .\/plugins\/apollo-error-handler.js                                                                                                                                                                                               friendly-errors 11:40:31\r\n\r\nModule Error (from .\/node_modules\/eslint-loader\/dist\/cjs.js):                                                                                                                                                                              friendly-errors 11:40:31\r\n\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/frontend\/plugins\/apollo-error-handler.js\r\n  2:3  warning  Unexpected console statement  no-console\r\n  5:1  error    Delete `\u23ce`                    prettier\/prettier\r\n\r\n\u2716 2 problems (1 error, 1 warning)\r\n  1 error and 0 warnings potentially fixable with the `--fix` option.\r\n\r\n                                                                                                                                                                                                                                           friendly-errors 11:40:31\r\n @ .\/.nuxt\/apollo-module.js 93:13-57\r\n @ .\/.nuxt\/index.js\r\n @ .\/.nuxt\/client.js\r\n @ multi eventsource-polyfill webpack-hot-middleware\/client?reload=true&amp;timeout=30000&amp;ansiColors=&amp;overlayStyles=&amp;name=client&amp;path=\/__webpack_hmr\/client .\/.nuxt\/client.js\r\n                                                                                                                                                                                                                                           friendly-errors 11:40:31\r\n\u2139 Waiting for file changes                                                                                                                                                                                                                                 11:40:31\r\n\u2139 Memory usage: 433 MB (RSS: 559 MB)                                                                                                                                                                                                                       11:40:31\r\n\r\n ERROR  ENOSPC: System limit for number of file watchers reached, watch '\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/frontend\/node_modules\/@nuxt\/vue-app\/template\/views\/loading'                                                                    11:40:31\r\n\r\n  at FSWatcher.start (internal\/fs\/watchers.js:165:26)\r\n  at Object.watch (fs.js:1329:11)\r\n  at createFsWatchInstance (node_modules\/@nuxt\/builder\/node_modules\/chokidar\/lib\/nodefs-handler.js:118:15)\r\n  at setFsWatchListener (node_modules\/@nuxt\/builder\/node_modules\/chokidar\/lib\/nodefs-handler.js:165:15)\r\n  at NodeFsHandler._watchWithNodeFs (node_modules\/@nuxt\/builder\/node_modules\/chokidar\/lib\/nodefs-handler.js:330:14)\r\n  at NodeFsHandler._handleDir (node_modules\/@nuxt\/builder\/node_modules\/chokidar\/lib\/nodefs-handler.js:551:19)\r\n  at runMicrotasks (&lt;anonymous&gt;)\r\n  at processTicksAndRejections (internal\/process\/task_queues.js:93:5)\r\n  at async NodeFsHandler._addToNodeFs (node_modules\/@nuxt\/builder\/node_modules\/chokidar\/lib\/nodefs-handler.js:600:16)\r\n<\/code><\/pre>\n<p>\u6211\u88ab\u8d23\u5907\u4e86\u3002Prettier\u7684\u68c0\u67e5\u5df2\u7ecf\u8fdb\u884c\u4e86\u3002<br \/>\n\u6309\u7167\u88ab\u544a\u77e5\u7684\uff0c\u8fdb\u884clint\u4fee\u590d\u3002<\/p>\n<pre class=\"post-pre\"><code>$ yarn run lint --fix\r\nyarn run v1.19.1\r\n$ eslint --ext .js,.vue --ignore-path .gitignore . --fix\r\n\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/frontend\/plugins\/apollo-error-handler.js\r\n  2:3  warning  Unexpected console statement  no-console\r\n\r\n\u2716 1 problem (0 errors, 1 warning)\r\n\r\nDone in 2.27s.\r\n<\/code><\/pre>\n<p>\u7136\u540e\uff0c\u6210\u529f\u542f\u52a8\u4e86\u3002<br \/>\n\u867d\u7136\u4f3c\u4e4e\u51fa\u73b0\u4e86\u4e00\u4e2a\u8b66\u544a\uff0c\u4f46\u662f\u8fd9\u662f\u4e3a\u4e86\u8c03\u8bd5\u800c\u5728\u9519\u8bef\u5904\u7406\u5668\u4e2d\u8f93\u51fa\u5230\u63a7\u5236\u53f0\u7684\u65e5\u5fd7\u5417\uff1f<br \/>\n\u5047\u8bbe\u5728\u6b63\u5f0f\u53d1\u5e03\u65f6\u4f1a\u5220\u9664\uff0c\u6240\u4ee5\u6682\u65f6\u5ffd\u7565\u5b83\uff08\u53cd\u6b63\u4e5f\u4e0d\u4f1a\u6b63\u5f0f\u53d1\u5e03\uff09\u3002<\/p>\n<pre class=\"post-pre\"><code>\u3000\u3000\u301c\u301c\u301c\r\n\r\n\u21bb Updated plugins\/apollo-error-handler.js                                                                                                                                                                                                                  11:45:05\r\n\r\n\u2714 Client\r\n  Compiled successfully in 694.86ms\r\n\r\n\u2714 Server\r\n  Compiled successfully in 823.17ms\r\n\r\n\r\n WARN  Compiled with 1 warnings                                                                                                                                                                                                            friendly-errors 11:45:07\r\n\r\nModule Warning (from .\/node_modules\/eslint-loader\/dist\/cjs.js):                                                                                                                                                                            friendly-errors 11:45:07\r\n\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/frontend\/plugins\/apollo-error-handler.js\r\n  2:3  warning  Unexpected console statement  no-console\r\n\r\n\u2716 1 problem (0 errors, 1 warning)\r\n\r\n                                                                                                                                                                                                                                           friendly-errors 11:45:07\r\nYou may use special comments to disable some warnings.                                                                                                                                                                                     friendly-errors 11:45:07\r\nUse \/\/ eslint-disable-next-line to ignore the next line.                                                                                                                                                                                   friendly-errors 11:45:07\r\nUse \/* eslint-disable *\/ to ignore all warnings in a file.                                                                                                                                                                                 friendly-errors 11:45:07\r\n<\/code><\/pre>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d8120913a08637a6ac5c6\/57-0.png\" alt=\"screenshot-localhost-44171-2019.11.16-11-56-29.png\" \/><\/div>\n<h2>\u540e\u53f0<\/h2>\n<h3>\u521b\u5efa\u7528\u4e8e\u5b58\u50a8\u540e\u7aef\u6e90\u4ee3\u7801\u7684\u76ee\u5f55\u4ee5\u53ca\u7528\u4e8e\u5b58\u50a8GraphQL\u6a21\u5f0f\u7684\u76ee\u5f55\u3002<\/h3>\n<pre class=\"post-pre\"><code>$ pwd\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\r\n$ tree -L 1\r\n.\r\n\u251c\u2500\u2500 frontend\r\n\u2514\u2500\u2500 README.md\r\n\r\n1 directory, 1 file\r\n$ mkdir backend\r\n$ tree -L 1\r\n.\r\n\u251c\u2500\u2500 backend\r\n\u251c\u2500\u2500 frontend\r\n\u2514\u2500\u2500 README.md\r\n<\/code><\/pre>\n<h3>Go\u9879\u76ee\u521d\u59cb\u5316<\/h3>\n<pre class=\"post-pre\"><code>$ cd backend\/\r\n$ go mod init github.com\/sky0621\/study-graphql\/backend\r\ngo: creating new go.mod: module github.com\/sky0621\/study-graphql\/backend$ tree -L 1\r\n.\r\n\u2514\u2500\u2500 go.mod\r\n\r\n0 directories, 1 file\r\n$ cat go.mod \r\nmodule github.com\/sky0621\/study-graphql\/backend\r\n\r\ngo 1.13\r\n<\/code><\/pre>\n<h3>\u901a\u8fc7gqlgen\u547d\u4ee4\u751f\u6210\u9aa8\u67b6\u3002<\/h3>\n<p>\u4e00\u4e0b\u5b50\u5c31\u4f1a\u81ea\u52a8\u751f\u6210\u5404\u79cd\u6587\u4ef6\u3002\uff08\u751a\u81f3\u4e0d\u9700\u8981\u7f16\u5199GraphQL\u6a21\u5f0f\u5c31\u80fd\u4e3a\u4f60\u51c6\u5907\u6837\u4f8b\uff09<\/p>\n<pre class=\"post-pre\"><code>$ go run github.com\/99designs\/gqlgen init\r\nExec \"go run .\/server\/server.go\" to start GraphQL server\r\n$\r\n$ tree -L 2\r\n.\r\n\u251c\u2500\u2500 generated.go\r\n\u251c\u2500\u2500 go.mod\r\n\u251c\u2500\u2500 go.sum\r\n\u251c\u2500\u2500 gqlgen.yml\r\n\u251c\u2500\u2500 models_gen.go\r\n\u251c\u2500\u2500 resolver.go\r\n\u251c\u2500\u2500 schema.graphql\r\n\u2514\u2500\u2500 server\r\n    \u2514\u2500\u2500 server.go\r\n<\/code><\/pre>\n<h3>\u81ea\u52a8\u751f\u6210\u7269\u54c1\u7684\u68c0\u67e5<\/h3>\n<h4>GraphQL \u7684\u6a21\u5f0f<\/h4>\n<pre class=\"post-pre\"><code><span class=\"c\"># GraphQL schema example<\/span>\r\n<span class=\"c\">#<\/span>\r\n<span class=\"c\"># https:\/\/gqlgen.com\/getting-started\/<\/span>\r\n\r\n<span class=\"k\">type<\/span> <span class=\"n\">Todo<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">id<\/span><span class=\"p\">:<\/span> <span class=\"nb\">ID<\/span><span class=\"p\">!<\/span>\r\n  <span class=\"n\">text<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span><span class=\"p\">!<\/span>\r\n  <span class=\"n\">done<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Boolean<\/span><span class=\"p\">!<\/span>\r\n  <span class=\"n\">user<\/span><span class=\"p\">:<\/span> <span class=\"n\">User<\/span><span class=\"p\">!<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">type<\/span> <span class=\"n\">User<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">id<\/span><span class=\"p\">:<\/span> <span class=\"nb\">ID<\/span><span class=\"p\">!<\/span>\r\n  <span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span><span class=\"p\">!<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">type<\/span> <span class=\"n\">Query<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">todos<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"n\">Todo<\/span><span class=\"p\">!]!<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">input<\/span> <span class=\"n\">NewTodo<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">text<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span><span class=\"p\">!<\/span>\r\n  <span class=\"n\">userId<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span><span class=\"p\">!<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">type<\/span> <span class=\"n\">Mutation<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"n\">createTodo<\/span><span class=\"p\">(<\/span><span class=\"n\">input<\/span><span class=\"p\">:<\/span> <span class=\"n\">NewTodo<\/span><span class=\"p\">!):<\/span> <span class=\"n\">Todo<\/span><span class=\"p\">!<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u5b9e\u9645\u4e0a\uff0c\u6211\u4eec\u9009\u62e9\u5c06\u4e3b\u9898\u8bbe\u4e3a\u201c\u7b80\u6613ToDo\u5e94\u7528\u7a0b\u5e8f\u201d\u662f\u56e0\u4e3a gqlgen \u9ed8\u8ba4\u4f1a\u751f\u6210\u4e0a\u8ff0\u6a21\u5f0f\u3002<br \/>\ngqlgen \u662f\u4e00\u4e2a\u4ee5\u6a21\u5f0f\u4e3a\u57fa\u7840\u7684\u5e93\uff0c\u56e0\u6b64\u6211\u4eec\u5c06\u6839\u636e\u6b64\u6a21\u5f0f\uff0c\u7ed3\u5408\u4ec5\u5728\u9996\u6b21\u81ea\u52a8\u751f\u6210\u7684\u6e90\u4ee3\u7801\u548c\u6bcf\u6b21\u8fd0\u884c gqlgen \u547d\u4ee4\u65f6\u81ea\u52a8\u751f\u6210\u7684\u6e90\u4ee3\u7801\uff0c\u6765\u5b9e\u73b0\u529f\u80fd\u3002<\/p>\n<h4>\u89e3\u51b3\u8005<\/h4>\n<p>\u4f7f\u7528GraphQL\u67b6\u6784\u5b9a\u4e49\u7684\u67e5\u8be2\uff08\u5728\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\u662f `todos: [Todo!]!`\uff0c\u5373\u83b7\u53d6ToDo\u5217\u8868\uff09\u548c\u53d8\u66f4\uff08\u5728\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\u662f `createTodo(input: NewTodo!): Todo!`\uff0c\u5373\u521b\u5efa\u65b0\u7684ToDo\uff09\u7684\u903b\u8f91\u5b9e\u73b0\u7684\u6e90\u4ee3\u7801\u3002<br \/>\n\u203b\u6b64\u6e90\u4ee3\u7801\u662f\u7531gqlgen\u547d\u4ee4\u81ea\u52a8\u751f\u6210\u7684\u6e90\u4ee3\u7801\uff08\u540e\u7eed\u4e0d\u4f1a\u518d\u6b21\u751f\u6210\uff0c\u9664\u975e\u5220\u9664\u8be5\u6587\u4ef6\u6216\u8005\u4e0d\u4fee\u6539gqlgen.yml\u914d\u7f6e\uff09\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">package<\/span> <span class=\"n\">backend<\/span>\r\n\r\n<span class=\"k\">import<\/span> <span class=\"p\">(<\/span>\r\n    <span class=\"s\">\"context\"<\/span>\r\n<span class=\"p\">)<\/span> <span class=\"c\">\/\/ THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.<\/span>\r\n\r\n<span class=\"k\">type<\/span> <span class=\"n\">Resolver<\/span> <span class=\"k\">struct<\/span><span class=\"p\">{}<\/span>\r\n\r\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">Resolver<\/span><span class=\"p\">)<\/span> <span class=\"n\">Mutation<\/span><span class=\"p\">()<\/span> <span class=\"n\">MutationResolver<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">mutationResolver<\/span><span class=\"p\">{<\/span><span class=\"n\">r<\/span><span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">Resolver<\/span><span class=\"p\">)<\/span> <span class=\"n\">Query<\/span><span class=\"p\">()<\/span> <span class=\"n\">QueryResolver<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">queryResolver<\/span><span class=\"p\">{<\/span><span class=\"n\">r<\/span><span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">type<\/span> <span class=\"n\">mutationResolver<\/span> <span class=\"k\">struct<\/span><span class=\"p\">{<\/span> <span class=\"o\">*<\/span><span class=\"n\">Resolver<\/span> <span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">mutationResolver<\/span><span class=\"p\">)<\/span> <span class=\"n\">CreateTodo<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span> <span class=\"n\">context<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">,<\/span> <span class=\"n\">input<\/span> <span class=\"n\">NewTodo<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">Todo<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nb\">panic<\/span><span class=\"p\">(<\/span><span class=\"s\">\"not implemented\"<\/span><span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">type<\/span> <span class=\"n\">queryResolver<\/span> <span class=\"k\">struct<\/span><span class=\"p\">{<\/span> <span class=\"o\">*<\/span><span class=\"n\">Resolver<\/span> <span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">queryResolver<\/span><span class=\"p\">)<\/span> <span class=\"n\">Todos<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span> <span class=\"n\">context<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">)<\/span> <span class=\"p\">([]<\/span><span class=\"o\">*<\/span><span class=\"n\">Todo<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nb\">panic<\/span><span class=\"p\">(<\/span><span class=\"s\">\"not implemented\"<\/span><span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u5f53\u524d\u7684 panic(&#8220;not implemented&#8221;) \u5c06\u88ab\u66ff\u6362\u4e3a\u7531\u524d\u7aef\u8c03\u7528\u65f6\u6267\u884c\u7684\u903b\u8f91\u3002<br \/>\n\u56e0\u6b64\uff0c\u8fdb\u884c\u4e86\u5982\u4e0b\u4fee\u6b63\uff1a<\/p>\n<pre class=\"post-pre\"><code>$ git diff\r\ndiff --git a\/backend\/resolver.go b\/backend\/resolver.go\r\nindex d015cbe..9bbe326 100644\r\n--- a\/backend\/resolver.go\r\n+++ b\/backend\/resolver.go\r\n@@ -16,11 +16,38 @@ func (r *Resolver) Query() QueryResolver {\r\n type mutationResolver struct{ *Resolver }\r\n\r\n func (r *mutationResolver) CreateTodo(ctx context.Context, input NewTodo) (*Todo, error) {\r\n-       panic(\"not implemented\")\r\n+       return &amp;Todo{\r\n+               ID:   \"todo001\",\r\n+               Text: \"\u90e8\u5c4b\u306e\u6383\u9664\",\r\n+               Done: false,\r\n+               User: &amp;User{\r\n+                       ID:   \"user001\",\r\n+                       Name: \"\u305f\u308d\u30fc\",\r\n+               },\r\n+       },nil\r\n }\r\n\r\n type queryResolver struct{ *Resolver }\r\n\r\n func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) {\r\n-       panic(\"not implemented\")\r\n+       return []*Todo{\r\n+               &amp;Todo{\r\n+                       ID:   \"todo001\",\r\n+                       Text: \"\u90e8\u5c4b\u306e\u6383\u9664\",\r\n+                       Done: false,\r\n+                       User: &amp;User{\r\n+                               ID:   \"user001\",\r\n+                               Name: \"\u305f\u308d\u30fc\",\r\n+                       },\r\n+               },\r\n+               &amp;Todo{\r\n+                       ID:   \"todo002\",\r\n+                       Text: \"\u8cb7\u3044\u7269\",\r\n+                       Done: true,\r\n+                       User: &amp;User{\r\n+                               ID:   \"user001\",\r\n+                               Name: \"\u305f\u308d\u30fc\",\r\n+                       },\r\n+               },\r\n+       },nil\r\n }\r\n<\/code><\/pre>\n<h4>Go\u670d\u52a1\u5668\u542f\u52a8\u903b\u8f91<\/h4>\n<p>gqlgen\u547d\u4ee4\u81ea\u52a8\u751f\u6210\u4e86main\u51fd\u6570\u548cWeb\u670d\u52a1\u5668\u542f\u52a8\u903b\u8f91\u7684\u76ee\u6807\u4ee3\u7801\u3002<br \/>\n\u5b83\u57288080\u7aef\u53e3\u4e0a\u542f\u52a8\uff0c\u540c\u65f6\u5728\u6839\u8def\u5f84\u663e\u793a\u4e86GraphQL\u7684Playground\u3002\uff08\u7b80\u76f4\u5b8c\u7f8e\u5230\u4e0d\u884c\uff09<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">package<\/span> <span class=\"n\">main<\/span>\r\n\r\n<span class=\"k\">import<\/span> <span class=\"p\">(<\/span>\r\n    <span class=\"s\">\"log\"<\/span>\r\n    <span class=\"s\">\"net\/http\"<\/span>\r\n    <span class=\"s\">\"os\"<\/span>\r\n\r\n    <span class=\"s\">\"github.com\/99designs\/gqlgen\/handler\"<\/span>\r\n    <span class=\"s\">\"github.com\/sky0621\/study-graphql\/backend\"<\/span>\r\n<span class=\"p\">)<\/span>\r\n\r\n<span class=\"k\">const<\/span> <span class=\"n\">defaultPort<\/span> <span class=\"o\">=<\/span> <span class=\"s\">\"8080\"<\/span>\r\n\r\n<span class=\"k\">func<\/span> <span class=\"n\">main<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"n\">port<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">Getenv<\/span><span class=\"p\">(<\/span><span class=\"s\">\"PORT\"<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">if<\/span> <span class=\"n\">port<\/span> <span class=\"o\">==<\/span> <span class=\"s\">\"\"<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"n\">port<\/span> <span class=\"o\">=<\/span> <span class=\"n\">defaultPort<\/span>\r\n    <span class=\"p\">}<\/span>\r\n\r\n    <span class=\"n\">http<\/span><span class=\"o\">.<\/span><span class=\"n\">Handle<\/span><span class=\"p\">(<\/span><span class=\"s\">\"\/\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">handler<\/span><span class=\"o\">.<\/span><span class=\"n\">Playground<\/span><span class=\"p\">(<\/span><span class=\"s\">\"GraphQL playground\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"\/query\"<\/span><span class=\"p\">))<\/span>\r\n    <span class=\"n\">http<\/span><span class=\"o\">.<\/span><span class=\"n\">Handle<\/span><span class=\"p\">(<\/span><span class=\"s\">\"\/query\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">handler<\/span><span class=\"o\">.<\/span><span class=\"n\">GraphQL<\/span><span class=\"p\">(<\/span><span class=\"n\">backend<\/span><span class=\"o\">.<\/span><span class=\"n\">NewExecutableSchema<\/span><span class=\"p\">(<\/span><span class=\"n\">backend<\/span><span class=\"o\">.<\/span><span class=\"n\">Config<\/span><span class=\"p\">{<\/span><span class=\"n\">Resolvers<\/span><span class=\"o\">:<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">backend<\/span><span class=\"o\">.<\/span><span class=\"n\">Resolver<\/span><span class=\"p\">{}})))<\/span>\r\n\r\n    <span class=\"n\">log<\/span><span class=\"o\">.<\/span><span class=\"n\">Printf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"connect to http:\/\/localhost:%s\/ for GraphQL playground\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">port<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">log<\/span><span class=\"o\">.<\/span><span class=\"n\">Fatal<\/span><span class=\"p\">(<\/span><span class=\"n\">http<\/span><span class=\"o\">.<\/span><span class=\"n\">ListenAndServe<\/span><span class=\"p\">(<\/span><span class=\"s\">\":\"<\/span><span class=\"o\">+<\/span><span class=\"n\">port<\/span><span class=\"p\">,<\/span> <span class=\"no\">nil<\/span><span class=\"p\">))<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h3>\u542f\u52a8GraphQL\u670d\u52a1\u5668<\/h3>\n<pre class=\"post-pre\"><code>$ pwd\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/backend\r\n$\r\n$ go run server\/server.go \r\n2019\/11\/16 12:33:49 connect to http:\/\/localhost:8080\/ for GraphQL playground\r\n<\/code><\/pre>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d8120913a08637a6ac5c6\/80-1.png\" alt=\"screenshot-localhost-8080-2019.11.16-12-38-57.png\" \/><\/div>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d8120913a08637a6ac5c6\/81-0.png\" alt=\"screenshot-localhost-8080-2019.11.16-12-43-04.png\" \/><\/div>\n<p>\u53ea\u662f\uff0c\u8fd9\u6b21\u5728resolver.go\u4e2d\u8fd4\u56de\u4e86\u4e00\u4e2a\u56fa\u5b9a\u503c\uff0c\u6240\u4ee5\u4e0d\u592a\u5728\u610f\uff0c\u4f46\u4ece\u8003\u8651\u5230\u8981\u6301\u4e45\u5316\u5230RDB\uff0c\u6211\u89c9\u5f97\u540e\u7aef\u7684\u5b9e\u73b0\u53ef\u80fd\u4f1a\u53d8\u5f97\u56f0\u96be\u4e00\u4e9b\u3002<br \/>\n\u5b9e\u9645\u4e0a\uff0c\u6211\u5728\u5de5\u4f5c\u4e2d\u540c\u65f6\u7f16\u5199\u4e86GraphQL\u7684\u524d\u7aef\u548c\u540e\u7aef\uff0c\u4f46\u4ece\u4fe1\u606f\u4ea4\u4e92\u7684\u89d2\u5ea6\u6765\u8bf4\uff0c\u540e\u7aef\u8981\u56f0\u96be\u5f97\u591a\u3002<br \/>\n\u55ef\uff0c\u5173\u4e8e\u8fd9\u4e00\u70b9\uff0c\u6211\u8ba1\u5212\u5728\u4e0b\u4e00\u7bc7\u6587\u7ae0\u4e2d\u7f16\u5199\u4e0eRDB\u8fde\u63a5\u7684\u4ee3\u7801\uff0c\u5230\u90a3\u65f6\u5019\u518d\u8bf4\u5427\u3002<\/p>\n<p>\u597d\u7684\uff0c\u73b0\u5728\u6211\u4eec\u5ffd\u7565\u5bf9\u4e8eTodo\u65b0\u6ce8\u518c\u7684\u786e\u8ba4\uff08\u56e0\u4e3a\u548c\u67e5\u8be2\u4e00\u6837\uff09\uff0c\u6211\u4eec\u53ea\u5173\u6ce8\u540e\u7aef\u90e8\u5206\u3002<br \/>\n\u6700\u540e\uff0c\u6211\u4eec\u9700\u8981\u8c03\u6574\u524d\u7aef\uff0c\u4ee5\u8fde\u63a5\u540e\u7aef\u7684GraphQL\u670d\u52a1\u5668\u3002<\/p>\n<h2>\u91cd\u65b0\u56de\u5230\u524d\u7aef<\/h2>\n<h3>\u4f7f\u7528Apollo\u5efa\u7acbGraphQL\u670d\u52a1\u5668\u8fde\u63a5\u3002<\/h3>\n<h4>\u51c6\u5907\u67e5\u8be2\u6587\u4ef6<\/h4>\n<p>\u4e3a\u4e86\u5411GraphQL\u670d\u52a1\u5668\u53d1\u9001\u8bf7\u6c42\uff0c\u9700\u8981\u5199\u4e00\u4e2a\u67e5\u8be2\uff0c\u5728\u540e\u7aef\u7684playground\u4e0a\u8bd5\u8fc7\u4e86\u3002<br \/>\n\u6dfb\u52a0\u4e00\u4e2a\u540d\u4e3a&#8221;apollo&#8221;\u7684\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u4e00\u4e2a\u6587\u4ef6\u5939\u7ed3\u6784\uff0c\u5b58\u653e\u7528\u4e8e&#8221;Todo\u5217\u8868\u83b7\u53d6&#8221;\u7684\u67e5\u8be2\u6587\u4ef6\u3002<\/p>\n<pre class=\"post-pre\"><code>$ pwd\r\n\/home\/sky0621\/src\/github.com\/sky0621\/study-graphql\/frontend\r\n$\r\n$ tree -L 1\r\n.\r\n\u251c\u2500\u2500 apollo\r\n\u251c\u2500\u2500 assets\r\n\u251c\u2500\u2500 components\r\n\u3000\u3000\u3000\u30fb\u30fb\u30fb\r\n$\r\n$ tree -L 2 apollo\/\r\napollo\/\r\n\u2514\u2500\u2500 queries\r\n    \u2514\u2500\u2500 todos.gql\r\n$\r\n$ cat apollo\/queries\/todos.gql \r\nquery todos {\r\n  todos {\r\n    id\r\n    text\r\n    done\r\n    user {\r\n      id\r\n      name\r\n    }\r\n  }\r\n}\r\n<\/code><\/pre>\n<h4>\u524d\u7aef\u9996\u9875<\/h4>\n<p>\u4fee\u6539\u4e3a\u6253\u5f00\u65f6\u663e\u793aTodo\u5217\u8868\u3002<\/p>\n<p>\u524d\u7aef\u7684\u76ee\u5f55\u7ed3\u6784\u5982\u4e0b\uff1a<\/p>\n<pre class=\"post-pre\"><code>$ tree -L 1\r\n.\r\n\u251c\u2500\u2500 apollo\r\n\u251c\u2500\u2500 assets\r\n\u251c\u2500\u2500 components\r\n\u251c\u2500\u2500 layouts\r\n\u251c\u2500\u2500 middleware\r\n\u251c\u2500\u2500 node_modules\r\n\u251c\u2500\u2500 nuxt.config.js\r\n\u251c\u2500\u2500 package.json\r\n\u251c\u2500\u2500 pages\r\n\u251c\u2500\u2500 plugins\r\n\u251c\u2500\u2500 README.md\r\n\u251c\u2500\u2500 static\r\n\u251c\u2500\u2500 store\r\n\u2514\u2500\u2500 yarn.lock\r\n<\/code><\/pre>\n<p>1. \u6211\u4eec\u9700\u8981\u4fee\u6539 pages\/index.vue \u8fd9\u4e2a\u6587\u4ef6\u3002<br \/>\n2. \u540c\u65f6\uff0c\u6211\u4eec\u8fd8\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u4f5c\u4e3a components\/TodoCard.vue \u7ec4\u4ef6\u4ece pages \u4e2d\u8c03\u7528\u7684\u7ec4\u4ef6\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nt\">&lt;<\/span><span class=\"k\">template<\/span><span class=\"nt\">&gt;<\/span>\r\n  <span class=\"nt\">&lt;div&gt;<\/span>\r\n    <span class=\"nt\">&lt;TodoCard<\/span> <span class=\"nt\">\/&gt;<\/span>\r\n  <span class=\"nt\">&lt;\/div&gt;<\/span>\r\n<span class=\"nt\">&lt;\/<\/span><span class=\"k\">template<\/span><span class=\"nt\">&gt;<\/span>\r\n\r\n<span class=\"nt\">&lt;<\/span><span class=\"k\">script<\/span><span class=\"nt\">&gt;<\/span>\r\n<span class=\"k\">import<\/span> <span class=\"nx\">TodoCard<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">~\/components\/TodoCard.vue<\/span><span class=\"dl\">'<\/span>\r\n\r\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"na\">components<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">TodoCard<\/span> <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<span class=\"nt\">&lt;\/<\/span><span class=\"k\">script<\/span><span class=\"nt\">&gt;<\/span>\r\n<\/code><\/pre>\n<p>\u4ee5\u4e0b\u7684\u9875\u9762\u53ea\u9700\u8981\u8c03\u7528\u7ec4\u4ef6\u5c31\u53ef\u4ee5\u4e86\u3002<\/p>\n<p>\u6211\u4eec\u4f7f\u7528\u4ee5\u4e0b\u7684\u7ec4\u4ef6\u901a\u8fc7Apollo\u83b7\u53d6\u4e86Todo\u5217\u8868\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nt\">&lt;<\/span><span class=\"k\">template<\/span><span class=\"nt\">&gt;<\/span>\r\n  <span class=\"nt\">&lt;div&gt;<\/span>\r\n    <span class=\"nt\">&lt;v-row&gt;<\/span>\r\n      <span class=\"nt\">&lt;v-col<\/span> <span class=\"na\">cols=<\/span><span class=\"s\">\"12\"<\/span> <span class=\"na\">sm=<\/span><span class=\"s\">\"6\"<\/span> <span class=\"na\">offset-sm=<\/span><span class=\"s\">\"3\"<\/span><span class=\"nt\">&gt;<\/span>\r\n        <span class=\"nt\">&lt;v-card&gt;<\/span>\r\n          <span class=\"nt\">&lt;v-list<\/span> <span class=\"na\">two-line<\/span> <span class=\"na\">subheader<\/span><span class=\"nt\">&gt;<\/span>\r\n            <span class=\"nt\">&lt;v-list-item<\/span> <span class=\"na\">v-for=<\/span><span class=\"s\">\"todo in todos\"<\/span> <span class=\"na\">:key=<\/span><span class=\"s\">\"todo.id\"<\/span> <span class=\"na\">link<\/span><span class=\"nt\">&gt;<\/span>\r\n              <span class=\"nt\">&lt;v-list-item-avatar&gt;<\/span>\r\n                <span class=\"nt\">&lt;v-icon&gt;<\/span>mdi-gift-outline<span class=\"nt\">&lt;\/v-icon&gt;<\/span>\r\n              <span class=\"nt\">&lt;\/v-list-item-avatar&gt;<\/span>\r\n              <span class=\"nt\">&lt;v-list-item-content&gt;<\/span>\r\n                <span class=\"nt\">&lt;v-list-item-title&gt;<\/span><span class=\"si\">{{<\/span> <span class=\"nx\">todo<\/span><span class=\"p\">.<\/span><span class=\"nx\">text<\/span> <span class=\"si\">}}<\/span><span class=\"nt\">&lt;\/v-list-item-title&gt;<\/span>\r\n                <span class=\"nt\">&lt;v-list-item-subtitle&gt;<\/span><span class=\"si\">{{<\/span> <span class=\"nx\">todo<\/span><span class=\"p\">.<\/span><span class=\"nx\">done<\/span> <span class=\"si\">}}<\/span><span class=\"nt\">&lt;\/v-list-item-subtitle&gt;<\/span>\r\n              <span class=\"nt\">&lt;\/v-list-item-content&gt;<\/span>\r\n              <span class=\"nt\">&lt;v-list-item-content&gt;<\/span>\r\n                <span class=\"nt\">&lt;v-list-item-title&gt;<\/span>\r\n                  <span class=\"si\">{{<\/span> <span class=\"nx\">todo<\/span><span class=\"p\">.<\/span><span class=\"nx\">user<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"si\">}}<\/span>\r\n                <span class=\"nt\">&lt;\/v-list-item-title&gt;<\/span>\r\n              <span class=\"nt\">&lt;\/v-list-item-content&gt;<\/span>\r\n            <span class=\"nt\">&lt;\/v-list-item&gt;<\/span>\r\n          <span class=\"nt\">&lt;\/v-list&gt;<\/span>\r\n        <span class=\"nt\">&lt;\/v-card&gt;<\/span>\r\n      <span class=\"nt\">&lt;\/v-col&gt;<\/span>\r\n    <span class=\"nt\">&lt;\/v-row&gt;<\/span>\r\n  <span class=\"nt\">&lt;\/div&gt;<\/span>\r\n<span class=\"nt\">&lt;\/<\/span><span class=\"k\">template<\/span><span class=\"nt\">&gt;<\/span>\r\n\r\n<span class=\"nt\">&lt;<\/span><span class=\"k\">script<\/span><span class=\"nt\">&gt;<\/span>\r\n<span class=\"k\">import<\/span> <span class=\"nx\">todos<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">~\/apollo\/queries\/todos.gql<\/span><span class=\"dl\">'<\/span>\r\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">data<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"na\">todos<\/span><span class=\"p\">:<\/span> <span class=\"p\">[]<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">},<\/span>\r\n\r\n  <span class=\"na\">apollo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"na\">todos<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"na\">prefetch<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"na\">query<\/span><span class=\"p\">:<\/span> <span class=\"nx\">todos<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<span class=\"nt\">&lt;\/<\/span><span class=\"k\">script<\/span><span class=\"nt\">&gt;<\/span>\r\n<\/code><\/pre>\n<p>\u5728\u4e2d\u56fd\u4e13\u4e1a\u4eba\u58eb\u4e2d\uff0c\u53ef\u4ee5\u4ece\u4e8b\u5148\u51c6\u5907\u597d\u7684\u6269\u5c55\u540d\u4e3agql\u7684\u6587\u4ef6\u4e2d\u5bfc\u5165\u67e5\u8be2\u6765\u4e0eGraphQL\u670d\u52a1\u5668\u8fdb\u884c\u8054\u7cfb\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">import<\/span> <span class=\"nx\">todos<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">~\/apollo\/queries\/todos.gql<\/span><span class=\"dl\">'<\/span>\r\n<\/code><\/pre>\n<p>\u5728 nuxt-config.js \u6587\u4ef6\u4e2d\uff0c\u5c06 @nuxtjs\/apollo \u6a21\u5757\u52a0\u8f7d\u4e3a\u914d\u7f6e\uff0c\u5e76\u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f\u5728 Vue \u6587\u4ef6\u4e2d\u5b9a\u4e49\u6765\u5c06 GraphQL \u670d\u52a1\u5668\u7684\u67e5\u8be2\u7ed3\u679c\u5b58\u50a8\u5728\u540d\u4e3a todos \u7684\u6570\u636e\u4e2d\u3002<\/p>\n<pre class=\"post-pre\"><code>  <span class=\"nx\">apollo<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nl\">todos<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"na\">prefetch<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"na\">query<\/span><span class=\"p\">:<\/span> <span class=\"nx\">todos<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u51b3\u5b9a\u4f7f\u7528Vuetify\u7684v-card\u7ec4\u4ef6\u6765\u8fdb\u884c\u4e00\u89c8\u663e\u793a\uff08\u867d\u7136v-data-table\u4e5f\u53ef\u4ee5\uff09\u3002<br \/>\n\u5728\u4e0a\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u901a\u8fc7v-for\u5faa\u73af\u904d\u5386todos\u83b7\u53d6TODO\u5217\u8868\u5e76\u5c06\u6bcf\u4e2a\u9879\u76ee\u663e\u793a\u51fa\u6765\uff0c\u6ca1\u6709\u8fdb\u4e00\u6b65\u7684\u8bf4\u660e\u3002<\/p>\n<p>\u554a\uff0c\u5bf9\u4e86\u3002\u5fd8\u8bb0\u4e86\u3002GraphQL\u670d\u52a1\u5668\u7684\u8def\u5f84\u662f&#8221;\/query&#8221;\uff0c\u6240\u4ee5\u9700\u8981\u4fee\u6539nuxt-config.js\u5982\u4e0b\u3002<\/p>\n<pre class=\"post-pre\"><code>diff --git a\/frontend\/nuxt.config.js b\/frontend\/nuxt.config.js\r\nindex afc0db4..8454218 100644\r\n--- a\/frontend\/nuxt.config.js\r\n+++ b\/frontend\/nuxt.config.js\r\n@@ -69,7 +69,7 @@ export default {\r\n     clientConfigs: {\r\n       default: {\r\n         \/\/ Go\u30b5\u30fc\u30d0\u3092 8080 \u30dd\u30fc\u30c8\u3067\u8d77\u52d5\u3059\u308b\u4e88\u5b9a\u306e\u305f\u3081\r\n-        httpEndpoint: 'http:\/\/localhost:8080\/'\r\n+        httpEndpoint: 'http:\/\/localhost:8080\/query'\r\n       }\r\n     },\r\n<\/code><\/pre>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d8120913a08637a6ac5c6\/104-0.png\" alt=\"screenshot-localhost-35567-2019.11.16-15-04-51.png\" \/><\/div>\n<h1>\u603b\u7ed3<\/h1>\n<p>\u7531\u4e8e\u65f6\u95f4\u7684\u5173\u7cfb\uff0c\u6211\u7701\u7565\u4e86Todo\u7684\u65b0\u6ce8\u518c\uff0c\u4f46\u662f\u901a\u8fc7\u4f7f\u7528GraphQL\u8fde\u63a5\u524d\u7aef\u548c\u540e\u7aef\u7684\u5b9e\u73b0\u6848\u4f8b\uff0c\u6211\u80fd\u591f\u5c55\u793a\u51fa\u6765\u3002\u4e0d\u8fc7\uff0c\u5728\u8fd9\u4e2a\u4efb\u52a1\u548c\u7f16\u7801\u6c34\u5e73\u4e0b\uff0c\u53ef\u80fd\u8fd8\u6ca1\u6709\u51fa\u73b0\u4f7f\u7528GraphQL\u7684\u52a8\u529b&#8230;<br \/>\n\u4ece\u524d\u7aef\u7684\u89d2\u5ea6\u6765\u770b\uff0c\u5f53\u9700\u8981\u5c06\u591a\u5c42\u6b21\u7ed3\u6784\u7684\u4fe1\u606f\u4f5c\u4e3a\u5217\u8868\u663e\u793a\u5728\u4e00\u4e2a\u9875\u9762\u4e0a\u65f6\uff0c\u4ee5\u524d\u9700\u8981\u4e3a\u6bcf\u4e2a\u5c42\u6b21\u8c03\u7528API\uff0c\u73b0\u5728\u901a\u8fc7GraphQL\u5e93\uff0c\u80fd\u591f\u4e00\u6b21\u83b7\u53d6\u6240\u9700\u7684\u6240\u6709\u4fe1\u606f\uff0c\u5e76\u5c06\u5176\u7ed3\u6784\u5316\uff0c\u8fd9\u5bf9\u524d\u7aef\u6765\u8bf4\u975e\u5e38\u4fbf\u5229\u3002<br \/>\n\u4f46\u662f\uff0c\u76f8\u53cd\u5730\uff0c\u540e\u7aef\u5374\u6709\u5f88\u591a\u9700\u8981\u8003\u8651\u7684\u95ee\u9898\uff0c\u5e76\u4e14\u5c3d\u7ba1GraphQL\u672c\u8eab\u4f5c\u4e3a\u89c4\u8303\u5b58\u5728\uff0c\u4f46\u5b83\u5e76\u6ca1\u6709\u5b9a\u4e49\u8bf8\u5982&#8221;\u8ba4\u8bc1&#8221;\u3001&#8221;\u5206\u9875&#8221;\u7b49\u5177\u4f53\u7684\u5b9e\u73b0\u65b9\u5f0f\uff0c\u6240\u4ee5\u6839\u636e\u6240\u4f7f\u7528\u7684\u5e93\uff0c\u53ef\u80fd\u9700\u8981\u81ea\u5df1\u91cd\u65b0\u53d1\u660e\u4e00\u4e9b\u8f6e\u5b50\u3002<br \/>\n\u4f3c\u4e4e\u8fd8\u6709\u50cfPrisma\u8fd9\u6837\u7684\u6846\u67b6(?)\u5b58\u5728\uff0c\u4f46\u5728\u6ca1\u6709\u66f4\u591a\u5e7f\u6cdb\u7684\u5b9e\u8df5\u548c\u77e5\u8bc6\u79ef\u7d2f\u4e4b\u524d\uff0c\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u4f7f\u7528\u8fd8\u662f\u6709\u4e9b\u53ef\u6015\u7684&#8230;<\/p>\n<p>\u672c\u6b21\u7684\u6240\u6709\u6e90\u4ee3\u7801\u5982\u4e0b\uff1a<br \/>\nhttps:\/\/github.com\/sky0621\/study-graphql\/tree\/v0.1.0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8bf7\u7528\u4e2d\u6587\u8fdb\u884c\u4ee5\u4e0b\u7684\u91ca\u4e49\uff0c\u53ea\u9700\u8981\u4e00\u4e2a\u9009\u9879\uff1a \u304a\u984c \u2192 \u8bdd\u9898 \u6211\u5011\u5c07\u901a\u904e\u4e00\u500b\u7c21\u55ae\u7684ToDo\u61c9\u7528\u7a0b\u5f0f\uff08\u5118\u7ba1\u5728\u9019\u7bc7\u6587\u7ae0 [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-47812","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u4f7f\u7528&quot;Nuxt.js\/Apollo&quot;\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a&quot;gqlgen&quot;\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1 - Blog - Silicon Cloud<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528nuxt-js-apollo\u4f5c\u4e3a\u524d\u7aef\uff0cgo\u8bed\u8a00\u52a0\u4e0agqlgen\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u4f7f\u7528&quot;Nuxt.js\/Apollo&quot;\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a&quot;gqlgen&quot;\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1\" \/>\n<meta property=\"og:description\" content=\"\u8bf7\u7528\u4e2d\u6587\u8fdb\u884c\u4ee5\u4e0b\u7684\u91ca\u4e49\uff0c\u53ea\u9700\u8981\u4e00\u4e2a\u9009\u9879\uff1a \u304a\u984c \u2192 \u8bdd\u9898 \u6211\u5011\u5c07\u901a\u904e\u4e00\u500b\u7c21\u55ae\u7684ToDo\u61c9\u7528\u7a0b\u5f0f\uff08\u5118\u7ba1\u5728\u9019\u7bc7\u6587\u7ae0 [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528nuxt-js-apollo\u4f5c\u4e3a\u524d\u7aef\uff0cgo\u8bed\u8a00\u52a0\u4e0agqlgen\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2023-01-15T02:24:13+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-29T21:24:59+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d8120913a08637a6ac5c6\/57-0.png\" \/>\n<meta name=\"author\" content=\"\u79d1, \u9896\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u79d1, \u9896\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/\",\"name\":\"\u4f7f\u7528\\\"Nuxt.js\/Apollo\\\"\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a\\\"gqlgen\\\"\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1 - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2023-01-15T02:24:13+00:00\",\"dateModified\":\"2024-04-29T21:24:59+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u4f7f\u7528&#8221;Nuxt.js\/Apollo&#8221;\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a&#8221;gqlgen&#8221;\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e\",\"name\":\"\u79d1, \u9896\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g\",\"caption\":\"\u79d1, \u9896\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/keying\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u4f7f\u7528\"Nuxt.js\/Apollo\"\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a\"gqlgen\"\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1 - Blog - Silicon Cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528nuxt-js-apollo\u4f5c\u4e3a\u524d\u7aef\uff0cgo\u8bed\u8a00\u52a0\u4e0agqlgen\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\/","og_locale":"zh_CN","og_type":"article","og_title":"\u4f7f\u7528\"Nuxt.js\/Apollo\"\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a\"gqlgen\"\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1","og_description":"\u8bf7\u7528\u4e2d\u6587\u8fdb\u884c\u4ee5\u4e0b\u7684\u91ca\u4e49\uff0c\u53ea\u9700\u8981\u4e00\u4e2a\u9009\u9879\uff1a \u304a\u984c \u2192 \u8bdd\u9898 \u6211\u5011\u5c07\u901a\u904e\u4e00\u500b\u7c21\u55ae\u7684ToDo\u61c9\u7528\u7a0b\u5f0f\uff08\u5118\u7ba1\u5728\u9019\u7bc7\u6587\u7ae0 [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528nuxt-js-apollo\u4f5c\u4e3a\u524d\u7aef\uff0cgo\u8bed\u8a00\u52a0\u4e0agqlgen\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2023-01-15T02:24:13+00:00","article_modified_time":"2024-04-29T21:24:59+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d8120913a08637a6ac5c6\/57-0.png"}],"author":"\u79d1, \u9896","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u79d1, \u9896","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"8 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/","name":"\u4f7f\u7528\"Nuxt.js\/Apollo\"\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a\"gqlgen\"\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1 - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2023-01-15T02:24:13+00:00","dateModified":"2024-04-29T21:24:59+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u4f7f\u7528&#8221;Nuxt.js\/Apollo&#8221;\u4f5c\u4e3a\u524d\u7aef\uff0cGo\u8bed\u8a00\u52a0\u4e0a&#8221;gqlgen&#8221;\u4f5c\u4e3a\u540e\u7aef\uff0c\u6765\u521b\u5efaGraphQL\u670d\u52a1"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/8ca01ba7f7362ad4edb7da206a12f29e","name":"\u79d1, \u9896","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8a6fb3cc7ba2f69d2189ba532aec4633ea7ed75ac0af162ec367cb3abc0fb2af?s=96&d=mm&r=g","caption":"\u79d1, \u9896"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/keying\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8nuxt-js-apollo%e4%bd%9c%e4%b8%ba%e5%89%8d%e7%ab%af%ef%bc%8cgo%e8%af%ad%e8%a8%80%e5%8a%a0%e4%b8%8agqlgen%e4%bd%9c%e4%b8%ba%e5%90%8e%e7%ab%af%ef%bc%8c%e6%9d%a5%e5%88%9b\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47812","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=47812"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47812\/revisions"}],"predecessor-version":[{"id":89955,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47812\/revisions\/89955"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=47812"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=47812"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=47812"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}