如何使用Apollo在Nuxt生成的动态页面中正确填充页面标题?

时间:2019-05-12 17:21:01

标签: javascript graphql apollo nuxt.js

我有一个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'导入{execute,makePromise}; 从'apollo-link-http'导入{createHttpLink}; 从“ graphql-tag”导入gql;

module.exports = {     模式:“通用”,

/*
** 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}`));
    }
}

}

1 个答案:

答案 0 :(得分:0)

如果您希望所有api请求都捆绑到应用中并且不再发出,那不是nuxt当前的工作方式。仍然会使用该应用向客户端浏览器上的api发送请求。

有一个计划在nuxt中建立全静态模式,您可以在此处https://github.com/nuxt/rfcs/issues/22

进行跟踪