preface

  • When it comes to react, the first scaffolding to use for newcomers is probably create-react-app (portal 👉create-react-app).
  • Create-react-app encapsulates webpack configuration, Lint configuration, Babel configuration, etcreact-scriptsThis ensures that the underlying dependencies can be upgraded and migrated smoothly without affecting the business project.
  • Create-react-app allows developers to personalize projects (through collaboration)react-app-rewiredThe use oryarn ejectModify the configuration after exposure).
  • The following describes some special configurations that I usually carry out on the project before business code development, which is beneficial to the later engineering development.

Initialize the project

  • Before using scaffolding, usenpmCommand to install scaffolding globally:
npm install -g create-react-app
Copy the code
  • After installation, scaffolding can be built:
create-react-app my-app
Copy the code
  • TypeScript is a superset of JavaScript types that can be compiled into pure JavaScript. To launch a new create-react-app project using TypeScript, run the following command:
create-react-app my-app --typescript
Copy the code
  • Note: The project configurations described below are for react + typescript projects.

Install the latest create-react app

  • When creating a project using the old create-React-app package, the console will give you the following prompt:
A template was not provided. This is likely because you're using an outdated version of create-react-app.
Please note that global installs of create-react-app are no longer supported.
Copy the code

Solution:

  • usenpm uninstall -g create-react-appUninstall the old version
  • usewhich create-react-appCommand to check whether the uninstallation is successful

If you prompt (/usr/local/bin/create-react-app) as I did, run rm -rf /usr/local/bin/create-react-app to remove this.

  • Install the new version:npm install -g create-react-app

react-scripts

  • This section is about react-scripts. If you are only interested in configuration, skip this section.

  • Create-react-app provides a layer of react-scripts on top of Webpack. On the one hand, create-React-app allows beginners who are not used to ESLint, Babel, and WebPack to focus only on component writing. On the other hand, the default options can be constantly updated and improved without affecting the business code.

  • As you can see, react-Scripts hides a lot of details upward by encapsulating some of the underlying configuration, leaving business developers to focus only on business code development.

  • Go to node_modules and see the react-scripts directory structure in create-react-app + typescript:

    • The scripts folder contains the development script and build script of the project, and the corresponding Webpack configuration is located in the Config folder.
  • There are three ways to modify these configurations:

    (1) Override the default Webpack configuration via react-app-rewired.

    (2) fork the corresponding react-scripts package and maintain the dependency package yourself.

    (3) Directly eject the entire configuration to be maintained in the business project. The disadvantage of this operation is that it is irreversible and cannot be hidden once the configuration file is exposed.

  • Because my skill is not enough, I use the third scheme.

  • First, enter the project directory:

cd my-app
Copy the code
  • exposedreact-scriptsPackage:
Yarn eject YARN Run v1.17.3 $react-scripts eject NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html ? Are you sure you want to eject? This action is permanent.  (y/N)Enter y
Copy the code
  • Generally use scaffolding to build the project after the use of the above command exposurereact-scriptsThe package. If you have installed other dependencies or changed other aspects of the project before usingyarn ejectAn error is reported when the command is executed:
This git repository has untracked files or uncommitted changes: Remove untracked files, stash or commit any changes, and try again. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! [email protected] eject: 'react-scripts eject' NPM ERR! Exit status 1 npm ERR! npm ERR! Failed at the [email protected] eject script.npm ERR! This is probably not a problem with npm. There is likely additionallog
ging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2019-8-1T0
3_18_15_677Z-debug.log
Copy the code
  • Don’t panic, the solution is to execute the following commands in sequence:
git add .
git commit -am "init"
yarn eject
Copy the code
  • After successfully eject the configuration, you can see the following changes in the project directory:

  • If you need to customize the project, you will generally modify the default Webpack in the Config directory.

Perfect customized projects

  • How to introduceless, addtslint å’Œ stylelintAnd the introduction ofreact-router, encapsulationfetchRequest, importreact-loadableAnd load on demandantd.

The introduction of less

  • The installationless å’Œ less-loader:
Yarn add less less-loader - devCopy the code
  • Modify the webpack configuration by adding it to the config/webpack.config.js filelessConfiguration variables:
