vue 预渲染的问题

我想实现让我的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}}">更多 &gt; &gt;</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">查看详情 &gt; &gt;
          </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>

阅读 8.7k
2 个回答

预渲染在构建阶段就已经生成了匹配预渲染路径的html文件,你的每个路由都可以作为入口文件,预渲染后其对应文件夹下都有一个index.html,作为路口文件,之后在跳转走的是前端路由,并不再请求html文件。首屏预渲染对还需要请求易变数据的页面不太合适,因为展示的html很可能是上次预渲染的html,等到请求完毕返回数据后再展示最新的html会引起客户的误解和疑惑。让你配路由是因为,若你一开始访问的不是首页,是其他路由,那么请求其他路由下已经预渲染好的index.html,否则如果不做预渲染,会请求你的根节点的index.html,再根据路由匹配,链到你请求的路由下的页面

把你要渲染的路由放进数组里,然后只支持history模式。但是这个东西是为了SEO的吧,并不能加快你真实页面的渲染速度。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题