Intensive reading of React Conf 2019 - Day1

Keywords: Javascript React git github TypeScript

1 Introduction

React Conf 2019 In October this year, the content quality is still as high as before. If you want to learn more about the front-end or React, this conference must not be missed.

I hope that the front-end intensive reading will become a preacher on your way to learning and growth, so this intensive reading will introduce the relevant content of React Conf 2019 - Day1.

In general, React Conf's content vision this year is broader. It not only includes technical content, but also promotes public welfare, extends to mobile terminals and back ends, and finally summarizes and prospects the development of web.

The front-end world is becoming more and more complex, we can see that everyone is full of hope for the future, and the never-ending spirit of exploration is the main theme of this conference.

2 Overview & Intensive Reading

There are more ideas and designs in this session of the conference, and less specific contents in the implementation layer, because the industry leaders need to lead the norms, while the real technical value lies in the thinking model and algorithm, and it is not difficult to realize it after understanding the problem-solving ideas.

Developer experience and user experience

  • Developer experience: DX (development experience)
  • User experience: UX (user experience)

Technical people always focus on DX and UX. Generally speaking, optimizing DX will improve UX. This is because a technical innovation to solve the developer experience will also upgrade the user experience. At least, it will give developers a better mood and more time to make good products.

How to optimize the developer experience?

Easy to get started

React is really committed to solving this problem, because react is actually a developer bridge. No matter you develop web, ios or SCM, you can achieve it through a set of unified syntax. React is a protocol standard (it will be more tactful to read the chapter of react adjuster). React is like HTML, but react can not only build HTML applications, but it wants to build everything.

Efficient development

React solves the problems of debugging and tools so that developers can complete their work more efficiently, which is also an important part of the developer experience.

elastic

The program written by React has good maintainability, including data-driven, modularization and other features, which are designed to better serve teams of different sizes.

For UX problems, React also has Concurrent mode, suspend and other solutions.

Although React is not perfect, we can see that React is committed to solving the goals and effects of DX and UX. Better DX and UX must be the future development trend of front-end technology.

Style scheme

Facebook uses CSS in JS, and this year's React conf offers a technical solution to reduce the size of 413 kb style files to 74 KB!

Step by step, start with the usage:

const styles = stylex.create({
  blue: { color: "blue" },
  red: { color: "red" }
});

function MyComponent(props) {
  return <span className={styles("blue", "red")}>I'm red now!</span>;
}

The above is the writing method of this scheme. Create the style through stylex.create, and use the style through styles().

Theme scheme

If you use CSS variables to define a theme, the skinning can be easily determined by the outermost class:

.old-school-theme {
  --link-text: blue;
}

.text-link {
  color: var(--link-text);
}

The specific value of font color is determined by the outer class, so the outer class can control the style of all sub elements:

<div class="old-school-theme">
  <a class="text-link" href="...">
    I'm blue!
  </a>
</div>

Encapsulating it as a React component does not require JS capabilities such as context, but just a layer of class.

function ThemeProvider({ children, theme }) {
  return <div className={themes[theme]}>{children}</div>;
}

Icon scheme

Here is the svg code given by the designer:

<svg viewBox="0 0 100 100">
  <path d="M9 25C8 25 8..." />
</svg>

Package it as a React component:

function SettingsIcon(props) {
  return (
    <SVGIcon viewBox="0 0 100 100" {...props}>
      <path d="M9 25C8 25 8..." />
    </SVGIcon>
  );
}

Combined with the theme scheme mentioned above, you can control the theme color of svg.

const styles = stylex.create({
  primary: { fill: "var(--primary-icon)" },
  gighlight: { fill: "var(--highlight-icon)" }
});

function SVGIcon(color, ...props) {
  return (
    <svg>
      {...props}
      className={styles({
        primary: color === "primary",
        highlight: color === "highlight"
      })}
      {children}
    </svg>
  );
}

The secret of reducing style size

const styles = stylex.create({
  blue: { color: "blue" },
  default: { color: "red", fontSize: 16 }
});

function MyComponent(props) {
  return <span className={styles("default", props.isBlue && "blue")} />;
}

