1 the introduction

React Conf 2019 will be held in October, and the quality of content is as high as ever. If you want to learn more about the front end or React, this conference is a must.

Here’s how to learn and grow React Conf 2019-DAY1.

Overall, React Conf has expanded its content horizons to include not only technical content, but also public service promotion, mobile expansion, back-end expansion, and a summary and outlook for the Web.

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

2 Overview & Intensive reading

This session of the conference ideas, design content is more, the specific implementation layer content is less, because industry leaders need to lead the standard, and the real technical value lies in the thinking model and algorithm, to understand the topic ideas, it is not difficult to achieve it.

Developer experience vs. user experience

  • DX (Develop Experience)
  • User Experience: UX

The problems that tech people solve tend to revolve around DX and UX, and generally speaking, improving DX often leads to better UX, because a technological innovation that solves the developer experience often leads to better user experience, or at the very least, better mood and more time for developers to make good products.

How do you optimize the developer experience?

Easy to get started

React really tries to solve this problem, because React is essentially a developer bridge. Whether you’re developing for the Web, ios, or microcontrollers, you can do it with a unified syntax. React is a protocol standard (read the reactReconciler chapter). React is like HTML, but React doesn’t just build HTML applications. React wants to build everything.

The efficient development

React solves debugging and tool issues and allows developers to do their jobs more efficiently, which is an important part of the developer experience.

The elastic

React applications are maintainable, data-driven, modular, and designed to better serve teams of different sizes.

React also has Concurrent mode and Suspense solutions for UX problems.

Although React is not perfect, the goals and effects of React to solve DX and UX are obvious to all. Better DX and UX will definitely be the trend of the future development of front-end technology.

The style package

Facebook uses css-in-js, and this year’s React conf offers a technical solution that reduces the size of a style file from 413 KB to 74kb!

Walk through the scheme step by step, starting with 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>; }Copy the code

Here’s how this scenario is written, creating styles with stylex.create and using styles with styles().

Theme plan

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

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

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

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

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

To encapsulate it as a React component, you do not need JS capabilities such as context, but instead wrap a layer of class.

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

Icon scheme

Here is the SVG code from the designer:

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

Wrap it as a React component:

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

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> ); }Copy the code

The secret to 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")} />;
}
Copy the code

For the above style file code, it will compile to c1, C2, and C3 classes:

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

Surprisingly, instead of generating the corresponding class based on blue and default, the class is generated based on the actual style value. What is the benefit of this?

The order in which a class takes effect depends on the order in which it is loaded, and a class generated from a style value can precisely control the order in which it is loaded to correspond to the order in which it is written:

<div className="blue red" /> <div className="blue red" /> // Class <div className={styles('blue', 'red')} />Copy the code

You’ll never have a headache with style overwriting.

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 to and generated by other classes, and the corresponding class will be reused instead of being generated:

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

Class1 and class2 have a lot of repetitions in the normal case, as this Demo shows, but with csS-in-JS, the compiled effect is equivalent to reusing and disassembling the class:

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

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

This approach not only saves space, but also automatically prioritizes styles to avoid collisions and reduces the size of a 413 KB style file to 74kb.

Font size scheme

The advantage of REM is the relative font size, using REM as a unit can be very convenient to achieve a web page font size switch.

The problem is that industrial design is now used to px units, so a new compilation scheme has emerged: converting PX to REM automatically at compile time.

This means that the font size in px can be scaled to match the font size of the root node.

Code detection

Statically detect type errors, spelling errors, and browser compatibility issues.

Online detection of DOM node elements for issues such as accessibility, such as alternative copy aria-label.

Increase loading speed

The loading process of a normal web page looks like this:

The code is loaded, the page is rendered, and a fetch request is issued at the same time. The actual data can only be rendered after the fetch is complete.

So how can this situation be improved? The first is prefetch, which can save a lot of time by parsing the request in advance and fetching it while the script loads:

Can downloaded code be split again? Note that not all code is used for UI rendering, we can divide modules into ImportForDisplay and importForAfterDisplay:

This allows uI-related code to be loaded first, and the rest of the logic to be loaded after the page is displayed:

This allows source code to be loaded in segments and rendered in segments:

The same is true for fetches, not all fetches are necessary for the initial render phase. You can flag lazy-loaded data via relay’s feature @defer:

