The JS framework I have used for the past year is nex.js. Although this framework has a great experience in front and back end isomorphism, it still causes bad user experience problems such as page jump lag and rendering blocking when the page JS file is too large and the preload is too large. Since I didn’t know how the framework worked, I didn’t know how to optimize it. Before the Lunar New Year, the construction site is less so a little research.

First question: Why does Next-js, which claims to be homogenous, get stuck?

The specific lifecycle hook function getInitialProps in nex.js will determine whether the browser is rendering the page for the first time. If so, the server will render the page, and if not, the client will render the page. When the page is rendered for the first time, it loads the Commons.xxxxx. js file, which is packed with React.js, next. Js and the associated framework code. This file is relatively large, usually more than 180KB. In terms of file size alone, this is not a big file, and you can use the next. Js preload mechanism to put the file size above 300KB. But once this file blocks the rendering of the page until commons.xxxxx.js is loaded, there is a problem.

The packaging tool used in Next7 is WebPack4, which has a silly mechanism for the packaging and loading process (or maybe it’s just my opinion). Any React DOM that has a style bound to it is not rendered on the server, but is packaged and extracted into a small JS file. After loadingcommons.xxxxx. js, load the JS to render the DOM and inline style to the HTML. This is partly responsible for the failure of the SSR in the first rendering of Next-.js, and even worse, the lag.

Some people might say, well, don’t write inline style. But the truth is that with a lot of background data dynamically rendering pages and user-defined pages, it’s impossible to write a bunch of classnames instead of inline styles altogether.

So we have to figure out how to make sure that the inline style React DOM is thrown into the background when the page is first rendered, rather than having commons.xxxxx.js pop up.

To solve the last problem, first understand how nex.js renders the page.

In the rules of nex.js, all page level code is written in the Pages folder, such as /pages/home:

export default() = > (<div>You see what? This is the home page</div>)
Copy the code

The Document component of the framework already helps developers to configure the and tags of traditional HTML files as shells for static resources. The Document component has a renderPage() method that synchronizes the code in the Pages folder and its external renderings to the browser if the code is working correctly. If you want to customize the Document component, just add the /pages/_document.js file.

RenderPage () is essentially a callback function that does only one thing: execute the React source rendering logic and synchronously load it into the Document component of nex.js to form a DOM node.

import Document, { Head, Main, NextScript } from 'next/document'

export default class MyDocument extends Document {
  static getInitialProps ({ renderPage }) {
    RenderPage () is in the nex.js specific lifecycle function getInitialProps.
    return renderPage();
  }

  render () {    
    return (
      <html>
        <Head>
          <title>Never seen a clickbait?</title>
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>)}}Copy the code

Server-side rendering style

In order to render the style server-side, we need to do two things first:

  1. When the page first loads, the so-called SSR. Allows the renderPage method to parse the React Dom on the server side, leaving HTML as HTML and CSS as CSS.

  2. Let the Document component update when the page switch, so that different pages can load their own script,style.


The emergence of a solution

Styled – Components are introduced, and have exceeded 10,000 stars on Github so far. It was designed to render a single ServerStyleSheet at the same time as the server rendering. And then we feed this ServerStyleSheet into the React DOM tree. It basically does two things:

  1. The components ofstylesPull away to<style>In the label;
  2. the<style>The label on the<head>In the

Here’s how to use a ServerStyleSheet correctly:

  import { ServerStyleSheet } from "styled-components";

  static getInitialProps ({ renderPage }) {
    const sheet = new ServerStyleSheet()
    const transform = (App) = > {
      returnsheet.collectStyles(<App />); } const styleTags = sheet.getStyleElement() const page = renderPage(transform); return { ... page, styleTags }; } render(){return(< HTML lang=" zh-hans "> <Head> width=device-width" /> <meta name="description" content="Kanseefoil"/> <link rel="shortcut icon" href="/static/favicon.ico"></link> {this.props.styleTags} </Head> </html> ); }Copy the code

The code above perfectly demonstrates how to extract inline styles from the DOM and render them using the method, so how to package and parse the React DOM and give the server a “pure, clean, and unspotless” DOM?

In this case, the Babel-Plugin-Styled – Components package should be used for parsing in Babel.

The code is as follows:

{
    "presets": [
        "next/babel"]."plugins": [["styled-components", { "ssr": true."displayName": true."preprocess": false}}]]Copy the code

At this point, go to the next. Js page and you will find that the guy, the scene rendering speed is whooshing. As for commons.xxxxx.js, which is responsible for the front-end logic, you can load it quietly and slowly.