我想实现让我的vue项目 首页加载得很更快点 网上了查找了一些关于vue首屏优化的问题 好像一般是两种解决方案 一个是SSR服务端渲染 还有一个是利用prerender spa plugin插件进行预渲染 感觉SSR那种方式我的项目应该用不到这么复杂的 就看了下预渲染
但是看了一天的预渲还是没太明白怎么用的
官方文档里有这么一段代码
module.exports = {
// ...
plugins: [
new PrerenderSpaPlugin(
// Absolute path to compiled SPA
path.join(__dirname, '../dist'),
// List of routes to prerender
[ '/', '/about', '/contact' ]
)
]
}
我是想让首页渲染加载得更快一点 不明白它里面为什么会有一个路由的设置 如果在路由的话就路由到其它组件了 这还跟首页渲染有什么关系呢
我的首页里主要就是头部 中间内容部分 以及底部 主要是中间内容部分的轮播图 产品列表的数据是通过axios调取后台接口获取的数据
我是应该把首页的路由路径放到那个配置里面去吗 好蒙
这是我的首页代码
<template>
<div class="home">
<qc-banner :imgUrl="imgUrl"></qc-banner>
<qc-notice :notices="notices"></qc-notice>
<div class="main">
<ul class="data clearfix" id="shortcut">
<li v-for="item in shortcuts">
<img :src="item.imageURL">
<router-link :to="item.url"></router-link>
<h2>{{item.title}}</h2>
</li>
</ul>
<div class="floor">
<div class="floorA" v-show="item.lists.length" v-for="item in productCategories">
<div class="title clearfix">
<p class="prTitle">{{item.prTitle}}</p>
<router-link :to="{path:'/invest',query: {productCategoryId: item.productCategoryId}}">更多 > ></router-link>
</div>
<ul class="bidList clearfix">
<li
v-for="(list, index) in item.lists"
:class="{btwo: index % 3 === 1}"
v-if="index < 3"
>
<h2>{{list.name}}</h2>
<div ref="box" class="circle" :per="list.percent">
<p class="p1">{{list.repayRate.toFixed(2)}}<span>%</span></p>
<p class="p2">预期年化收益率</p>
</div>
<!-- <circle-load class="circle"
:percent="list|proguressPercent"
:size="190"
:trail-width="3"
:stroke-width="3"
stroke-linecap="square"
stroke-color="rgb(255, 114, 29)">
<p class="p1">{{list.repayRate.toFixed(2)}}<span>%</span></p>
<p class="p2">预期年化收益率</p>
</circle-load> -->
<div class="deadline clearfix">
<p class="p1" v-if="list.periodUnit==1" ><i>{{list.period}}</i>个月<span>投资期限</span></p>
<p class="p1" v-if="list.periodUnit==0"><i>{{list.period}}</i>天<span>投资期限</span></p>
<p class="p2">{{list.releaseAmount}}元<span>产品总额</span></p>
</div>
<router-link
v-if="list.status == 2"
:to="{path:'invest/scattered',query: {productId: list.id}}">
立即购买
</router-link>
<router-link
v-if="list.status == 3"
:to="{path:'invest/scattered',query: {productId: list.id}}" class="btn">
已满标
</router-link>
<router-link
v-if="list.status == 4"
:to="{path:'invest/scattered',query: {productId: list.id}}" class="btn">
还款中
</router-link>
<router-link
v-if="list.status == 5"
:to="{path:'invest/scattered',query: {productId: list.id}}" class="btn">
已完成
</router-link>
</li>
</ul>
</div>
</div>
<div class="media clearfix">
<div class="mediaLf">
<div class="title clearfix">
<p class="prTitle">媒体报道</p>
</div>
<div class="detail clearfix">
<img :src="report.imageURL" alt="">
<div class="mediaTxt">
<a :href="report.url" class="cl" target="_blank" style=" float:none;"><h2>{{report.title}}</h2>
</a>
<div v-html="report.content"></div>
<a :href="report.url" class="detl cl" target="_blank">查看详情 > >
</a>
</div>
</div>
</div>
<div class="mediaRt">
<div class="title clearfix">
<a class="prTitle" href="#">网站公告</a>
</div>
<ul id="notice_footer">
<li v-for="item in notices">
<router-link :to="{path:'/information/notice/noticeDetail',query:{id: item.id}}">
<p>{{item.title}}</p><span>2017-08-16</span>
</router-link>
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
import qcBanner from 'components/uiView/Banner/Banner'
import qcNotice from 'components/uiView/HomeNotice/HomeNotice'
import Circle from 'iview/src/components/circle'
import system from 'service/system'
import product from 'service/product'
import article from 'service/article'
import ProgressBar from 'progressbar.js'
export default {
data() {
return {
imgUrl: [],
notices: [],
shortcuts: [],
productCategories: [],
report: {},
lists: []
}
},
created() {
system.getCarousel().then((res) => {
this.imgUrl = res.data.carousel
});
system.getNotice().then((res) => {
this.notices = res.data.list
})
system.getShortcut().then((res) => {
this.shortcuts = res.data
})
product.getProductCategory().then((res) => {
this._getProductList(res.data)
})
article.getReportList().then((res) => {
this.report = res.data.list[0]
})
},
mounted() {
window.addEventListener('scroll', () => {
var top = document.documentElement.scrollTop || document.body.scrollTop
})
setTimeout(() => {
var box = this.$refs.box
box.forEach((item) => {
var bar = new ProgressBar.Circle(item, {
color: '#EAEEF2',
strokeWidth: 3,
trailWidth: 3,
easing: 'easeInOut',
duration: 1400,
text: {
autoStyleContainer: false
},
from: { color: '#FF721D', width: 3 },
to: { color: '#FF721D', width: 3 },
// Set default step function for all animate calls
step: function(state, circle) {
circle.path.setAttribute('stroke', state.color);
circle.path.setAttribute('stroke-width', state.width);
var value = Math.round(circle.value() * 100);
if (value === 0) {
circle.setText('');
} else {
circle.setText(value);
}
}
});
bar.animate( item.getAttribute('per') );
})
},800)
},
methods: {
_getProductList(data) {
for(let i = 0; i < data.length; i++) {
product.getIndexCategoryProductList( data[i].id ).then((res) => {
let lists = res.data.list.map( item => Object.assign(item,{
percent: item.amountNow / item.releaseAmount
}))
this.productCategories.push({
prTitle: data[i].name,
lists: lists,
productCategoryId: data[i].id
})
})
}
}
},
components: {
qcBanner,
qcNotice/*,
CircleLoad: Circle*/
}
}
</script>
<style lang="less" scoped>
@import '~assets/less/index.less';
.home {
width: 100%;
.main {
width: @pages-width;
margin: 0 auto;
.data {
font-size: 14px;
& > li {
color: @french-grey;
margin: 40px 0;
width: 25%;
.fl(left);
text-align: center;
position: relative;
& > img {
width: 56px;
height: 56px;
margin: 0 auto;
position: absolute;
left: 119px;
top: 23px;
border: 0;
vertical-align: middle;
& + a {
margin: 0 auto;
display: block;
width: 100px;
height: 100px;
background: url(../../../assets/images/rect.png);
background-repeat: no-repeat;
transition: transform 0.6s ease-out;
&:hover {
transform: rotateZ(360deg);
}
& + h2 {
font-size: 24px;
color: @french-grey;
margin: 20px 0;
font-weight: normal;
}
}
}
}
}
.floor {
& > div {
margin-bottom: 20px;
.title {
height: 64px;
line-height: 60px;
font-size: 12px;
color: #9a9a9a;
background-color: @white-color;
& > p {
.fl(left);
color: @orange-color;
font-size: 22px;
font-weight: bold;
& + a {
.fr(right);
color: @black-color;
&:hover {
color: @orange-color;
}
}
}
}
.bidList {
& > li {
box-sizing: border-box;
padding: 30px 0 10px 0;
text-align: center;
float: left;
width: 369px;
margin-bottom: 20px;
border: 1px solid #dedede;
&.btwo {
margin: 0 31px;
}
h2 {
font-size: 18px;
color: @french-grey;
font-weight: normal;
padding-bottom: 30px;
}
.circle {
width: 190px;
height: 190px;
position: relative;
margin: 0 auto;
.p1 {
position: absolute;
top: 66px;
left: 40px;
font-size: 36px;
color: @orange-color;
font-weight: bolder;
padding-bottom: 6px;
& > span {
font-size: 18px;
}
}
.p2 {
position: absolute;
top: 120px;
left: 50px;
}
svg {
width: 190px;
height: 190px;
}
}
.deadline{
padding: 20px 50px 0 84px;
& > p {
font-size: 18px;
text-align: left;
& > span {
display: block;
font-size: 14px;
color: #999;
}
&.p1{
color: #666666;
.fl(left);
& > i {
font-size: 20px;
font-style: normal;
color: @orange-color;
}
}
&.p2{
.fr(right);
color: @french-grey;
}
}
}
& > a {
display: block;
width: 291px;
height: 38px;
line-height: 38px;
font-size: 16px;
color: @white-color;
border-radius: 4px;
margin: 20px auto;
background-color: #ff721d;
-webkit-transition: background 0.2s;
cursor: pointer;
&.btn {
border: 1px solid #d9d9d9;
background-color: #d9d9d9;
box-shadow: 0 2px #d5d5d5;
}
}
}
}
}
}
.media {
margin: 90px 0;
.mediaLf {
width: 769px;
height: 219px;
.fl(left);
.title {
background-color: @white-color;
.prTitle{
color: @orange-color;
font-size: 22px;
font-weight: bold;
}
}
.detail {
margin-top: 30px;
& > img {
width: 205px;
height: 115px;
border: 0;
.fl(left);
vertical-align: middle;
}
& > .mediaTxt {
width: 536px;
height: 155px;
.fr(right);
position: relative;
& > a{
.fr(right);
}
& > div {
font-size: 14px;
margin-bottom: 25px;
margin-top: 15px;
height: 65px;
overflow: hidden;
color: #999999;
}
& > .detl {
color: #fe5618;
position: absolute;
bottom: 0;
right: 0;
}
}
}
}
.mediaRt {
height: 219px;
width: 366px;
overflow: hidden;
.title {
background-color: @white-color;
a {
color: @orange-color;
font-size: 22px;
font-weight: bold;
}
}
.fr(right);
& > ul {
height: 157px;
margin-top: 25px;
li {
height: 20%;
a {
color: #666666;
& > p {
width: 280px;
font-size: 14px;
.fl(left);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
& + span {
.fr(right);
color: #999;
}
}
}
}
}
}
}
}
}
</style>
预渲染在构建阶段就已经生成了匹配预渲染路径的html文件,你的每个路由都可以作为入口文件,预渲染后其对应文件夹下都有一个index.html,作为路口文件,之后在跳转走的是前端路由,并不再请求html文件。首屏预渲染对还需要请求易变数据的页面不太合适,因为展示的html很可能是上次预渲染的html,等到请求完毕返回数据后再展示最新的html会引起客户的误解和疑惑。让你配路由是因为,若你一开始访问的不是首页,是其他路由,那么请求其他路由下已经预渲染好的index.html,否则如果不做预渲染,会请求你的根节点的index.html,再根据路由匹配,链到你请求的路由下的页面