Nuxt Nation 大会即将到来。加入我们,时间为 11 月 12 日至 13 日。

apollo
@nuxtjs/apollo

使用 vue-apollo 在您的 Nuxt 应用中集成 GraphQL。

NuxtJS 中的 Apollo

npm version license

警告

此版本需要 Vue 2.6+ 及其 serverPrefetch 支持。例如

有时您可能需要删除/重建 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://apollo.graphql.net.cn/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 选项:必需

设置 apollo 客户端端点。您可以在 此处 找到每个端点的所有可用选项

查看 官方 vue-apollo-cli,其中展示了可能的用例。

clientConfigs.default 对象:必需

clientConfigs。 对象|路径:可选

tokenName 字符串:可选,默认值:'apollo-token'

用于在身份验证情况下设置的 cookie 的令牌名称。您还可以在每个 clientConfigs 中提供一个 tokenName 选项来覆盖默认值。在每次发出请求时,此 cookie 中的值都将发送到“Authorization”HTTP 标头中,如以下 authenticationType 所指定。

authenticationType 字符串:可选,默认值:'Bearer'

设置任何授权请求的身份验证类型。如果您的 GraphQL API 需要身份验证类型不是默认的 Bearer,请修改此设置。然后,所有请求都将以适当的 HTTP 标头格式发送:“Authorization ”(例如 Authorization: Bearer abc123)。

如果您的后端需要“Authorization”格式的 Authorization 标头,没有任何前缀,那么您应该将此值设置为空字符串。

includeNodeModules 布尔值:可选,默认值: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 的 defaultClient 的示例

Vuex 操作
// ~/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
  }
}
访问客户端或在组件内的任何方法中调用变异和查询
// ~/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 的升级指南更新所有中间件/后置件。查看此源代码以供参考:https://apollo.graphql.net.cn/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 authenticateUser($email:String!,$password:String!){
    authenticateUser(email: $email, password: $password) {
        token
        id
    }
}

如果您的 gql 后端已准备好,请按如下方式运行 nuxt

npm install
npm run dev