透過 100 多個技巧的集合來學習 Nuxt!

apollo
@nuxtjs/apollo

在您的 Nuxt 應用程式中使用 vue-apollo 整合 GraphQL。

NuxtJS 內的 Apollo

npm version license

警告

此版本需要支援 serverPrefetch 的 Vue 2.6+。例如

npm install --save vue@2.6.6 vue-template-compiler@2.6.6 vue-server-renderer@2.6.6

有時您可能需要移除/重建 package-lock.json/yarn.lock 才能使其運作。

設定

1- 安裝 apollo 模組

npm install --save @nuxtjs/apollo

yarn add @nuxtjs/apollo

2- 載入 @nuxtjs/apollo 模組

// nuxt.config.js

export default {
  modules: [
    '@nuxtjs/apollo',
  ],

  apollo: {
    clientConfigs: {
      default: {
        httpEndpoint: 'https://127.0.0.1:4000',
      }
    }
  }
}

3- 載入 *.gql*.graphql 檔案(選用)

安裝 graphql-tag

npm install --save graphql-tag

yarn add graphql-tag

⚠️ Typescript 使用者

在您的來源資料夾中新增一個 gql.d.ts 檔案,內容如下

declare module '*.gql' {
  import { DocumentNode } from 'graphql'

  const content: DocumentNode
  export default content
}

declare module '*.graphql' {
  import { DocumentNode } from 'graphql'

  const content: DocumentNode
  export default content
}

用法

您已在專案中成功啟用 vue-apollo

請查看 官方範例vue-apollo 官方文件,了解如何在您的應用程式內使用 vue-apollo

進階設定

{
  // Add apollo module
  modules: ['@nuxtjs/apollo'],

  apollo: {
    // Sets up the apollo client endpoints
    clientConfigs: {
      // recommended: use a file to declare the client configuration (see below for example)
      default: '~/plugins/my-alternative-apollo-config.js',

      // you can setup multiple clients with arbitrary names
      alternativeClient: {
        // required
        httpEndpoint: 'https://127.0.0.1:4000',

        // override HTTP endpoint in browser only
        browserHttpEndpoint: '/graphql',

        // See https://www.apollographql.com/docs/link/links/http.html#options
        httpLinkOptions: {
          credentials: 'same-origin'
        },

        // You can use `wss` for secure connection (recommended in production)
        // Use `null` to disable subscriptions
        wsEndpoint: 'ws://127.0.0.1:4000',

        // LocalStorage token
        tokenName: 'apollo-token',

        // Enable Automatic Query persisting with Apollo Engine
        persisting: false,

        // Use websockets for everything (no HTTP)
        // You need to pass a `wsEndpoint` for this to work
        websocketsOnly: false
      },
    },
    
    /**
     * default 'apollo' definition
     */
    defaultOptions: {
      // See 'apollo' definition
      // For example: default query options
      $query: {
        loadingKey: 'loading',
        fetchPolicy: 'cache-and-network',
      },
    },
    
    // setup a global query loader observer (see below for example)
    watchLoading: '~/plugins/apollo-watch-loading-handler.js',
    
    // setup a global error handler (see below for example)
    errorHandler: '~/plugins/apollo-error-handler.js',

    // Sets the authentication type for any authorized request.
    authenticationType: 'Bearer', 

    // Token name for the cookie which will be set in case of authentication
    tokenName: 'apollo-token',

    // [deprecated] Enable the graphql-tag/loader to parse *.gql/*.graphql files
    includeNodeModules: true,

    // Cookie parameters used to store authentication token
    cookieAttributes: {
      /**
        * Define when the cookie will be removed. Value can be a Number
        * which will be interpreted as days from time of creation or a
        * Date instance. If omitted, the cookie becomes a session cookie.
        */
      expires: 7,

      /**
        * Define the path where the cookie is available. Defaults to '/'
        */
      path: '/',

      /**
        * Define the domain where the cookie is available. Defaults to
        * the domain of the page where the cookie was created.
        */
      domain: 'example.com',

      /**
        * A Boolean indicating if the cookie transmission requires a
        * secure protocol (https). Defaults to false.
        */
      secure: false,
    },
  }
}

使用檔案設定的 Apollo clientOptions

⚠️ 如果您需要在 apollo 設定中宣告函式(例如 getAuthinMemoryCacheOptions.fragmentMatcher),您必須使用外部檔案定義您的 clientOptions

// ~/plugins/my-alternative-apollo-config.js

export default (context) => {
  return {
    httpEndpoint: 'https://127.0.0.1:4000/graphql-alt',

    /*
     * For permanent authentication provide `getAuth` function.
     * The string returned will be used in all requests as authorization header
     */
    getAuth: () => 'Bearer my-static-token',
  }
}

watchLoading 範例

// ~/plugins/apollo-watch-loading-handler.js

export default (isLoading, countModifier, nuxtContext) => {
  loading += countModifier
  console.log('Global loading', loading, countModifier)
}

errorHandler 範例

// ~/plugins/apollo-error-handler.js

export default ({ graphQLErrors, networkError, operation, forward }, nuxtContext) => {
  console.log('Global error handler')
  console.log(graphQLErrors, networkError, operation, forward)
}

選項

您可以(在簡單的設定中)只新增一個如上所述的物件。如果您需要覆寫快取或預設的 getAuth() 函式,則使用指向您的設定檔的路徑,該檔案會傳回用戶端設定選項。

clientConfigs Option:必要

設定 apollo 用戶端端點。您可以在 此處 找到每個端點的所有可用選項

查看 官方 vue-apollo-cli,其中介紹了可能的使用案例。

clientConfigs.default Object:必要

clientConfigs. Object|Path:選用

tokenName String:選用,預設值:'apollo-token'