const lessRegex = /\.less$/; // Add less const LessLessModuleregex = /\.module\.less$/; // Add less configurationCopy the code
  • Also, add rules to the module in config/webpack.config.js:
    module: {
      strictExportPresence: trueRules: [/ * * omitted code / {oneOf: [/ * / / * * omitted code below is the original code block * / {test: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: true, getLocalIdent: getCSSModuleLocalIdent,}),}, /*test: lessRegex, exclude: lessModuleRegex, use: getStyleLoaders({importLoaders: 1,// The value is 1sourceMap: isEnvProduction && shouldUseSourceMap
              },
                "less-loader"
              ),
              sideEffects: true
            },
            {
              test: lessModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: trueLess getLocalIdent: getCSSModuleLocalIdent},"less-loader"}, /* Add code block */ * add code block */test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'sass-loader'
              ),
              sideEffects: true},},},Copy the code
  • Modularity can be achieved through the above configurationless(file named xx.module.less) and globalless(files named xx.less).
  • Portal 👉CSS Modules and React
  • Modular introduction:
import * as styles from ./index.module.less
Copy the code
  • The point! If you want to introduce modularity into your projectless, you need to configure it in the SRC /react-app-env.d.ts file. Otherwise, ts errors will occur Cannot find module './index.module.less', the configuration is as follows:
declare module '*.less' {
  const styles: any;
  export = styles;
}
Copy the code
  • And that’s donelessIntroduced in react + typescript projects.

Editor configuration

  • In daily development, it is common to switch between different editors and always have to set the configuration again. Team development, with each person using a different editor and having a different configuration style. You can set up consistent code specifications for different editors by adding an. Editorconfig file in the project root directory and configuring certain rules.
  • Here is my configuration:
# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab
Copy the code

Add tsLint and stylelint to the project

  • Tslint: Similar to ESLint, which essentially restricts our logical code style, can be configured by adding a.tslint.json file to the project root. You can usually quote things like"extends": ["tslint-react"]If there are special rules, you can add them yourself. Content examples:
{
  "extends": ["tslint-react"]."rules": {/* add special rules */}}Copy the code
  • Stylelint: Style code style that can constrain our style, which can be configured by adding the. Stylelintrc file in the project root directory. You can usually quote things like"extends": ["stylelint-config-standard"]If there are special rules, you can add them yourself. Content examples:
{
  "extends": "stylelint-config-standard"."rules": {/* add special rules */}}Copy the code
  • The above are completed in the projecttslint å’Œ stylelintTo add.

The introduction of the react – the router

  • Some people would say, noyarn add react-routerDo you need to be taught? Actually not, look at 👇 :
  • The React Router is now split into three packages:react-router.react-router-dom.react-router-native.
  • It should not be installed directly during developmentreact-routerThis package provides core routing components and functions for the React Router application, while the other two packages provide context-specific components (browser and React Router)react-nativeCorresponding platform), but they too willreact-routerThe exported module is exported again.
  • We should choose either of these packages for the development environment, since I need to build a website (running in a browser), so I installedreact-router-dom. Also, since I’m using typescript in my project, I need to install it@types/react-router-dom. Installation command:
yarn add react-router-dom
yarn add @types/react-router-dom --dev
Copy the code
  • The above are completed in the projectreact-routerThe introduction of.

Encapsulating fetch requests

  • If it is just a simple request, there is no need to introduce AIxOS. The relevant codes of fetch request can be encapsulated in request.js/request.ts file and relevant request methods can be introduced when using it.

    • Less local code is requested.

    • Common errors can be added in one place.

    • Requests for customization errors can be handled by the request itself.

    • Good scalability, add functionality only need to change one place.

  • Here are the details of the request.ts file I wrapped in the project:

// path: SRC /utils/request.ts const request = (url: string, config: any) => {// path: SRC /utils/request.ts const request = (url: string, config: any) => {return fetch(url, config)
    .then((res: any) => {
      if(! Res.ok) {// Server exception returns throw Error('Interface request exception');
      }
      return res.json();
    })
    .catch((error: any) => {
      returnPromise.reject(error); }); }; / / GET requestexport const get = (url: string) => {
  return request(url, { method: 'GET'}); }; / / POST requestexport const post = (url: string, data: any) => {
  return request(url, {
    body: JSON.stringify(data),
    headers: {
      'content-type': 'application/json',
    },
    method: 'POST'}); };Copy the code
  • Create different request modules according to function, such as list module:
// path: SRC /services/ API /list.ts import * as Fetch from'.. /.. /utils/request';

export async function getListData () {
  return Fetch.get('URL1');
}

export async function getListItemDetail (id: number) {
  return Fetch.get(
    `URL2/${id}`); }Copy the code
  • Exposed API:
/ / path: SRC/services/API. The tsexport * from './api/list';
Copy the code
  • Components used in:
