Where did you make your request?

Fetching page data via Ajax is a common operation for a pure front-end page. React there have been a lot of requests for componentWillMount and componentDidMount on the web. The official recommendation is the latter:

ComponentDidMount () is called immediately after the component is mounted (inserted into the DOM tree). Initialization dependent on DOM nodes should be placed here. This is a good place to instantiate a request to get data over the network.

But here we’re talking about where the request is the fastest. While this issue is not the purpose of this article, I would argue that a request for componentWillMount(deprecated) or constructor is faster than a request for componentDidMount (deprecated). The time difference between the two cycles depends on the complexity of the application, and the same is true for VUE.

So my argument is early, early request, early access to interface data. At this time, there will be children ask, how do you know that the earlier you call the request method, the request really will be sent earlier, in case it is to wait for the js main thread to execute after sending. Let’s open Chrome’s developer tools.

In order to make the effect more obvious, we actively increase the js execution time to make the difference more large and ignore the impact of the runtime environment. Let’s define a time-consuming Fibonacci method:

function fibonacci(n){
    if(n==0) return 0
    else if(n==1) return 1
    else return fibonacci(n- 1) + fibonacci(n2 -)}Copy the code

To do a control experiment, place the request before or after the method here:

/ / A group
getApiData();
fibonacci(41); // How far can your computer go?

/ / group B
fibonacci(41);
getApiData();
Copy the code

Group A:

You can see here that the request started at 605ms, and the meaning of all the metrics here can be seen here -> Google website

Group B:

You can see my computer running Fibonacci for almost 2 seconds. The result shows that the request time is indeed delayed, 605ms -> 2.43s. Therefore, the earlier you send a request, the earlier you request the server.

I’m making a request outside the circle

So back to our question. ComponentWillMount is faster than componentDidMount. Like outside the React component?

import React from 'react';

getApiData() / / here
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>; }}Copy the code

Theoretically, it’s faster, but it’s usually not obvious. Import React from ‘React’. Remember that our request method runs after the various libraries and frameworks you’ve introduced, which also takes a lot of time. So let’s just go straight back to the premise. At this time there are children ask: that put where? Here we can separate the request method into a package called network.ts, for example, and then add this entry to the Webpack and end up with a different JS file.

entry: {
    main: [path.resolve(__dirname, `./src/index.tsx`)].network: [path.resolve(__dirname, `./src/network.ts`)]}Copy the code

Then put the js of the network request in front of the application, so that the request can be made without even waiting for the JS of our application to finish loading.

<script
  src="<%= htmlWebpackPlugin.files.chunks.main && htmlWebpackPlugin.files.chunks.network.entry %>"
  type="text/javascript"
></script>
<script
  src="<%= htmlWebpackPlugin.files.chunks.main && htmlWebpackPlugin.files.chunks.main.entry %>"
  type="text/javascript"
></script>
Copy the code

Of course, network.js may also use some libraries to assist in the request process, and may be used in the main application. At this time you can use webpack to hit a public package. See here -> splitChunks for the configuration

optimization: {
  minimizer: [
    new TerserPlugin(),
    new OptimizeCssAssetsPlugin({}),
  ],
  splitChunks: {
    cacheGroups: {
      commons: {
        name: 'vendors'.chunks: 'all'.minChunks: 2,},},},}Copy the code

Then set up the public vendors on top. There are probably kids here who have a lot of questions: How do you get data from one packet to the other packet? This can be saved simply by using the Window global object. You might also ask: what if I load the component and the data doesn’t return? That’s fine, as long as we store the Promise object in the window instead of the data itself.

function getApiData() :Promise<any> // Customize a returnPromiseObject request function //network.ts
window.__request = getApiData();

// app.tsx
function getRequest() {
  if (window.__request) {
    const request = window.__request;
    window.__request = undefined;
    return request;
  }
  return getApiData();
}

getRequest().then(xxx)
Copy the code

So we’re done. What about the optimized data?

The second column shows how long it takes for the first screen to appear for an eight-quartile user (the median 8-bit version) on Android. You can see the end result is 400 milliseconds faster. If you watch carefully, you can see that the load event trigger in the first column has been pulled about 300ms behind. Why is this? Here we assume that my Ajax request blocks the load event, and the initial screen minus the load time is 700ms. Let’s assume that this is the request time, the first screen time is optimized for 400ms, and the optimized time is exactly the time when the JS and the request execute in parallel, 700-400 = 300. But I have no proof because the W3C specification only says that JS and CSS resources will affect my JSON data request and doesn’t mention it. I’ll just have to simulate a time-consuming request myself. But my experiments with Chrome and phones have shown no effect. Is the problem with the model or scenario? If you have an idea, you can post your opinion in the comments below. I will also add new research in the comments.

If you still want to advance the request time you can choose to use the client pre-request, which needs to work with the app to get your data before opening the web page. It would be nice if you could preload the webView. Here is a recommended baidu APP-Android H5 first screen optimization practice

Other optimization

If the front-end page is opened in the APP, HTML and JS can be downloaded to the APP in advance in the form of offline package without loading and obtaining. Visually, we can advance the time and user experience of the first frame by placing loading diagram or skeleton screen (as shown below) on HTML. It is highly recommended to use a skeleton screen. From a design perspective, it can help users analyze the interface structure in advance, prepare for the arrival of data, and give users the illusion that the page has been formed and is about to come out. Other optimization methods, of course, there are many here to recommend a H5 seconds open scheme daqo