我们按照vue-cli脚手架开发的vue项目,打包后是一个空的html和一些js、css,在浏览器拿到这些资源后就会根据js去请求数据、生成dom然后再插入html,这种就浏览器渲染,由于这种方式无法解决seo,而且白屏时间偏长导致对应的体验不佳,便有了预渲染和服务器渲染。
与服务器渲染(ssr)相对比,预渲染能与服务端渲染一样提高 SEO 优化,但是预渲染对配置更简单,实现成本低。弱网环境下,预渲染能更快地呈现页面内容,减少页面可见时间。
接下来我们实现下预渲染
# 安装 vue-cli
npm install -g vue-cli
# 初始化项目
vue init webpack rerender__test
# 安装依赖
cd rerender__test
yarn
// 安装prerender-spa-plugin
yarn add prerender-spa-plugin --dev
// 安装vue-meta-info
yarn add vue meta-info
<!-- webpack.prod.conf.js -->
const PrerenderSpaPlugin = require('prerender-spa-plugin')
...
plugins: [
...,
new PrerenderSpaPlugin({
// 编译后html需要存放的路径
staticDir: path.join(__dirname, '../dist'),
// 列出需要预渲染的路由
routes: ['/page1', '/page2']
})
]
export default new Router({
<!-- 要用history模式 -->
mode: 'history',
routes: [
{
path: '/page1',
name: 'page1',
component: () => import('@/components/page1')
},
{
path: '/page2',
name: 'page2',
component: () => import('@/components/page2')
},
{
path: '/page3',
name: 'page3',
component: () => import('@/components/page3')
}
]
})
<!-- page1/index.vue代码 -->
<template>
<div>
<h3>这是page1</h3>
<p>state里面的静态数据:{{staticData}}</p>
<p>计算属性里的静态数据:{{staticComputed}}</p>
<p>axios请求的数据list的长度为:{{listLength}}</p>
<div v-for="(item, index) in list" :key="index">
<h4>{{item.address}}</h4>
<img :src="item.image" />
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
// 这个是配置head信息,vue-meta-info插进提供的功能
metaInfo: {
title: 'page1',
meta: [{
name: 'keyWords',
content: '这个页面是page1'
}],
link: [{
rel: 'stylesheet',
href: 'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
}]
},
data () {
return {
staticData: '这是data里的静态数据',
forComputed: 10,
list: []
}
},
mounted () {
this.getList()
},
computed: {
staticComputed () {
return '这是计算属性里的静态数据' + this.forComputed * 66
},
listLength () {
return this.list.length
}
},
methods: {
getList () {
axios.get('http://rapapi.org/mockjsdata/35670/login/get', {params: {id: 11}}).then(_ => {
let res = _.data
this.list = res.data
})
}
}
}
</script>
├── dist
│ ├── index.html
│ ├── page1
│ │ └── index.html
│ ├── page2
│ │ └── index.html
│ └── static
├── src
│ ├── App.vue
│ ├── assets
│ ├── components
│ │ ├── HelloWorld.vue
│ │ ├── page1
│ │ │ └── index.vue
│ │ ├── page2
│ │ │ └── index.vue
│ │ └── page3
│ │ └── index.vue
│ ├── main.js
│ └── router
│ └── index.js
<!-- dist/page1/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>page1</title>
<link href="/static/css/app.05e24694d1eab4bf2a3c0e1b579ae067.css" rel="stylesheet">
<script type="text/javascript" charset="utf-8" async="" src="/static/js/0.0d9db27f9cb7a148cdca.js"></script>
<meta data-vue-meta-info="true" name="keyWords" content="这个页面是page1">
<link data-vue-meta-info="true" rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div>
<h3>这是page1</h3>
<p>state里面的静态数据:这是data里的静态数据</p>
<p>计算属性里的静态数据:这是计算属性里的静态数据660</p>
<p>axios请求的数据list的长度为:10</p>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/52d228)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/1b0ce8)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/f7db9d)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/ef9977)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/cd66e9)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/0e0e7f)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/0fbdb1)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/e191af)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/4ff834)">
</div>
<div>
<h4>测试内容g371</h4>
<img src="http://dummyimage.com/1200x500/0ae451)">
</div>
</div>
<script type="text/javascript" src="/static/js/manifest.f45cd573301737205ab1.js"></script>
<script type="text/javascript" src="/static/js/vendor.41b1de9c48dd8a8c25a5.js"></script>
<script type="text/javascript" src="/static/js/app.4dc161e30e2d37a0411a.js"></script>
</body>
</html>