For the above style file code, it will be compiled into three class es: c1, c2 and c3

.c1 {
  color: blue;
}
.c2 {
  color: red;
}
.c3 {
  font-size: 16px;
}

Unexpectedly, instead of generating corresponding classes based on blue and default, what's the benefit of generating classes based on actual style values?

The first is the loading order. The order in which the class takes effect is related to the loading order. The class generated according to the style value can precisely control the loading order of the style, so that it corresponds to the writing order:

// The effect may be blue, not red
<div className="blue red" />

// The effect must be red, because CSS in JS has two styles in the final class arrangement, but the writing order leads to the highest priority,
// The invalid class will be abandoned when merging
<div className={styles('blue', 'red')} />

There will never be a headache about style coverage.

More importantly, as the number of style files increases, the total number of classes decreases. This is because the attributes covered by the new class may have been written and generated by other classes. In this case, the class generated by the corresponding attribute will be reused directly instead of generating a new one:

<Component1 className=".class1"/>
<Component2 className=".class2"/>
.class1 {
  background-color: mediumseagreen;
  cursor: default;
  margin-left: 0px;
}
.class2 {
  background-color: thistle;
  cursor: default;
  justify-self: flex-start;
  margin-left: 0px;
}

As shown in this Demo, there are many attributes defined repeatedly in class1 and class2 under normal circumstances, but in the scheme of CSS in JS, the compiled effect is equivalent to reusing and disassembling class:

<Component1 classNames=".classA .classC .classD">

<Component2 classNames=".classA .classN .classD .classE">
.classA {
  cursor: default;
}
.classB {
  background-color: mediumseagreen;
}
.classC {
  background-color: thistle;
}
.classD {
  margin-left: 0px;
}
.classE {
  justify-self: flex-start;
}

This method not only saves space, but also automatically calculates style priority to avoid conflicts, and reduces the size of 413 kb style file to 74 KB.

Font size scheme

The advantage of REM is the relative font size. Using rem as a unit can easily switch the font size of web pages.

But the problem is that industrial design is used to px as a unit now, so a new compilation scheme is produced: px is automatically converted to rem in the compilation phase.

This is equivalent to making the font size in px follow the font size of the root node.

code detection

Static detection type error, spelling error, browser compatibility problem.

Online detection of dom node elements, such as whether there is accessibility, such as alternative copy aria label.

Increase loading speed

The loading process of ordinary web pages is as follows:

First load the code, and then render the page. At the same time, send a data retrieval request, and then render the real data after the retrieval is completed.

So how to improve this situation? The first is prefetch, which resolves the request in advance and fetches the data at the same time when the script is loaded, which can save a lot of time:

Can the downloaded code be split again? Note that not all code works for UI rendering. We can divide the modules into ImportForDisplay and importForAfterDisplay:

In this way, the UI related code can be loaded first, and the rest of the logic code can be loaded after the page is displayed:

In this way, the source code can be loaded in sections and rendered in sections:

This is also true for fetching. Not all fetching is necessary during the initial rendering phase. You can mark the data that can be delayed to load through the @ defer attribute of relay:

fragment ProfileData on User {
  classNameprofile_picture { ... }

  ...AdditionalData @defer
}

This access can also be segmented. The first screen data will be loaded first:

With relay, you can also split code in a data-driven way:

... on Post {
  ... on PhotoPost {
    @module('PhotoComponent.js')
    photo_data
  }

  ... on VideoPost {
    @module('VideoComponent.js')
    video_data
  }

  ... on SongPost {
    @module('SongComponent.js')
    song_data
  }
}

In this way, the first screen data will only be loaded as needed, and the request time can be shortened again:

As you can see, combining with relay can further optimize the load performance.

Loading experience

You can dynamically load components with react.suspend and React.lazy. Specify the occupation map of the element through fallback to improve the loading experience:

<React.Suspense fallback={<MyPlaceholder />}>
  <Post>
    <Header />
    <Body />
    <Reactions />
    <Comments />
  </Post>
</React.Suspense>

