如何使用 Apollo 在 Nuxt 生成的动态页面中正确填充页面 headers?
How to properly populate page headers in Nuxt generated dynamic pages using Apollo?
我有一个 Nuxt.js 静态生成的站点,其中包含一些动态页面。我使用基于 GraphQL 的无头 CMS (DatoCMS) 为这些页面提供数据,使用 Apollo (@nuxt/apollo) 访问。我让它正确生成所有路由,但是当我从我的站点导航导航到这些页面时,我收到以下错误 3 次:
TypeError: Cannot read property '_seoMetaTags' of undefined
at f.head (cf150f1920d36ab67139.js:1)
at wn.get (008dfc959ff6e6a713a0.js:2)
at wn.evaluate (008dfc959ff6e6a713a0.js:2)
at f.$metaInfo (008dfc959ff6e6a713a0.js:2)
at f.created (008dfc959ff6e6a713a0.js:2)
at Qt (008dfc959ff6e6a713a0.js:2)
at fn (008dfc959ff6e6a713a0.js:2)
at f.t._init (008dfc959ff6e6a713a0.js:2)
at new f (008dfc959ff6e6a713a0.js:2)
at 008dfc959ff6e6a713a0.js:2
这是来自我的页面组件中的头部代码,很明显有些东西没有正确生成。我还可以在 Chrome 网络选项卡中看到正在调用 GraphQL 接口,这也告诉我静态生成工作不正常。
这是我的页面组件的 head() 和 apollo 部分:
head() {
return {
title: this.blogPost._seoMetaTags.find(element => {
return element.tag === 'title';
}).content,
meta: [
{ hid: 'keywords', keywords: this.blogPost.keywords },
{ hid: 'description', description: this.blogPost._seoMetaTags.find(element => {
return element.tag === 'meta' && element.attributes.name === 'description';
}).attributes.content}
],
script: [
{ src: 'https://cdn.commento.io/js/commento.js', defer: true }
]
}
},
apollo: {
blogPost: {
query: gpl`
query BlogPost($slug: String!) {
blogPost(filter: { slug:{ eq: $slug }}) {
title
titleColor {
hex
}
slug
author
keywords
_seoMetaTags {
tag
attributes
content
}
_firstPublishedAt
banner {
id
url
title
}
content {
... on HeadingRecord {
_modelApiKey
heading
}
... on SubHeadingRecord {
_modelApiKey
subHeading
}
... on TextRecord {
_modelApiKey
content
}
... on CodeRecord {
_modelApiKey
codeBlock
}
... on ImageRecord {
_modelApiKey
image {
id
height
width
url
title
alt
}
}
... on VideoRecord {
_modelApiKey
video {
height
provider
providerUid
thumbnailUrl
title
url
width
}
}
}
}
}
`,
prefetch({ route }) {
return {
slug: route.params.slug
};
},
variables() {
return {
slug: this.$route.params.slug
};
}
还有我的 nuxt.config.js 如果有帮助的话:
const pkg = require('./package')
const webpack = require('webpack');
从 'node-fetch' 导入提取;
从 'apollo-link' 导入 { 执行,makePromise };
从 'apollo-link-http' 导入 { createHttpLink };
从 'graphql-tag';
导入 gql
module.exports = {
模式:'universal',
/*
** Headers of the page
*/
head: {
title: pkg.name,
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'stylesheet', href: 'https://cdn.jsdelivr.net/gh/tonsky/FiraCode@1.206/distr/fira_code.css' }
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
],
/*
** Plugins to load before mounting the App
*/
plugins: [
],
/*
** Nuxt.js modules
*/
modules: [
'@nuxtjs/style-resources',
'@nuxtjs/apollo',
'@nuxtjs/google-analytics'
],
/*
** @nuxtjs/google-analytics settings
*/
googleAnalytics: {
id: 'UA-136517294-1'
},
/*
** @nuxtjs/style-resources settings
*/
styleResources: {
scss: [
'./assets/css/*.scss'
]
},
/*
** Apollo setup for DatoCMS graphql queries
*/
apollo: {
includeNodeModules: true,
clientConfigs: {
default: '@/apollo/default.js'
}
},
/*
** Build configuration
*/
build: {
postcss: {
preset: {
features: {
customProperties: false
}
}
},
/*
** You can extend webpack config here
*/
extend(config, ctx) {
}
},
/*
** Generate configuration
*/
generate: {
routes: function(callback) {
// Get the list of posts
const uri = 'https://graphql.datocms.com';
const link = new createHttpLink({ uri: uri, fetch: fetch });
const operation = {
query: gql`
{
allBlogPosts {
id
slug
keywords
_seoMetaTags {
tag
attributes
content
}
}
}`,
context: {
headers: {
authorization: 'Bearer <my token>'
}
}
};
makePromise(execute(link, operation))
.then(data => {
// Build the routes from the posts
const postRoutes = data.data.allBlogPosts.map(item => {
return { route: `/blog/${item.slug}`, payload: { keywords: item.keywords, seoData: item._seoMetaTags }};
});
// Register the routes
callback(null, postRoutes);
})
.catch(error => console.log(`received error ${error}`));
}
}
}
如果您希望所有 api 请求都被捆绑到应用程序中并且不再发出,那不是 nuxt 目前的工作方式。它仍然会使用应用程序在客户端导航上向 api`s 发出请求。
nuxt中有制作全静态模式的计划,你可以在这里追踪https://github.com/nuxt/rfcs/issues/22
我有一个 Nuxt.js 静态生成的站点,其中包含一些动态页面。我使用基于 GraphQL 的无头 CMS (DatoCMS) 为这些页面提供数据,使用 Apollo (@nuxt/apollo) 访问。我让它正确生成所有路由,但是当我从我的站点导航导航到这些页面时,我收到以下错误 3 次:
TypeError: Cannot read property '_seoMetaTags' of undefined
at f.head (cf150f1920d36ab67139.js:1)
at wn.get (008dfc959ff6e6a713a0.js:2)
at wn.evaluate (008dfc959ff6e6a713a0.js:2)
at f.$metaInfo (008dfc959ff6e6a713a0.js:2)
at f.created (008dfc959ff6e6a713a0.js:2)
at Qt (008dfc959ff6e6a713a0.js:2)
at fn (008dfc959ff6e6a713a0.js:2)
at f.t._init (008dfc959ff6e6a713a0.js:2)
at new f (008dfc959ff6e6a713a0.js:2)
at 008dfc959ff6e6a713a0.js:2
这是来自我的页面组件中的头部代码,很明显有些东西没有正确生成。我还可以在 Chrome 网络选项卡中看到正在调用 GraphQL 接口,这也告诉我静态生成工作不正常。
这是我的页面组件的 head() 和 apollo 部分:
head() {
return {
title: this.blogPost._seoMetaTags.find(element => {
return element.tag === 'title';
}).content,
meta: [
{ hid: 'keywords', keywords: this.blogPost.keywords },
{ hid: 'description', description: this.blogPost._seoMetaTags.find(element => {
return element.tag === 'meta' && element.attributes.name === 'description';
}).attributes.content}
],
script: [
{ src: 'https://cdn.commento.io/js/commento.js', defer: true }
]
}
},
apollo: {
blogPost: {
query: gpl`
query BlogPost($slug: String!) {
blogPost(filter: { slug:{ eq: $slug }}) {
title
titleColor {
hex
}
slug
author
keywords
_seoMetaTags {
tag
attributes
content
}
_firstPublishedAt
banner {
id
url
title
}
content {
... on HeadingRecord {
_modelApiKey
heading
}
... on SubHeadingRecord {
_modelApiKey
subHeading
}
... on TextRecord {
_modelApiKey
content
}
... on CodeRecord {
_modelApiKey
codeBlock
}
... on ImageRecord {
_modelApiKey
image {
id
height
width
url
title
alt
}
}
... on VideoRecord {
_modelApiKey
video {
height
provider
providerUid
thumbnailUrl
title
url
width
}
}
}
}
}
`,
prefetch({ route }) {
return {
slug: route.params.slug
};
},
variables() {
return {
slug: this.$route.params.slug
};
}
还有我的 nuxt.config.js 如果有帮助的话:
const pkg = require('./package')
const webpack = require('webpack'); 从 'node-fetch' 导入提取; 从 'apollo-link' 导入 { 执行,makePromise }; 从 'apollo-link-http' 导入 { createHttpLink }; 从 'graphql-tag';
导入 gqlmodule.exports = { 模式:'universal',
/*
** Headers of the page
*/
head: {
title: pkg.name,
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'stylesheet', href: 'https://cdn.jsdelivr.net/gh/tonsky/FiraCode@1.206/distr/fira_code.css' }
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
],
/*
** Plugins to load before mounting the App
*/
plugins: [
],
/*
** Nuxt.js modules
*/
modules: [
'@nuxtjs/style-resources',
'@nuxtjs/apollo',
'@nuxtjs/google-analytics'
],
/*
** @nuxtjs/google-analytics settings
*/
googleAnalytics: {
id: 'UA-136517294-1'
},
/*
** @nuxtjs/style-resources settings
*/
styleResources: {
scss: [
'./assets/css/*.scss'
]
},
/*
** Apollo setup for DatoCMS graphql queries
*/
apollo: {
includeNodeModules: true,
clientConfigs: {
default: '@/apollo/default.js'
}
},
/*
** Build configuration
*/
build: {
postcss: {
preset: {
features: {
customProperties: false
}
}
},
/*
** You can extend webpack config here
*/
extend(config, ctx) {
}
},
/*
** Generate configuration
*/
generate: {
routes: function(callback) {
// Get the list of posts
const uri = 'https://graphql.datocms.com';
const link = new createHttpLink({ uri: uri, fetch: fetch });
const operation = {
query: gql`
{
allBlogPosts {
id
slug
keywords
_seoMetaTags {
tag
attributes
content
}
}
}`,
context: {
headers: {
authorization: 'Bearer <my token>'
}
}
};
makePromise(execute(link, operation))
.then(data => {
// Build the routes from the posts
const postRoutes = data.data.allBlogPosts.map(item => {
return { route: `/blog/${item.slug}`, payload: { keywords: item.keywords, seoData: item._seoMetaTags }};
});
// Register the routes
callback(null, postRoutes);
})
.catch(error => console.log(`received error ${error}`));
}
}
}
如果您希望所有 api 请求都被捆绑到应用程序中并且不再发出,那不是 nuxt 目前的工作方式。它仍然会使用应用程序在客户端导航上向 api`s 发出请求。
nuxt中有制作全静态模式的计划,你可以在这里追踪https://github.com/nuxt/rfcs/issues/22