Front-end optimization of first screen loading speed

Execute npm run build, and access the project after deploying the packaged code online. You will find that the performance is very bad and the page will be blank for a long time. This is an intolerable performance problem and urgently needs to be solved.

1. Lazy loading of routing.

Original route import component

import Index from @/views/index.vue;
{
    
    
	path: '/'
	name: 'index'
	component: Index
}

Now introduce routing (vue asynchronous component)

import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router)
 {
    
    
      path: "/",
      name: "index",
      component: resolve => require(["@/views/Index"], resolve)
}

ES proposed import method (commonly used)
const HelloWorld = ()=>import('The address of the module to be loaded')

import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router)
const HelloWorld = ()=>import("@/components/HelloWorld")
export default new Router({
    
    
  routes: [
    {
    
    
      path: '/',
      name: 'HelloWorld',
      component:HelloWorld
    }
  ]
})

2. Lazy loading of components

The wording in the original component:

<template>
	<div>
		<span></span>
		<One-com></One-com>
	</div>
</template>

<script>
import One from './one';
export default{
    
    
	components:{
    
    
		"One-com": One,
	},
	data(){
    
    
		return{
    
    
			num: 0
		}
	}
}
</script>

const method

<template>
  <div class="hello">
  <One-com></One-com>
  1111
  </div>
</template>

<script>
const One = ()=>import("./one");
export default {
    
    
  components:{
    
    
    "One-com":One
  },
  data () {
    
    
    return {
    
    
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

Asynchronous method:

<template>
  <div class="hello">
  <One-com></One-com>
  1111
  </div>
</template>

<script>
export default {
    
    
  components:{
    
    
    "One-com":resolve=>(['./one'],resolve)
  },
  data () {
    
    
    return {
    
    
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

3. The server opens gzip. The optimization effect of this step is the most significant

The first step is to configure and enable gzip in vue-config.js.

// 安装插件
npm i --save-dev compression-webpack-plugin
 
// 在vue-config.js 中加入
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
const isProduction = process.env.NODE_ENV === 'production';
 
.....
module.exports = {
    
    
....
 configureWebpack: config => {
    
    
  if (isProduction) {
    
    
   config.plugins.push(new CompressionWebpackPlugin({
    
    
    algorithm: 'gzip',
    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
    threshold: 10240,
    minRatio: 0.8
   }))
  }
 }
}

Step 2 Start gzip on the WEB server. Take my nginx as an example here.

gzip  on;
gzip_types text/plain application/x-javascript application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

4. Enable CDN acceleration.

Using Gzip has reduced the file size by two-thirds. If it is still not enough, separate out the code or library that is unlikely to change, continue to reduce the single chunk-vendors, and then accelerate the loading of resources through CDN.
(For vue, vuex, vue-router, and vue-moment, use cdn to introduce. In addition, the client can also introduce highlight cdn, but the management side does not need it. Therefore, two different template html are required. The configuration is as follows:)

(1), vue.config.js continues to join based on the previous step

config.externals的配置,如下:
configureWebpack: config => {
    
    
    if (isProduction) {
    
    
      config.plugins.push(
        new CompressionWebpackPlugin({
    
    
          algorithm: "gzip",
          test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
          threshold: 10240,
          minRatio: 0.8
        })
      );
 
      config.externals = {
    
    
        vue: "Vue",
        "vue-router": "VueRouter"
      };
    }
  }

(2) Block or delete all the places where vue and vue-router were originally introduced.

//原来对vue、vue-router的引用全部注释掉。
//涉及所有引用的文件,只要有引入就注释掉。
 
// import Vue from "vue";
// import Router from "vue-router";
 
//vue-router的非cdn引用
//Vue.use(Router);
 

(3) When using vue-router in the code, use VueRouter.

//cdn 引入vue-router时,源码抛出的变量是:VueRouter
console.log(VueRouter);
Vue.use(VueRouter);
 
//Vue.use(Router); 继续像原来一样用Router就会报错。

Pre-render

The problem solved by the above solution is to reduce the size of js resources in order to speed up the loading speed. Such a solution is fast enough for the first screen rendering when the network is good, but after all, rendering depends on the execution logic after the js loading is completed, and This approach is not conducive to SEO. Then there are two solutions to further improve the loading of the first screen, one is pre-rendering, and the other is SSR, which is server-side rendering. The latter is more complicated. I will analyze it in a future article. The method of server-side rendering is similar. Compared with pre-rendering, the main advantage is that it can dynamically splice data and return it as part of the document, thus achieving more friendly SEO and dynamic sharing functions.

Pre-rendering relies on a prerender-spa-plugin plug-in, which must be introduced in webpack.prod.conf.js first, as follows

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

Then, add the following plugin configuration in plugins:

new PrerenderSPAPlugin(

      path.join(__dirname, '../nginx/blog'),
      ['/'],
      {
    
    
        //在一定时间后再捕获页面信息,使得页面数据信息加载完成
          captureAfterTime: 50000,
          //忽略打包错误
          ignoreJSErrors: true,
          phantomOptions: '--web-security=false',
          maxAttempts: 10,
        }
)

After this configuration, the packaged index.html contains the pre-rendered dom structure, so the first screen rendering speed will be greatly improved. But there is a problem to pay attention to here. The chunk file after asynchronously loaded routing is inserted into the head tag, and has an async attribute, as follows:

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Blog - SilentPort</title>
  <link href="/static/css/client.6b5a982c3673872dbaa1a8891279d36d.css" rel="stylesheet">
  <script type="text/javascript" charset="utf-8" async="" src="/static/js/3.c925dfc72043d1d1d5ac.js"></script>
</head>

The runtime manifest file is located at the bottom of the body. Because async will cause the process of loading and rendering subsequent document elements and the loading and execution of the current script script to proceed in parallel (asynchronous), this will cause the script to be executed before the manifest. Will produce a webpackJsonp is not defined error. Therefore, you need to manually change async to defer before deployment. The latter will also be performed in parallel with the loading of the current script during the process of loading subsequent document elements (asynchronously), but the execution of the current script will be executed after all elements are parsed. , Finished before the DOMContentLoaded event is triggered, which ensures that the script will be executed in the manifest afterwards.

Reference article: https://www.jianshu.com/p/da46f410156a?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Guess you like

Origin blog.csdn.net/weixin_39854011/article/details/111822108