vue预渲染实践总结

vue

# 预渲染

## 预渲染简介

SEO和首屏加载速度慢的问题,社区讨论最多的解决方案是同构 SSR,即首屏使用服务端渲染,之后的交互逻辑交给客户端处理,解决了单页应用带来的两个问题,但是也带来了服务器压力增大,学习成本高,对老项目入侵性过强等问题。

## 版本信息

vue: 2.5.2

webpack: 3.6.0

vue-router: 3.0.1

prerender-spa-plugin: 3.4.0


## 使用

这里我们按照官方 github 的例子敲一下

const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')

module.exports = {
plugins: [
...
new PrerenderSPAPlugin({
// 这里选择文件生成目录.
staticDir: path.join(__dirname, 'dist'),
// 这里选择你要预加载的 router 路径,要与在 router 文件里面定义保持一致
routes: [ '/login' ],
})
]
}


还有一些注意事项,假设你的 vue 工程是 vue-cli 2-x 版本的

在 `config/index.js` 里面 `build/assetsPublicPath` 的值为 '/', 这里不能使用相对路径了


const path = require("path")

module.exports = {

build: {

index: path.resolve(__dirname, "../base/index.html"),

assetsRoot: path.resolve(__dirname, "../dist"),

assetsSubDirectory: "static",

assetsPublicPath: "/",

}

}


还有个配置要注意下在`build/utils.js` 中的 `ExtractTextPlugin.extract` 的 `publicPath` ,否则一些vue中引用的资源会找不到

ExtractTextPlugin.extract({

use: loaders,

fallback: 'vue-style-loader',

// publicPath: '../../'

})



然后在 `router/index.js` 的配置,预渲染要求是 history 模式,如果不声明,则生成的页面都是同一个 html,

import Vue from 'vue'

import Router from 'vue-router'

Vue.use(Router)

export default new Router({

mode: 'history',

routes: [...]

})


这个时候可以执行 `npm run build` 打包我们的项目了,一切正常的话,dist目录应该是这个样子的

├── index.html
├── login
│   └── index.html
└── static
├── css
├── fonts
├── images
├── img
└── js

看到 login 文件夹里面有 index.html,就代表你成功了,


## nginx 配置

这里不需要对这个插件做特殊处理,但是需要对 history 路由做处理,这里贴一下我的ngnix.config配置

server{

listen 8000;

server_name localhost;

root /dist;

error_page 500 502 503 504 /50x.html;

location ~^/declaring/ {

try_files $uri $uri/ /index.html;

}

location = /50x.html {

root /dist;

}

}

到这里,重启 nginx, 应该就可以看到效果了

## 遇到的问题:

**生成的 html 里面不是我们想要的页面 html,或者里面的css,js引用失效。**

检查 `config/index` 里面的 `build/assetsPublicPath` 是不是根目录,

检查 路由是否是 history 模式

检查 `build/utils.js` 中的 `ExtractTextPlugin.extract` 的 `publicPath` 字段是否为空,


**加载页面会有闪屏的效果**

因为预加载是把当前页面,提到构建的时候加载,请求的时候,就会先加载html,然后加载 vue 实例,当 vue 加载好了,vue 会 render 并 push 到 #app 的 DOM 节点上,效果就是闪屏,而且如果页面是动态的,千人千面的,那么用户第一次看到的页面将会是你 build 时获取的数据,然后闪一下,vue 接管页面后正常渲染,

这个问题,RRS也是遇到,vue 也提供了相应的解决方案,我们移植过来就可以解决了,想了解更详细的,请参考[客户端激活(client-side hydration)](https://ssr.vuejs.org/zh/guide/hydration.html)

postProcess(context) {

context.html = context.html.replace('');

return context;

},


下面是全部更改:

// build/webpack.prod.conf.js

...

const PrerenderSpaPlugin = require('prerender-spa-plugin')

const Renderer = PrerenderSpaPlugin.PuppeteerRenderer

...

plugins: [

new PrerenderSpaPlugin({

// 编译后html需要存放的路径

staticDir: config.build.assetsRoot,

outputDir: config.build.assetsRoot,

indexPath: config.build.index,

// 列出需要预渲染的路由

routes: ['/', '/login'],

postProcess(context) {

context.html = context.html.replace('>);

return context;

},

renderer: new Renderer({

headless: false,

renderAfterTime: 5000,

// renderAfterDocumentEvent: 'render-event' // document.dispatchEvent(new Event('render-event'))

})

})

]

// build/utils

if (options.extract) {

return ExtractTextPlugin.extract({

use: loaders,

fallback: 'vue-style-loader',

// publicPath: '../../'

})

}

// router/indes.js

let router = new Router({

mode: 'history',

routes: [...]

})

// config/index.js

build: {

...

assetsPublicPath: '/'

}

// nginx.conf

server{

listen 8000;

server_name localhost;

root /dist;

error_page 500 502 503 504 /50x.html;

location /api/ {

#rewrite ^/api/(.*)$ /$1 break;

proxy_pass xxx.xxx.xxx;

}

location ~^/declaring/ {

try_files $uri $uri/ /index.html;

}

location = /50x.html {

root /dist;

}

}



以上是 vue预渲染实践总结 的全部内容, 来源链接: utcz.com/z/379346.html

回到顶部