用於 Cookie 的權杖名稱,在驗證的情況下將會設定。您也可以在每個 clientConfigs 中提供選項 tokenName 以覆寫預設值。當每次提出請求時,此 Cookie 中的任何值都將在 "Authorization" HTTP 標頭中傳送,如下面的 authenticationType 所指定。

authenticationType String:選用,預設值:'Bearer'

為任何授權請求設定驗證類型。如果您的 GraphQL API 要求的驗證類型不是預設的 Bearer,請修改此設定。然後,所有請求都將以適當的 HTTP 標頭格式傳送:"Authorization "(例如 Authorization: Bearer abc123)。

如果您的後端要求 "Authorization" 格式的 Authorization 標頭",沒有任何前綴,則您應該將此值設定為空字串。

includeNodeModules Boolean:選用,預設值:false

如果您在 node_module 資料夾內使用 *.gql 檔案,您可以啟用 graphql-tag/loader 來為您解析檔案。

驗證

您可以使用以下驗證方法

 // set your graphql-token
 this.$apolloHelpers.onLogin(token /* if not default you can pass in client as second argument, you can set custom cookies attributes object as the third argument, and you can skip reset store as the fourth argument */)
 // unset your graphql-token
 this.$apolloHelpers.onLogout(/* if not default you can pass in client as first argument, and you can skip reset store as the second argument */)
 // get your current token (we persist token in a cookie)
 this.$apolloHelpers.getToken(/* you can provide named tokenName if not 'apollo-token' */)

查看 完整範例

使用者登入

// ~/components/my-component.js

export default {
  methods: {
    async onSubmit () {
      const credentials = this.credentials
      try {
          const res = await this.$apollo.mutate({
              mutation: authenticateUserGql,
              variables: credentials
          }).then(({data}) => data && data.authenticateUser)
          await this.$apolloHelpers.onLogin(res.token)
      } catch (e) {
          console.error(e)
      }
    },
  }
}

使用者登出

// ~/components/my-component.js

export default {
  methods: {
    async onLogout () {
      await this.$apolloHelpers.onLogout()
    },
  }
}

getToken

// ~/middleware/isAuth.js

export default ({app, error}) => {
  const hasToken = !!app.$apolloHelpers.getToken()
  if (!hasToken) {
    error({
      errorCode:503, 
      message:'You are not allowed to see this'
    })
  }
}

存取 apolloProvider 預設用戶端的範例

Vuex actions
// ~/store/my-store.js

export default {
  actions: {
    foo (store, payload) {
      let client = this.app.apolloProvider.defaultClient
    }
  }
}
頁面元件的 asyncData/fetch 方法
// ~/components/my-component.js

export default {
  asyncData (context) {
    let client = context.app.apolloProvider.defaultClient
  }
}
nuxtServerInit
export default {
  nuxtServerInit (store, context) {
    let client = context.app.apolloProvider.defaultClient
  }
}
存取用戶端或呼叫元件內任何方法的 mutations 和 queries
// ~/components/my-component.js

export default {
  methods: {
    foo () {
      // receive the associated Apollo client 
      const client = this.$apollo.getClient()

      // most likely you would call mutations like following:
      this.$apollo.mutate({mutation, variables})
      
      // but you could also call queries like this:
      this.$apollo.query({query, variables})
        .then(({ data }) => {
          // do what you want with data
        })
    }
  }
}

取得用戶端後,您可以存取其方法和屬性。請參閱 API 參考

任何元件上的智慧查詢

// nuxt.config.js

export default {
  apollo: {
    foo: {
      query: fooGql,
      variables () {
        return {
          myVar: this.myVar
        }
      }
    }
  }
}

有關智慧查詢的更多資訊,請參閱 vue-apollo 文件

在 node_modules 上新增 GQL 檔案識別

// nuxt.config.js

export default {
  apollo: {
    clientConfigs: {
      default: '~/apollo/client-configs/default.js'
    },
    includeNodeModules: true
  }
}

升級

升級指南 apollo-module v3 => v4

此模組的第 4 版讓您無需任何設定。這表示我們使用 vue-cli-plugin-apollo 中可用的最佳方法以及相同的設定行為。這表示您不需要自行設定組態,只需傳遞

如下編輯您的設定

// nuxt.config.js

export default {
  apollo: {
    clientConfigs: {
      default:{
        httpEndpoint: YOUR_ENDPOINT,
        wsEndpoint: YOUR_WS_ENDPOINT
      }
    }
  }
}

升級指南 apollo-client v1 => v2

此模組的第 3 版使用 apollo-client 2.x。您需要確保根據 apollo-client 的升級指南更新所有 middle/afterware。請查看此來源以取得參考:https://www.apollographql.com/docs/apollo-server/migration-two-dot/

疑難排解

代理伺服器

CORS 錯誤通常透過代理伺服器解決。如果您在用戶端主控台中看到跨來源請求錯誤,請研究設定代理伺服器。查看 https://github.com/nuxt-community/proxy-module 以取得快速且直接的設定。

ctx.req.session - req 未定義

這只是一個佔位符。您會想要將其替換為您選擇用來儲存權杖的任何儲存機制。以下是使用本機儲存的範例:https://github.com/Akryum/vue-apollo/issues/144

貢獻和配置設定

在根資料夾的 .env 檔案中設定必要欄位

# cat .env
HTTP_ENDPOINT=https://your-endpoint
WS_ENDPOINT=wss://your-endpoint

index.vue 中,登入過程需要 gql 端點啟用傳回有效權杖的 mutation

mutation authenticateUser($email:String!,$password:String!){
    authenticateUser(email: $email, password: $password) {
        token
        id
    }
}

如果您的 gql 後端已準備好,請開始依以下方式執行 nuxt

npm install
npm run dev