雖然 Vue 允許我們在 ECMAScript 內以 String 定義 GraphQL Query,但實務上 Query 會相當複雜,比較好的方式是拆成獨立的 *.graphql
方便維護。
Version
macOS Catalina 10.15.2
WebStorm 2019.3.1
Node 12.14.0
Vue CLI 4.1.1
Vue 2.6.10
Vue Apollo 3.0.0-beta.11
Vue Apollo
/src/App.vue
<template>
<div>
<ul>
<li v-for="(item, index) in books" :key="index">
{{ item.title }}:{{ item.price }}
</li>
</ul>
</div>
</template>
<script>
import gql from 'graphql-tag';
let query = gql(`
query {
books {
title
price
}
}
`)
export default {
name: 'app',
apollo: {
books: {
query
}
}
}
</script>
12 行
import gql from 'graphql-tag';
let query = gql(`
query {
books {
title
price
}
}
`)
傳統寫法需先 import gql()
,然後使用 gql()
將 string 轉成 GraphQL AST。
這種寫法有幾個缺點:
- 實務上 query 會很龐大,僅使用單一 string 難以維護
- GraphQL 畢竟是獨立語言,藏在 ECMAScript 內稍嫌不妥
- 須在 runtime 將 string 轉成 GraphQL AST,稍微影響速度
比較好的方式是藉由 graphql-tag
Webpack loader,將 GraphQL query 獨立成 *.graphql
,在 Webpack bundle 階段將 string 轉成 GraphQL AST。
Webpack Loader
/src/App.vue
<template>
<div>
<ul>
<li v-for="(item, index) in books" :key="index">
{{ item.title }}:{{ item.price }}
</li>
</ul>
</div>
</template>
<script>
import query from './graphql/books.graphql'
export default {
name: 'app',
apollo: {
books: {
query
}
}
}
</script>
12 行
import query from './graphql/books.graphql'
將 books
query 寫在獨立的 books.graphql
內 import 進來,可自行取其名稱。
14 行
export default {
name: 'app',
apollo: {
books: {
query
}
}
}
定義 books
smart query,可直接使用 import 進來的 query
,不必再透過 gql()
將 string 轉成 GraphQL AST。
GraphQL Query
/src/graphql/books.graphql
query {
books {
title
price
}
}
將 books
query 獨立成 books.graphql
,除了方便維護外,還可直接在 WebStorm 內測試結果。
Q:為什麼 Vue 不必使用
gql()
將 string 轉成 GraphQL AST 就能執行呢 ?
module.exports = {
chainWebpack: config => {
config.module
.rule('graphql')
.test(/\.graphql$/)
.use('graphql-tag/loader')
.loader('graphql-tag/loader')
.end()
}
}
其實 Vue Apollo 有另外設定 graphql-tag
Webpack loader,在 bundle 階段將 string 轉成 GraphQL AST,因此我們 import
後即可使用。
Start Development Server
$ yarn serve
使用 yarn serve
啟動 Webpack dev server,graphql-tag
Webpack loader 會將 import string 轉成 GraphQL AST。
Build Docker Image
$ yarn docker:build
$ yarn docker:up
使用 yarn docker:build
命令 Babel 轉譯與 Webpack 打包,最後包成 Docker image。
Browser
可成功執行 Vue。
Conclusion
- 使用 Webpack Loader 最大優點是將 GraphQL query 獨立成
*.graphql
,適合大型專案使用,也能避免 runtime 使用gql
轉譯成 GraphQL AST 造成效能耗損 - Vue Apollo 已經將 Webpack loader 整好,可直接使用
- 實務上建議一個 GraphQL query 使用一個檔案即可
Sample Code
完整範例可在我的 GitHub 上找到
Reference
Apollo Docs, Loading queries with Webpack
Vue CLI, Adding a New Loader
Apollographql, graphql-tag