fragment ProfileData on User {
  classNameprofile_picture { ... }

  ...AdditionalData @defer
}
Copy the code

The data on the first screen will be loaded first:

Relay can also combine code splitting in a data-driven manner:

. on Post { ... on PhotoPost { @module('PhotoComponent.js') photo_data } ... on VideoPost { @module('VideoComponent.js') video_data } ... on SongPost { @module('SongComponent.js') song_data } }Copy the code

In this way, only the required part of the first screen data will be loaded on demand, and the request time can be reduced again:

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

Load experience

Components can be dynamically loaded in react. Suspense and react. lazy. The loading experience can be improved by specifying a placeholder map for elements via fallback:

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

Suspense can be nested and resources are loaded in a nested order, ensuring a natural visual continuity.

Intelligent documents

Automatic documentation generated by parsing Markdown is familiar, and there are plenty of tools out there, but the interesting part about this shared documentation system is that you can modify the source code dynamically and take effect in real time.

Not only that, but also use Typescript + MonacoEditor to do syntax detection and API auto-prompt on web pages, which takes the documentation experience to a new level.

Although the technical implementation details are not disclosed, from the operation of hot update, it seems that the compilation work is put in the browser Web worker. If it is implemented in this way, the principle is similar to the implementation principle of CodeSandbox.

GraphQL and Stuff

Amway uses the interface to automatically generate Typescript code to improve the efficiency of front – and back-end syncing, such as GO2DTS.

Our team also open source The Swagger-based Typescript interface automatic generation tool Pont, welcome to use.

React Reconciler

This is the most knowledge-dense section on how to use the React Reconclier.

React Reconclier can create React renderers based on any platform, and can also be understood as creating custom ReactDOM through React Reconclier.

For example, we tried to render the React component with the custom function ReactDOMMini:

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((a)= > {
    let colors = ["red"."green"."blue"];
    let i = 0;
    let interval = setInterval((a)= > {
      i++;
      setColor(colors[i % 3]);
    }, 1000);

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

  return (
    <div
      className="App"
      onClick={()= >{ setShowLogo(show => ! show); }} ><header className="App-header">
        {showLogo && <img src={logo} className="App-logo" alt="logo /" />} // Create your own syntax<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"));
Copy the code

ReactDOMMini is a custom component rendering function generated by ReactReconciler. Here 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);
    }

    // create 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;
Copy the code

The author disassembles the explanation:

React is cross-platform because its rendering function, ReactReconciler, only cares about how to organize relationships between components, not how to implement them, so it exposes a series of callback functions.

Create an instance

Since the React component is essentially a description, namely a Tag + attribute, it does not care how the Reconciler elements are created. The basic attributes of the component need to be obtained through createInstance and implemented on the Web platform using the 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);
    }

    // create API bgColor
    if (props.bgColor) {
      el.style.backgroundColor = props.bgColor;
    }

    return el;
  }
Copy the code

React proxies for DOM events because none of the JSX functions are actually passed through to the DOM. Instead, they are implemented in ways like el.addeventListener (“click”, props. OnClick).

By customizing this function, we can even create special syntax like bgColor, as long as the parsing engine implements the Handler for that syntax.

In addition, there are callback functions for creating and deleting instances, which need to be re-implemented using THE DOM platform API to achieve compatibility with browser apis and non-Web platforms such as React-Native.

Update the components

PrepareUpdate and commitUpdate are implemented to complete component updates.

The payload returned by prepareUpdate is received by the commitUpdate function, which decides how to update the instance node based on the received information. This instance node is the object returned by the createInstance callback, so if the instance returned in the WEB environment is DOMInstance, all subsequent operations use DOMAPI.

To sum up: React primarily generates an AST with business implications using platform-independent syntax, which can be parsed using rendering functions generated by react-Reconciler, and provides a series of callbacks for complete UI rendering. The React-DOM is now also written based on the React-Reconciler.

Icon volume optimization

The Facebook team optimized the icon to reduce its size from 4046.05KB to 132.95 KB, resulting in a whopping 96.7% reduction in volume, which is 19.6% of the total package size!

The implementation is very simple, here is the code used for the original icon:

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

During compilation, all string references are replaced with icon instance references by AST analysis, and the unused ICONS are removed using WebPack’s tree-shaking feature for on-demand loading.

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} />
Copy the code