Suspend can be nested. Resources will be loaded in nesting order to ensure a natural visual consistency.

Intelligent document

We are familiar with the automatic generation of documents by parsing Markdown, and there are many ready-made tools to use, but the interesting thing about the shared document system is that it can dynamically modify the source code and take effect in real time.

In addition, Typescript + MonacoEditor is also used to do syntax detection and API automatic prompt on Web pages. This document experience has risen to a higher level.

Although the technical implementation details are not disclosed, the hot update operation seems to put the compilation work in the browser web worker. If this implementation method is adopted, the principle and CodeSandbox implementation principle Similar.

GraphQL and Stuff

This section of Amway uses the interface to automatically generate Typescript code to improve the efficiency of front and back end joint debugging, such as go2dts.

Our team has also opened an automatic generation tool of Typescript interface based on swagger pont , welcome to.

React Reconciler

This is the most knowledge intensive section, which describes how to use React Reconclier.

React reconciler can create a react renderer based on any platform, or it can be understood that a custom react DOM can be created through react reconciler.

For example, in the following example, we try to render the React component with the custom function React dommini:

import React from "react";
import logo from "./logo.svg";
import ReactDOMMini from "./react-dom-mini";
import "./App.css";

function App() {
  const [showLogo, setShowLogo] = React.useState(true);

  let [color, setColor] = React.useState("red");
  React.useEffect(() => {
    let colors = ["red", "green", "blue"];
    let i = 0;
    let interval = setInterval(() => {
      i++;
      setColor(colors[i % 3]);
    }, 1000);

    return () => clearInterval(interval);
  });

  return (
    <div
      className="App"
      onClick={() => {
        setShowLogo(show => !show);
      }}
    >
      <header className="App-header">
        {showLogo && <img src={logo} className="App-logo" alt="logo /" />}
        // Self generated grammar
        <p bgColor={color}>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React{" "}
        </a>
      </header>
    </div>
  );
}

ReactDOMMini.render(<App />, codument.getElementById("root"));

ReactDOMMini is a custom component rendering function generated by ReactReconciler. The following is the complete code:

import ReactReconciler from "react-reconciler";

const reconciler = ReactReconciler({
  createInstance(
    type,
    props,
    rootContainerInstance,
    hostContext,
    internalInstanceHandle
  ) {
    const el = document.createElement(type);

    ["alt", "className", "href", "rel", "src", "target"].forEach(key => {
      if (props[key]) {
        el[key] = props[key];
      }
    });

    // React event agent
    if (props.onClick) {
      el.addEventListener("click", props.onClick);
    }

    // Self created api bgColor
    if (props.bgColor) {
      el.style.backgroundColor = props.bgColor;
    }

    return el;
  },

  createTextInstance(
    text,
    rootContainerInstance,
    hostContext,
    internalInstanceHandle
  ) {
    return document.createTextNode(text);
  },

  appendChildToContainer(container, child) {
    container.appendChild(child);
  },
  appendChild(parent, child) {
    parent.appendChild(child);
  },
  appendInitialChild(parent, child) {
    parent.appendChild(child);
  },

  removeChildFromContainer(container, child) {
    container.removeChild(child);
  },
  removeChild(parent, child) {
    parent.removeChild(child);
  },
  insertInContainerBefore(container, child, before) {
    container.insertBefore(child, before);
  },
  insertBefore(parent, child, before) {
    parent.insertBefore(child, before);
  },

  prepareUpdate(
    instance,
    type,
    oldProps,
    newProps,
    rootContainerInstance,
    currentHostContext
  ) {
    let payload;
    if (oldProps.bgColor !== newProps.bgColor) {
      payload = { newBgCOlor: newProps.bgColor };
    }
    return payload;
  },
  commitUpdate(
    instance,
    updatePayload,
    type,
    oldProps,
    newProps,
    finishedWork
  ) {
    if (updatePayload.newBgColor) {
      instance.style.backgroundColor = updatePayload.newBgColor;
    }
  }
});

const ReactDOMMini = {
  render(wahtToRender, div) {
    const container = reconciler.createContainer(div, false, false);
    reconciler.updateContainer(whatToRender, container, null, null);
  }
};

