Common performance optimization methods
- Loading state or skeleton screen in HTML;
- Remove the external CSS;
- Caching infrastructure;
- Use dynamic polyfill;
- Split common code using SplitChunksPlugin;
- Use Webpack 4.0 Tree Shaking correctly;
- Dynamic import is used to slice the page code and reduce the JS volume of the front screen.
- Compile to ES2015+, improve the efficiency of code operation, reduce the size;
- Use LazyLoad and placeholder to improve the loading experience.
What is first screen loading
First Contentful Paint refers to the time between the browser’s response to the user’s input of the url address and the time when the First screen content is rendered. In this case, the entire web page does not have to be completely rendered, but the content of the current window needs to be displayed
About calculating the first screen time
Use the data provided by performance. Timing
Use DOMContentLoad or Performance to calculate the first screen time
/ / plan: document. AddEventListener (' DOMContentLoaded '(event) = > {the console. The log (' first contentful painting'); }); // Option 2: performance.getEntriesByName("first-contentful-paint")[0].startTime // Performance. GetEntriesByName (" first - contentful - paint ") [0] / / returns a PerformancePaintTiming instance, structure is as follows: {name: "First-contentful-paint ", entryType: "paint", startTime: 507.80000002123415, duration: 0,};Copy the code
Cause of slow loading
In the process of page rendering, factors leading to slow loading may be as follows:
- Network Delay problem
- Check whether the resource file is too large
- Whether the resource has been repeatedly requested to be loaded
- The render content was blocked while loading the script
The solution
Several common optimization methods of SPA first screen
- Reduce the import file volume
- Static resource local cache
- The UI framework loads on demand
- Image resource compression
- Component repackaging
- Enable GZip compression
- Using SSR
background
Due to historical architecture, the loading process of H5 page is that the Server injects jSON_encode interface master data into Smarty template, responds to the browser page with complete JSON data, then executes JavaScript on the browser side, and finally paints the user. The process is shown as follows:
Loading and rendering process before H5 optimization
H5 First screen critical path Takes time to disassemble
Two critical paths that affect H5 First screen content (FCP, First Contentful Paint, First content Paint) are:
- Network Time: depends on Server data query and template compilation. When data query is slow, the arrival of the First Byte (TTFB) is delayed.
- Kernel rendering time: Relies on JavaScript execution to read the page master data and generate a full DOM structure.
Therefore, we specifically designed and implemented the scheme of “route separation + pre-static +WebView pre-creation”. The improved page loading and rendering process is shown as follows:
H5 optimized loading and rendering process
Routing separation
Before route separation, the URL of H5 page is allocated by the Server, and the front end is responsible for writing TPL template products. The corresponding relationship between TPL and final URL is mapped through configuration files in the Server, which increasingly exposes the problems of slow startup and development and high cost of maintenance, handover and communication in the later stage of the page.
So we want to normalize the page routing, let front-end developers control the page entry format, and let back-end developers focus more on the API data logic. Therefore, we designed a front-end route separation scheme and agreed on the mapping relationship between page URL and page source directory, as shown in the following figure:
Predefined URL routing specifications
NGINX responds directly to pre-static HTML files, with the first byte arriving independent of data query and template compilation.
Preliminary static
Front-end route separation directly returns HTML files at the NGINX proxy layer, but the page does not fully render the required data. Before the AJAX request is executed and no return is made, it is necessary to avoid the white screen or global loading state of the page and advance the FCP time.
We used a pre-static page solution. Prestatic does not produce fully static HTML from instant compilation like server rendering. It only generates a few static pages at build time for a specific route. We can use the Webpack plugin to inject some specific pages into the DOM structure at compile time. First, shorten the page white screen time; second, save the resource cost of cloud infrastructure relative to server-side rendering; third, output to search engines to crawl the common content of the page.
Combined with the actual application scenarios and the mainstream pre-static mode in the market, the final webpack plug-in based on the original server rendering capability of ReactDomServer improves the performance and efficiency of pre-static.
The compilation context of each build is obtained by the Webpack plug-in system, and the bundle of the current page is obtained by the before AssetTagGeneration hook of htML-webpack-Plugin. AfterTemplateExecution Hook gets the compiled template HTML of the current page, executes the bundle to export the entire APP module of the page through Eval. The output of each route applied to a single page through ReactDomServer is APP HTML and template HTML merged into pre-static HTML.
The pre-static call sequence of H5 is as follows
The WebView created beforehand
The cache pool composed of WebViews is initialized immediately upon APP startup to ensure that the time of WebView initialization is saved when loading each URL, and the pre-static HTML cache is utilized to finally make the page free from blank screen loading state.
React Server renders SSR
Before we begin, we need to clarify one question: what is server-side rendering?
In the past, rendering was more done on the client side, so why do we let the server do it now?
Are there any differences between server-side rendering and client-side rendering?
In fact, there are a lot of server-side rendering tools, looking at the manual will soon be able to get started, there is no difficulty, the key lies in what scenarios we need to use server-side rendering, what kind of rendering scheme is more suitable for our project; Learning, know how, we need to understand the service side rendering of the basic concept and principle of the service side rendering why, what is solved our problems, grasp the overall rendering logic and thinking, can we use in learning tools, at ease, and even tools have changed and updated later, we can with ease, No more “can’t learn”;
This logic is called the concept of tao, Dharma, shu and apparatus; Do not just stay in the use of tools and some of the tools of strange and crafty, more to the Dharma, dao level growth;
What is SSR?
Most of the modern front-end projects are single-page applications, which is what we call SPA. The whole application has only one page, and different page contents are displayed by means of components. After all the data is obtained by the request server, the client is assembled and displayed. This is the default rendering logic of the current front-end framework, which we call Client Side Render (CSR for short);
Load the rendering process as follows: HTML/CSS code –> load JavaScript code –> Execute JavaScript code –> render page data
image-20210126143051858.png
The biggest problem with client-side rendering for SPA applications is twofold:
1: The white screen lasts for a long time, resulting in poor user experience.
2: No content in HTML, SEO is not friendly;
The reason for this problem is that, when loading for the first time, the whole SPA script program needs to be downloaded, and the browser can only obtain the data to be displayed on the page after executing the code logic. However, the download of SPA script requires a long wait and execution time. Meanwhile, the SPA script downloaded to the browser has no page data. The browser actually does not have much rendering work, so users see a page without any content, not only that, because there is no content in the page, the search engine crawler crawls to the blank content, which is not conducive to SEO keyword acquisition;
Compared with the traditional site, browser pages are processed by the server has content static pages, back-end programming experience may be more familiar with some, page structure and content, are processed by the server, returned to the client;
The whole universe starting diagram, the whole process display
Comparison of the two we will find that traditional site page data synthesis server in the background, and the application of SPA page data synthesis in the browser, but regardless of that, the final rendering, or to the browser to complete, so, don’t get me wrong, we here rendering of a service and the client rendering, refers to the page structure and data synthesis, It’s not a browser presentation job;
So can we use the ideas of traditional websites to solve the problems of SPA and retain the advantages of SPA? Whether long hang time or SEO is not friendly, practical is the first screen page structure back to the browser first, and then to get the data after synthesis problems, so, the first screen page structure and data, as long as like traditional site, first on the server returned again after synthesis, at the same time put the SPA script loading is still in the first screen, At this point, the returned page is the complete content of the structure and data, so that the browser can load the SPA script when displaying the home page data, and the crawler of the search engine can also obtain the corresponding data, to solve the problem of SEO; To better understand this logic, I drew a flow chart:
Yes, this is the basic logic of what we call Server Side Rendering, which is SSR (Server Side Rendering);
The problem of long white screen time is solved because the server returns the rendered static page and reloads the request SPA script in the static page when it is first loaded.
Basic principle: the content and data of the home page are generated into a static page before the user requests, and the script code of SPA is introduced. After the static page is rendered by the browser, SPA script application is requested, and the subsequent page interaction is still client rendering.
Understand the principle of it, that is, to the realm of tao and law, next, let us descend to the application level of the art and apparatus to feel;
The React framework corresponds to the Next. Js framework, and the Vue framework corresponds to the Nuxt.js framework. Of course, if you are not interested in these, you can also implement an SSR server application. I wrote one myself before, if you are interested, want to see my implementation of the code, you can leave a message to me, back to make a tutorial sent;
Take React’s Next. Js as an example to get a feel for server rendering.
Next, js framework
Chinese official website homepage, has been introduced very clearly: www.nextjs.cn/
The basic application
Install the deployment
Project installation command: NPX create-next-app or NPM init next-app my-next-project
Run the NPM run dev command to start the project
You can also view the script configuration in the./package.json file
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
Copy the code
These scripts involve different stages of application development:
-
Dev – Run next dev to start next.js in development mode
-
Build – Run next Build to build the application for production
-
Start – Running next start will start the next. Js production server
Check out our application at http://localhost:3000.
Page routing
In next.js, pages are Reac components placed in the Pages folder, as defined by the framework;
Components need to be exported by default; React is not needed in component files; The page address is corresponding to the file address;
A page is associated with a route based on its file name. For example, pages/about.js is mapped to /about.
Create an abou.js in the Pages directory of your project.
Fill the./pages/about.js file with the following:
Import react from 'react' class AboutPage extends React.Component {render(){return <h3>class Component -- About Page</h3> } } export default AboutPageCopy the code
React function AboutPage(){return <h3> function Component -- AboutPage </h3>} export default AboutPageCopy the code
Page jump
By default, the Link component uses Javascript for page jumps, that is, spa-style jumps. If Javascript is disabled in the browser, the Link component should not add attributes other than href. The Link component automatically optimizes the application for best performance through prefetching (in production) functionality
React function AboutPage() {return (<div> {/* Link must write a tag, <Link href="/list"><a>Go to list Page</a></Link> <h3>Function Component</h3> </div>)} export default AboutPage</pre>Copy the code
Static resource
The public folder in the application root is used to hold static resources; PNG public/ CSS /style. CSS ->/ CSS /style.css
Import React from 'React' class ListPage extends React.Component {render(){return <div> <h3>ListPage</h3> {/* */} <img src="/img/1.png" /> </div> } } export default ListPage</pre>Copy the code
CSS styles
Built-in styled – JSX
Github.com/vercel/styl…
Soft-jsx is built into next.js, which is a CSS-in-JS library that allows writing CSS in the React component. CSS acts only inside the current component;
import React from 'react' class ListPage extends React.Component { render(){ return <div> <h3 >ListPage</h3> <p </p> <style JSX > {'. Pra {color: red; } `} </style> </div> } } export default ListPage</pre>Copy the code
CSS module
By using the CSS module function, the CSS styles of components are allowed to be written in a separate CSS file. The name of the CSS module convention style file must be: component file name.module.css
Create the./pages/list.module. CSS file and fill in the following contents:
.prag{ color:brown; font-size: 20px; } import React from 'React' import ListStyle from './list.module. CSS 'class ListPage extends React.Component { Render (){return <div> <h3 >ListPage</h3> {/* use style */} <p className={liststyle. prag}> export default ListPage</pre>Copy the code
Global style file
1: create a _app.js file in the pages folder (the file name is fixed) 2: create a styles folder in the root directory and create global. CSS in it 3: import global. CSS in _app.js
Styles in global.css will take effect globally
The contents of the /pages/_app.js file are as follows:
import '.. // styles/globals. CSS '// fixed code function MyApp({Component, pageProps}) {return <Component {... pageProps} /> } export default MyAppCopy the code
In the new version of the framework, has helped us to do a good job of the relevant content and files and code
Server-side rendering methods
GetServerSideProps () this method is a server-side rendering method suitable for applications where page data is changing in real time; The getServerSideProps() method takes a parameter that is the current HTTP client request object;
Import React from 'React' class ListPage extends React.Component {render(){return <div> <h3 >ListPage</h3> < H4 > Server data: < / h4 > {/ * class components display data content * /} < p > {this. Props. Data [0]. Name} < / p > < / div >}} / / / / function component/function/ListPage ({data}) {/ / Return (/ / < div > / / < h3 > ListPage < / h3 > / / < h4 > server data: < / h4 > / / {/ * class components display data content * /} / / < p > {data [1]. The name} < / p > < / div > / / / / /} / / the Node implementation of environment / / file reading and writing, database links, // export Async function getStaticProps(){export async function getServerSideProps(){const res = await fetch('http://localhost:80/'); const backData = await res.json(); const data = JSON.parse(backData); console.log(data); return { props:{data} } } export default ListPageCopy the code
Project construction and operation
NPM Run Build
Start project: NPM run start
Static site generation
Next. Js provides not only server-side rendering, but also static site generation solutions;
Static Site generation (also known as SSG (Static Site Generators)) is a Static file generation scheme for all pages used in an application.
Next official recommendation in most cases to use static site generation, static site generation scheme, more suitable for CDN, cache, content data unchanged pages, such as: publicity pages, blog articles, help documents, news pages, e-commerce product list and many other application scenarios;
GetStaticProps and getStaticPaths in next. js are static site generation; Is the method of generating HTML at build time, and each subsequent request shares the HTML generated at build time;
Next. Js recommends static generation for most pages because pages are pre-generated, built once, reused repeatedly, and accessed quickly. Server-side rendering access is not as fast as static generation, but because each request will be re-rendered, it is suitable for pages with frequently updated data or pages whose content changes with requests;
In next. Js, static generation is divided into two cases: no data and data; If the component does not need to fetch data elsewhere, it is generated statically by default. If the component needs to fetch data elsewhere, at build time, next.js will pre-fetch the data the component needs and then generate the component statically
For comparison, the development environment does not package static files, while the production environment packages static files by default
image-20210202210535010.png
So what do you do when you have data?
There is static generation of data
GetStaticProps () This method is officially translated as static generation. Components are pre-compiled into HTML files, and the entire HTML file is responded to the client, so as to achieve the purpose of pre-rendering.
The getStaticProps() method is an asynchronous method that executes in a Node environment (at build time), so it can do file reads and writes, database links, network communications, and more
For the use of this method, see demo:
Import React from 'React' import Axios from "Axios" // Class ListPage extends React.Component {render(){return <div> <h3 >ListPage</h3> <h4> Server data: < / h4 > {/ * class components display data content * /} < p > {this. Props. Data [0]. Name} < / p > < / div >}} / / / / function component/function/ListPage ({data}) {/ / Return (/ / < div > / / < h3 > ListPage < / h3 > / / < h4 > server data: < / h4 > / / {/ * class components display data content * /} / / < p > {data [1]. The name} < / p > < / div > / / / / /} / / the Node implementation of environment / / file reading and writing, database links, Export Async function getStaticProps(){const d3 = await axios.get ('http://localhost:80/'); const data = JSON.parse(d3.data); Console. log(data) // The value of the Props property returned is passed to the component return {Props :{data}}} export default ListPageCopy the code
The getStaticProps method must return an object within which the props property is passed to the component.
GetStaticPaths () This method is also statically generated. This method is used with getStaticProps to generate different static pages for different request parameters. The code file must be stored in a directory and the file name of the code file must be in the form of an optional file name, such as \ Pages \props\[id].js. When the project is built, Next will generate different static files based on different ID values, as shown in the following code
Import React from 'React' import Axios from "Axios" // Class ListPage extends React.Component {render() {return <div> <h3 >ListPage - Class</h3> <p>{this.props. Backdata. name}</p> </div>}} // Generate a static page based on the client parameters export Async function Paths: [{params: {id: "1"}}, {params: {id: "2"}}], fallback: False}} // Automatically call the current method, passing in the client arguments; Export Async function getStaticProps({params}) {const d3 = await Axios.get('http://localhost:80/'); const data = JSON.parse(d3.data); Console. log(params) // Loop server data, get for (let I = 0; i < data.length; I ++) {// console.log(data[I].id) if (params.id == data[I].id) {const backData = data[I]; return { props: { backData } } } } } export default ListPageCopy the code
After the final build, different static pages are generated:
image-20210205151341092.png
Static Site Export
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"export": "next build && next export"
},
Copy the code
Run the NPM run export command to build and export data, and generate the OUT folder to obtain static site resources.
image-20210205151648214.png
In addition, there is the SSG static site generation solution for React: Gatsby www.gatsbyjs.cn/. If you are interested, check it out for yourself
Of course, you React have it, how could I Vue not: Gridsome www.gridsome.cn/
Reference:
React 16 Loading performance Optimization Guide
H5 performance optimization for front-end engineering
How to solve the problem of slow loading on the first screen of SPA (single-page application)?