There’s a link to the replacement tool, so if you’re interested, you can click there to learn more.

In a sense, iconFont is destined for obsoletion, as font files cannot currently be loaded on demand, and only projects that use all SVG ICONS can use this optimization.

Git & Github

This section introduces you to the basics of Git and Github usage. I’ll skip the comparison section and list two things you might not know about Git:

Intervention Github project major language detection

If your submitted code contains a lot of auto-generated files, and the language you’re actually using may not be resolved to the main language by Github, you can ignore the detection of the specified folder with the.gitAttributes file:

static/* linguist-vendored
Copy the code

Static/folder will be ignored in the language file ratio statistics.

Git hooks

Here are a few more enlightening things you can do with Git hooks:

  • Block submission to master.
  • Prettier/ESLint/jEST check before commit
  • Check for code specifications, merge conflicts, and large files.
  • After the commit succeeds, a message is displayed or logged.

But Git hooks still have limitations:

  • Easy to be circumvented: –no-verifuy –no-merge –no-checkout –force
  • Local hooks cannot be committed, resulting in potentially different project development rules.
  • Cannot replace CI, server branch protection, Code Review.

In the WebIDE environment, you can use custom git commands to prohibit detection bypassing, which naturally solves the problem of inconsistency in the second environment.

GraphQL + Typescript

GraphQL has no type support, so it would be a pain 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);
Copy the code

Having the same code maintained in two places is always a problem. We can use libraries such as typed graphqlify to solve type problems:

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

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

const gqlString = query("getUser", getUserQuery);
Copy the code

A single definition automatically generates GQLString and gets the Typescript type.

React Document Internationalization

Even Google Translate is not reliable, and international documents still rely on human flesh. Nat Alison made full use of Github to mobilize the power of people from all countries to jointly build an international warehouse under the ReactJS group.

Reactjs/xx.reactjs.org. For example, the name of an internationalized repository in Simplified Chinese is github.com/reactjs/zh-…

As you can see from the readme of the repository, the maintenance rules look like this:

  • Please fork the warehouse.
  • The master branch pulls a new branch (name your own) from the fork repository.
  • Translate (proofread) your selected articles and submit them to a new branch.
  • Submit the Pull Request to the repository.
  • Someone will Review the Pull Request. When more than two people pass the Pull Request, your translation will be merged into the warehouse.
  • Delete the branch you created (see the synchronization process if you continue to participate).

Periodically pull the latest code from the React documentation project to keep the document up to date.

Do you need redux?

There’s nothing new about data flows, but the React Conf talks about data flows in a very honest way.

  1. Global data flows are not required now, such as Redux, but they are not completely unavailable, at least when the global state is more complex.
  2. Instead of using just one data flow scheme, it is better to determine the scheme based on the scope of the state.
  3. In engineering, unlike science, there is no best solution, only a better solution.
  4. Don’t stop learning even if you have the perfect solution. There’s always something new.

Web history

It was a wonderful speech, but there was not much new content. The web address used to correspond to a specific file on the server disk. For example, in early PHP applications, the backend is now servitized rather than filendized. This layer of abstraction allows the server to get rid of the dependency on the file structure, build more complex dynamic logic, and support the technical solution of separating the front end from the back end.

3 summary

The React Conf opened our eyes to more possibilities on the front end, focusing not only on technical implementation details, but also on industry standards and team vision.

The React team’s vision is to make React all-encompassing, to enhance the development experience of developers around the world and to enhance the user experience of global products. With this goal in mind, React Conf naturally cannot just include technical details such as DOM Diff and Reconciler, It’s important to show how React helps developers around the world, how it helps users, how it helps industry standards evolve, and how React breaks down borders and language barriers.

Compared with other front-end conferences, React Conf seems to have a variety of topics, but it is the embodiment of humanistic feelings. I believe that only technical teams with a higher mission vision and sincerity to help others can go further.

React Conf 2019-day1 · Issue #214 · dt-fe/weekly

If you’d like to participate in the discussion, pleaseClick here to, with a new theme every week, released on weekends or Mondays. Front end Intensive Reading – Helps you filter the right content.

Pay attention to the front end of intensive reading wechat public account

Copyright Notice: Freely reproduced – Non-commercial – Non-derivative – Remain signed (Creative Commons 3.0 License)