export default ReactDOMMini;

The author disassembles the following instructions:

The reason that React has cross platform characteristics is that its rendering function, React reconciler, only cares about how to organize the relationship between components, but not the specific implementation, so it will expose a series of callback functions.

Create examples

Because the essence of React component is a description, i.e. tag + attribute, Reconciler doesn't care how the element is created. It needs to get the basic attribute of the component through createInstance, which is implemented in the Web platform using DOM API:

createInstance(
    type,
    props,
    rootContainerInstance,
    hostContext,
    internalInstanceHandle
  ) {
    const el = document.createElement(type);

    ["alt", "className", "href", "rel", "src", "target"].forEach(key => {
      if (props[key]) {
        el[key] = props[key];
      }
    });

    // React event agent
    if (props.onClick) {
      el.addEventListener("click", props.onClick);
    }

    // Self created api bgColor
    if (props.bgColor) {
      el.style.backgroundColor = props.bgColor;
    }

    return el;
  }

The reason that React acts as a layer of proxy for DOM events is that all functions of JSX are not really passed to DOM, but are implemented by proxy in a similar way as el.addEventListener("click", props.onClick).

To customize this function, we can even create a special syntax such as bgColor, as long as the parsing engine implements the Handler of this syntax.

In addition, there are callback functions to create and delete instances. We need to re implement them by using the DOM platform API, so that we can not only achieve compatibility with browser API, but also connect to non WEB platforms such as react native.

Update components

Only when prepareUpdate and commitUpdate are implemented can component update be completed.

The payload returned by prepareUpdate is received by the commitUpdate function and determines how to update the instance node according to the received information. This instance node is the object returned by the createInstance callback function, so if the instance returned in the WEB environment is DOMInstance, the DOM API will be used for all subsequent operations.

To sum up: react mainly generates AST with business meaning with platform independent syntax, and the rendering function generated by react reconciler can analyze this AST, and provide a series of callback functions to achieve complete UI rendering function. React DOM is also written based on react reconciler now.

Icon volume optimization

Through optimization, the Facebook team reduced the icon size from 4046.05KB to 132.95kb, reducing the volume by an amazing 96.7%, accounting for 19.6% of the total volume!

The implementation is simple. Here is the code used by the original Icon:

<FontAwesomeIcon icon="coffee" />
<Icon icon={["fab", "twitter"]} />
<Button leftIcon="user" />
<FeatureGroup.Item icon="info" />
<FeatureGroup.Item icon={["fail", "info"]} />

During compilation, through AST analysis, all string references are replaced by icon instance references, and web pack's tree sharing function is used to load on demand, thus deleting unused icons.

import {faCoffee,faInfo,faUser} from "@fontawesome/free-solid-svg-icons"
import {faTwitter} from '@fontawesome/free-brands-svg-icons'
import {faInfo as faInfoFal} from '@fontawesome/pro-light-svg-icons'

<FontAwesomeIcon icon={faCoffee} />
<Icon icon={faTwitter} />
<Button leftIcon={faUser} />
<FeatureGroup.Item icon={faInfo} />
<FeatureGroup.Item icon={faInfoFal} />

Replacement tool The link of is released, the students who are interested can click in to learn more.

This also shows that iconFont is doomed to be eliminated in a sense, because font files cannot be loaded on demand at present, and only all projects using SVG icons can use this optimization.

Git & Github

This section introduces the basic Git knowledge and Github usage. The author skips over the water comparison part and lists two points that you may not know:

Intervention in major language testing of Github project

If the code you submit contains many auto generated files, it is possible that the language you actually use will not be parsed into the main language by Github. At this time, you can ignore the detection of the specified folder through the. gitattributes file:

