# Vue首屏渲染优化与SEO

TIP

对于展示类型的页面,可以使用SSR服务端渲染的方式来提高首屏加载的速度,以及SEO的优化,那么对于SPA类型的项目,如何提高首屏的加载速度以及SEO的优化呢

# 路由懒加载

TIP

在路由中采用懒加载的写法,。此方法会将懒加载的页面分成多个js打包,减小了单个文件的大小。path到对应的路由时,才会异步的加载对应的页面以及数据,这样可以提高首屏页面加载的速度,减少不必要的页面加载

# 通过CDN引入第三方库

TIP

项目开发中,会用到很多第三方库,如果可以按需引入,只引入自己需要的组件来减少所占的空间。但也会有一些不能按需引入,我们可以采用CDN外部加载,在index.html中从CDN引入第三方库(国内采用https://www.bootcdn.cn/)。通过CDN引入,可以通过CDN加速,获得更快的访问速度。目前采用引入依赖包生产环境的js文件加载,直接通过window可以访问暴露出的全局变量,不必通过import引入、Vue.use注册。 在webpack打包配置中添加externals字段在运行时去外部获取这些扩展依赖。key为依赖包的名称,value是源码抛出的全局变量。

module.exports = {
  //...
  externals: {
    vue: 'Vue',
    vuex: 'Vuex',
    'vue-router': 'VueRouter',
    axios: 'axios',
    'element-ui': 'ELEMENT'
  },
};

# 开启gzip压缩

TIP

gzip压缩是一中http请求优化方式,通过减少文件体积来提高加载速度。html、js、css文件甚至json数据都可以用它压缩,可以减小60%以上的体积。前端配置gzip压缩,并且服务端使用nginx开启gzip,用来减小网络传输的流量大小。客户端和服务端必须共同支持gzip。前端压缩需要安装compression-webpack-plugin插件。

// 在webpack中配置如下
// webpack.prod.config.js
const CompressionWebpackPlugin = require('compression-webpack-plugin')

plugins: [
  new CompressionWebpackPlugin({
    test: /\.js$|\.html$|\.css/, // 都压缩哪些文件
    threshold: 10240, // 
    deleteOriginalAssets: false // 不删除源文件,对于不支持的浏览器还会继续请求源文件
  })
]


// nginx启用gzip
// nginx -s reload :修改配置后重新加载生效
http {
  gzip on; # 开启Gzip
  gzip_static on; # 开启静态文件压缩
  gzip_min_length  1k; # 不压缩临界值,大于1K的才压缩
  gzip_buffers     4 16k;
  gzip_http_version 1.1;
  gzip_comp_level 2;
  gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss; # 进行压缩的文件类型
  gzip_vary on;
  gzip_proxied   expired no-cache no-store private auth;
  gzip_disable   "MSIE [1-6]\.";
  // 其他配置....
}

# SPA预渲染

TIP

对于spa类的项目,要想更快的话,只有预渲染。需要用到prerender-spa-plugin。 预渲染原理:构建阶段生成匹配预渲染路径的html(写的每个需要预渲染的路由都有一个对应的html)。构建出来的html文件已有部分内容。

需要用到prerender-spa-plugin来做预渲染,它是一个webpack插件,用于在单页应用中预渲染静态html内容。

prerender-spa-plugin原理:在webpack构建阶段的最后,在本地启动node服务,启动Puppeteer,通过Puppeteer这个node提供的无头浏览器(没有用户界面的浏览器),提供的API来模拟用户访问需要预渲染的路由,node服务收到请求处理后并返回对应的页面,之后Puppeteer处理返回的页面并渲染,拿到最终渲染的页面内容并替换掉之前打包的html文件。

使用预渲染路由模式必须用history模式。因为hash不会被带到服务器,路由信息会丢失。

// 在webpack中引入并使用
// webpack.prod.config.js
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;

// 加到plugins对象中
// 预渲染配置
new PrerenderSPAPlugin({
  // 生成文件的路径,也可以与webpakc打包的一致
  // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
  staticDir: path.join(__dirname, 'dist'),
  //必需,要渲染的路由。index有参数,就需要写成 /index/param1。
  routes: ['/login'],
  //必须,要使用的实际渲染器,没有则不能预编译
  renderer: new Renderer({
      inject: {},
      headless: false, //渲染时显示浏览器窗口。对调试很有用。  
      // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
      renderAfterDocumentEvent: 'render-event'
  })
})

// main.js
new Vue({
  router,
  store,
  render: h => h(App),
  mounted () {
    // 增加预渲染触发事件
    document.dispatchEvent(new Event('render-event'))
  }
}).$mount('#app')

// 如果用了`nginx`做代理,nginx还需要一些配置
location = / {
  try_files /home/index.html /index.html;
}

location / {
  try_files $uri $uri/ /index.html;
}

解决预渲染的SEO问题

需要安装vue-meta-info包。

npm install vue-meta-info --save

main.js中引入

import MetaInfo from 'vue-meta-info'
Vue.use(MetaInfo)

然后在各个vue页面里面配置属于自己的meta标签

<script>
export default {
  // 配置title和meta数据
  metaInfo: {
    title: 'title',
    meta: [
      {
        name: 'keywords',
        content: '关键字'
      },
      {
        name: 'description',
        content: '描述'
      }
    ]
  },
  data () {
    return {}
  }
}
</script>
上次更新: 7/25/2021, 6:53:21 PM