// path: SRC /components/xxx.tsx import React from'react';
import * as api from '.. /.. /services/api'; Class HomePage extends React.Component<any> {/* omit code */ asyncloadListData () {
    try {
      const res = await api.getListData();
      this.setState({
        listData: res.data.list,
      });
    } catch (error) {
      // doSomething}} /* omit code */export default HomePage;

Copy the code
  • The above is successfully completedfetchEncapsulation of the request.

The introduction of the react – loadable

  • Applications tend to grow when using react.js single-page applications. One part of the application (or path) may import a large number of components that were not necessary when first loaded. This will increase the initial load time of our application.
  • When we useyarn buildWhen we package the project, create-React-app will generate a large file that contains all the JavaScript we need for our application. However, if the user only loads the login page to log in; It doesn’t make sense for us to load the rest of the application with it.
  • To solve this problem, create-React-app has a very simple built-in way to split our Code. This feature is called Code Splitting.
  • Project Settings support code splitting via dynamic import(). We can use a third-party library called react-loadable that takes into account various scenarios such as component load failures, loading, and so on.
  • First, installreact-loadableAlso, since I’m using typescript in my project, I need to install it@types/react-loadable. Installation command:
yarn add react-loadable
yarn add @types/react-loadable --dev
Copy the code
  • To make the entry file look more concise, I will separate out the route configuration in the routes.tsx file. In the entry route file app.tsx, I will just put therouteDataIntroduce and use:
// path:src/App.tsx

import { createHashHistory } from 'history';
import React from 'react';
import { Router } from 'react-router';
import routeData from './common/route';

const history = createHashHistory();

const App: React.FC = () => {
  return (
    <Router history= {history}>
      <Switch>
        {routeData.map(({ path, component, exact }: IRouterItem) => (
          <Route key={path} path={path} component={component} exact={exact} />
        ))}
        <Route component={NotFound} />
      </Switch>
    </Router>
  );
};

export default App;

Copy the code
  • The routes. TSX file contains the following information:
// path: SRC /common/route. TSX import * as React from'react';
import Loadable from 'react-loadable';
import Loading from '.. /components/Loading';

const routeConfig: any = [
  {
    path: '/',
    component: asyncLoad(() => import('.. /views/HomePage')),
  },
  {
    path: '/detail/:id',
    component: asyncLoad(() => import('.. /views/DetailPage'}, /** * Exception page */ {path:'/exception/404',
    component: asyncLoad(() => import('.. /views/Exception')),},];function generateRouteConfig (route: IRouteConfig[]) {
  return route.map(item => {
    return {
      key: item.path,
      exact: typeof item.exact === 'undefined' ? true: item.exact, ... item, component: item.component, }; }); }function asyncLoad (loader: () => Promise<any>) {
  return Loadable({
    loader,
    loading: props => {
      if (props.pastDelay) {
        return <Loading />;
      } else {
        return null;
      }
    },
    delay: 500,
  });
}

export default generateRouteConfig(routeConfig);
Copy the code
  • By encapsulating asyncLoad functions that load routes dynamically, it is possible to render related components only when switching to the corresponding route.

Load ANTD on demand

  • Antd is an excellent React UI library from Ant Financial. It contains many components that we use most often.
  • When we use the ANTD library directly in this project without any configuration, we see the following prompt on the console:
  • Antd library size is about 80M, the full introduction of this library will inevitably affect the network performance of our application, on-demand introduction is particularly important.
  • The official documentation (portal 👉 ANTD documentation) provides two ways to implement antD on demand:
  • In this paperbabel-plugin-importTo load on demand. Detailed steps are described below.
  • The installationantd :
yarn add antd
Copy the code
  • The installationbabel-plugin-import :
yarn add babel-plugin-import --dev
Copy the code
  • Add rule to module in config/webpack.config.js:
    module: {
      strictExportPresence: trueRules: [/ * * omitted code / {oneOf: [/ * / / * * omitted code below is the original code block * / {test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              loader: require.resolve('babel-loader'),
              options: {
                customize: require.resolve(
                  'babel-preset-react-app/webpack-overrides'
                ),
                plugins: [
                  [
                    require.resolve('babel-plugin-named-asset-import'),
                    {
                      loaderMap: {
                        svg: {
                          ReactComponent: '@svgr/webpack? -svgo,+ref! [path]'},},},], /* Add code block */'import',{// Import a plugin called libraryName:'antd', // Exposed library name style:'css'}],], /* add code block */ * add code block */ cacheDirectory:true, cacheCompression: isEnvProduction, compact: isEnvProduction,Copy the code
  • This allows antD components to be loaded on demand without importing style files each time:
import { Button } from 'antd';
Copy the code
  • Note: Since modularity is implemented in the projectless, if you want to modify the style of antD components within a module:global, such as:
:global { .ant-divider { margin: 0 0; }}Copy the code
  • The above is the full text of the introduction of the content, the relevant configuration is through my own painstaking practice, if you have questions, welcome to leave a message.