月月鸟开发日记(2)
本文地址: ()
avatar
作者: FeRookie 类型: 原创
更新时间:2022-06-26 阅读:556

vue-cli3构建的项目使用prerender-spa-plugin做预渲染

需求描述:

某项目需要做SEO优化,进行对SEO友好处理,不仅仅是添加TDK

技术方案

  1. 前端使用node+koa2进行服务端渲染,也就是SSR,因为我们使用的是vue,也可以采用nuxt
  2. 前端使用prerender-spa-plugin做预渲染,只针对需要进行SEO的页面进行预渲染,比如新闻、资讯等页面

技术利好对比

  1. 如果采用ssr,服务端渲染,可能对已经开发好的项目,改动比较大,虽然也能做,但是比较麻烦,重构成本较高,不建议使用
  2. 采用预渲染,改动较小,开发成本低,但是不能预渲染动态页面,比如某条资讯或者某条新闻等页面不能进行预渲染,可能不能满足需求

最后,进过以上比对,采用了方案二,因为我们虽然不能动态渲染新闻资讯页面,但是我们可以提前将新闻和资讯列表等请求出来放在页面 超出隐藏,可能比较投机取巧,但是以满足业务为主。所以决定了方案,就开始执行了,当然就遇到了一些问题。

开发时遇到的问题

  1. 本地通过serve命令模拟一个服务启动项目,能预渲染,但是放到线上后,就出现了预渲染失败
  2. nginx文件放在服务器端,在配置预渲染页面时极其不方便

预渲染webpack配置代码 vue.config.js:

if (env === 'production' || env === 'development') {
    config.plugins.push(
        new PrerenderSPAPlugin({
        // 生成文件的路径,也可以与webpakc打包的一致。
        // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
            staticDir: path.join(__dirname, 'dist'),
            // 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。
            routes: ['/', '/unlogin', '/news', '/newsmore'],
            minify: {
                collapseBooleanAttributes: true,
                collapseWhitespace: true,
                decodeEntities: true,
                keepClosingSlash: true,
                sortAttributes: true
            },
            renderer: new Renderer({
                headless: true,
                renderAfterTime: 5000, // Wait 5 seconds.
                // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
                renderAfterDocumentEvent: 'render-event'
            })
        })
    )
}

在main.js里面需写上:

new Vue({
    el: '#app',
    router,
    store,
    render: h => h(App),
    mounted() {
        // render-event 需与webpack配置的事件名称同名
        document.dispatchEvent(new Event('render-event'))
    }
})

然后在本地build一次,dist目录里面会创建好你预渲染的页面 然后在通过serve -s dist命令 启动项目打开 localhost:5000 (安装serve npm install serve -g) 打开浏览器控制台,查看document资源,可以看到preview已经把整个页面渲染出来了 说明已经成功了! 至此,前端配置已经完成了! 那么问题来了,为什么放到服务器上就GG了呢? 放上去的效果是可以打开页面,但首次不是预渲染页面,刷新一下当前页面,页面就丢失了。实在的 困惑了我很久,也用过很多方式,比如修改打包配置文件啊等等,到最后都不行,所以只能采取强制措施了,修改nginx 叫你不听话!!! 这也是问题1,2的关键所在,咱们需要配置nginx。怎么配置的呢? 直接上代码:

location / {
    if ($uri = /unlogin) {
        rewrite .* /unlogin/index.html break; // 重定向
    }
    if ($uri = /news) {
        rewrite .* /news/index.html break;
    }
    if ($uri = /newsmore) {
        rewrite .* /newsmore/index.html break;
    }
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html; #目录不存在则执行index.html
}

就这样哈,不解释了,一口干了!(看得懂的非常好,看不懂的copy) 好了,以上的一系列已经解决了我的问题了。不知道能不能解决你的问题呢。 最后说几个没去调研的注意事项吧,帮助有问题的同学找到问题(不要抠字眼啊!!!)

注意事项:

  1. vue项目路由需要history模式
  2. webpack配置的预渲染的输出目录 staticDir outputDir indexPath
  3. nginx 放在前端配置,每次通过jenkins部署的时候 通过命令将nginx文件 copy进去就ok了
  4. 下载不了prerender-spa-plugin是因为 默认使用的是chormeium,你可以在jenkins的服务器上安装一个cnpm,通过cnpm来下载,记住第一次使用cnpm install的时候 需要修改jenkins构建配置清除上一次下载的包,因为npm install 会生成package-lock.json文件,会默认下载里面的东西,导致下载不了,以后就可以不用清除了,因为cnpm install不会生成版本锁,prerender-spa-plugin每次都重新下载的话,还是比较浪费时间的。

完事了!谢谢!