static/* linguist-vendored

In this way, the statistics of the proportion of language files will ignore the static / folder.

Tips for Git hooks

Here are some enlightening points. We can do something with Git hooks:

  • Block commit to master.
  • Perform the prettier / eslint / jet test before commit ting.
  • Check code specifications, merge conflicts, and check whether there are large files.
  • After the commit is successful, give a prompt or record to the log.

But Git hooks still has limitations:

  • It is easy to be bypassed: - no verify -- no merge -- no checkout -- force.
  • Local hooks could not be submitted, resulting in different project development rules.
  • CI, server branch protection, Code Review cannot be replaced.

You can imagine that in the WebIDE environment, you can disable detection bypass through the custom git command, and naturally solve the second inconsistency problem.

GraphQL + Typescript

There is no type support for GraphQL. It is very painful to create a type file manually:

interface GetArticleData {
  getArticle: {
    id: number;
    title: string;
  };
}

const query = graphql(gql`
  query getArticle {
    article {
      id
      title
    }
  }
`);

apolloClient.query<GetArticleData>(query);

If the same code is maintained in two places, it will bring problems. We can use a library such as typed graphqlify to solve the type problems:

import { params, types, query } from "typed-graphqlify";

const getArticleQuery = {
  article: params({
    id: types.number,
    title: types.string
  })
};

const gqlString = query("getUser", getUserQuery);

You can automatically generate GQLString and get Typescript type as long as you define it once.

React document internationalization

Even Google translation is not very reliable, international documents still rely on human flesh, Nat Alison Using Github to fully mobilize the strength of people from all countries, we have jointly built international warehouses under react JS group.

The naming rules of international warehouses are reactjs/xx.reactjs.org. For example, the international warehouses in simplified Chinese are: https://github.com/reactjs/zh...

From the readme of the warehouse, you can see that the maintenance rules are as follows:

  • Please fork this warehouse.
  • Based on the master branch in the warehouse after fork, pull a new branch (named by yourself).
  • Translate (proofread) your selected articles and submit them to the new branch.
  • At this time, submit the Pull Request to the warehouse.
  • There will be a special person to Review the Pull Request. When more than two people pass the Pull Request, your translation will be incorporated into the warehouse.
  • Delete the branch you created (if you continue to participate, refer to the synchronization process).

After that, pull the latest code from React official document project regularly to keep the document updated synchronously.

Do you need redux?

There is no new idea about the topic of data flow at present, but this time React Conf's summary of data flow is quite sincere. It summarizes the following points:

  1. Global data flow is not necessary at present, such as Redux, but it cannot be used at all, at least when the global state is more complex.
  2. Don't use only one data flow scheme. It's better to determine the scheme according to the scope of the state.
  3. Engineering technology is different from science. There is no best plan in the engineering world, only better plan.
  4. Even if you have a perfect plan, don't stop learning. There will always be new knowledge.

web History

It's a wonderful speech, but there's not much new content. One of the more touching points is that the previous web address corresponds to a specific file on the server disk, such as the early php application. Now the back end is no longer file-based but service-oriented. This layer of abstraction makes the server independent of the file structure, and can build more complex dynamic logic, and also supports the front and back Technical scheme of end separation.

3 Summary

This React Conf allows us to see more possibilities in the front end. We should not only focus on the details of technology implementation, but also on industry standards and team vision.

The vision of React team is to make React all inclusive, improve the development experience of global developers, and enhance the user experience of global products. Based on this goal, React Conf can not only contain DOM Diff, Reconciler and other technical details, but also show how React can help global developers, how to let these developers help users, and how to promote the evolution of industry standards How to let React break the barriers of national boundaries and languages.

Compared with many dry goods of other front-end conferences, React Conf seems to have a complex theme, but this is the embodiment of human feelings. I believe that only with a higher mission vision, the technical team that sincerely helps others can go further.

Discussion address: Intensive reading of React Conf 2019 - Day1 · issue · 214 · DT Fe / weekly

If you want to participate in the discussion, please click here , new theme every week, released on weekend or Monday. Front end intensive reading - help you to select reliable content.

Focus on front-end intensive reading WeChat public address

<img width=200 src="https://img.alicdn.com/tfs/TB...;>

Copyright notice: Free Reprint - non commercial - non derivative - keep signature( Creative sharing 3.0 License)

Posted by AQHost on Sun, 03 Nov 2019 17:04:45 -0800