Project address: github.com/X-neuron/an…

Project Features:

1. Use webPack, Babel, ANTD and other relatively native configuration and function components to build, support PWA.

2. Minimal Hox data flow.

3. Support dynamic configuration of JSON routes.

4. Page and button level dynamic permissions.

5. The development environment supports hot overloading. 6, refine the routing algorithm, realize multi-label page routing, support component, routing state saving.

7. Support internationalization (react-Intl-universal)

8. Support micro front end (Qiankun).

9. Small amount of code, complete development environment, suitable for the reference of friends who want to adapt to React Hook era.

Project fit object

This project is suitable for those who have a strong curiosity to build the front end of the management system separated from the front end or who are fanatic about technical cleanliness. It is still recommended to use UMI for quick application under Ant Design, because the native Webpack builds the React development environment of Ant Design. This project only integrates the technical route of direction that the author thinks. If you don’t want to learn so many constraints, you want to feel the pleasure of fate in your own hands, or use other UI, or write a micro front-end component, then this project will be a good reference for migration.

Project motivation

When preparing to develop management system based on React, the author chose Ant Design and found that most of the community is ANTD3 version, some are ANTD4, and UMI is still 2. Wait until the Ant Design Pro umi reaches 3. Data flows and permissions have not been migrated. Otherwise, it is still in the era of class components, with part of hook, permission management can not reach the button level, if you want to build a hook version of multi-label micro front-end based on Ant Design Pro, the community can not find the desired solution. So instead of waiting, make your own…

The advantage of project

Embrace react Hook, function components. Hox data flow, minimal permissions, rewritten components, components code concise, easy to understand, easy to learn anatomy. Dynamic multi-label routing hooks, permission components, permission hooks, micro-front-end components, internationalization and other non-configured core code add up to no more than 500 lines.

Main structure of the project

The project structure is basically the same as Ant Design Pro..

├── Package.json ├─.eslintrc.js ├─.postcss.config.js ├─ WebPack.dev.config.js ├─ build // Build folder ├─ mock // Mock Mock Data folder (mockJS) For real production test environment recommend using other libraries ├─ public // Public Resources folder ├─ // └─ SRC ├─ components // ├─ hooks // Set custom non-global effects hook ├─ config ├─ ICONS The main purpose is to implement the string configuration of the routes.js icon. ├ ─ pages.js // to implement routes.js routing page string configuration. ├ ── routes.js // Get your own route setup. ├ ─ ├ ─ layouts // ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├─ ├.js // ├─ ├─ pds.txt // conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf/conf App. JSX └ ─ ─ index. The JSX └ ─ ─ index. The HTMLCopy the code

Q&A

1、为什么用 antd design

After an in-depth review of more than a dozen UIs, I was impressed by the Material UI, Ant Design, and Rsuite. The characteristics of the Material UI project are: Technology catches up with the new quickly. When React Hook was released at the end of 2018, the Material kernel and documentation were all switched to hook in less than half a year. In the description of the UI component separation, the design is also very elegant, it is very convenient to use CSS-in-JS, styled-component on it, the theme switch is never a problem, for technology enthusiasts, it is the ideal UI programmer. However, due to the lack of large company background, components are not rich enough, such as date range selection and cascade selection, you need to write a large number of components, the author thinks that because of the V5 UI engine may be upgraded, so it is suggested to consider starting after V5 release.

Antd Design was upgraded to version 4.0 in early 2020, and hooks have been seen in some components. In terms of CSS style, less has remained unchanged for a hundred years (there may be some consideration for sketch designer), changing the theme often requires a lot of magic combination, digital input component still cannot use the scroll wheel, ANTD3 form is a little difficult to look at, 4.0 form Hook, has reached an acceptable level, Antd’s strength is in making the technology into a product. What really impressed me was the Message component, which can be called as if writing a function (message.info(‘a message’)), as if returning to familiar Extjs overnight. Component richness is comparable to personal customization. In general, ANTD Design is not radical and conservative in technology (due to a large amount of historical burden). Large-scale application will be carried out only when small-scale experiments can be carried out properly.

Rsuite is a nice UI with a Material water wave effect and close to antD’s aesthetic. I used to love the way their schema-typed forms were described. Similar to YUP, it is small, the code is easy to read and modify. If you don’t want to use formIK to manage your forms, it is very easy to develop your own form hooks (FYI) with schema-typed forms. However, the current 4.0 Version of Icon is packaged as a whole, which is large and has not enough components for community expansion.

2. Why not use Umi

“Native, not necessarily the fastest, but often the best “– when the React founders used JS in an object-oriented way, embracing class syntax sugar, designing component lifecyls, and creating higher-order components for reuse. When they understood JS and embraced function closures, Close to the function component, there is a Hook.. React gravitate toward functions because the closure nature of functions perfectly matches the need to render frame state preservation.

Every framework has a life cycle, and with each iteration of technology, the shelf may disappear, but good ideas tend to sink. For example: Ruby constraints: create a model folder, you have a model, create a locale folder, you have internationalization. Although Ruby is rarely seen, constraint ideas have influenced the design of frameworks from generation to generation. For example, in the Redux era of react class component, dVA and rematch were used to make you feel that it was too late to use dVA and rematch. When react was upgraded to Hook, these data streams became less natural to use. When you’re using antD Design Pro that doesn’t offer the features, and you can’t wait to get into the new technology, you’re just waiting, trudging, waiting…. Round and round…

Life is limited, do not repeat the wheel, but should have the idea and technology to build the wheel..

3. Why not use CRA

Using CRA to start ANTD project, the main difficulty lies in modifying webPack configuration, because javascriptEnabled: true(a risky option) needs to be enabled for less-Loader. Currently, the best community solution is: React-app-rewired, Craco, and React-app-Rewired can override some crA webpack configurations, but it is difficult to enable some packaging performance optimizations, such as Thread-Loader. In my tests, only YARN can be used to initialize the project. Dependencies cannot be installed with NPM I. Not using this scaffolding is also an effort to live up to the principle of pure original.

4. Why Hox is selected for data flow

When choosing data flow, the author has tried dozens of data flow schemes. Why didn’t he choose DVA, Rematch, Easy-Peasy, ICestore-next, unstated-next… Wait, dVA and Rematch are both products of redux’s idea to optimize code writing, which is needed in the Hook era, while Easy Peasy manually maps state, action and Redux Connect in the same way. Even the Connect approach loosens the coupling between the UI and the business model and facilitates decorator injection. So I searched and searched and found Hox, Unstate-Next, Icestore-Next. By comparison, HOX doesn’t need as many providers and contexts, and just one API is simpler. Kind of like mobox’s subscription and hook combination. Makes coding for global state simpler, even if you run into irreconcilable problems, making it easy to migrate to unstate-next. Hox is the original Hook, so the sky floated a few words: “the original, is often the best”…

Why use react/router for routing

The authors of react-Router say that Reach/Router is the next generation of React-Router. So I used it. Packing size is 4KB smaller. The most critical is, it is easy to civilian out of its routing algorithm, do a multi-label page, master the route entrance, get to umi god technology feel very comfortable.. Secondly, based on the nested routine written by the code is simple and good-looking. Disadvantages: the author has limited ability, and the configuration based on REACH/Router dynamic nesting routine has not been overcome. Second, there was a small problem navigating history and redirect. This option may be a bit radical.. Replace it with the react-router.

6. Why use qiankun micro front end?

Due to the advertisement “This is probably the most complete microfront-end solution you’ll ever see”, I haven’t tried any other microfront-end yet due to my limited time. The author tried many times in qiankun1.0 and found that it could not solve the problem of dynamic Dom nodes generated by dynamically adding multiple tags to components, and almost gave up. After Qiankun 2.0, THE API is upgraded and simple. Support for manual loading is perfect for this purpose and can easily build MicroApp components (see project SRC/Components /MicroApp for details). Qiankun also has many step pit points, please pay attention to production and use.

Json configuration routing? Isn’t this the magic frame can get?

In React, it is very difficult to implement json configuration routing gracefully, which mainly involves the dynamic addition of JSX components and the loading of code segmentation on demand. There may be irreconcilable contradictions. Under current conditions, if there is no need to configure route dynamically, the best solution may be UMI, which automatically generates corresponding codes according to the configuration under the support of Node plus framework. If you want to dynamically configure the routing and adjust the display of menu, the author has made a variety of dynamic parsing attempts, but none of them can be solved. The current solution is to split the configuration of routes into three parts: ICON, Page and routes, and jointly realize the JSON routing configuration without frame.

Routing parsing code location: SRC/hooks/useAppRoute js, SRC/models/useTabRoute js

const routes = [
  {
    path: '/user'.page: 'userLayout'.routes: [{name: 'login'.path: 'login'.page: 'login'}, {name: 'register'.path: 'register'.page: 'register',},],}, {path: '/'.page: 'securityLayout'.// The routing configuration of the above layout has not implemented dynamic parsing based on @reach/router, but has provided corresponding hook reading configuration. If necessary, you can switch to react-router. The code in app.jsx has provided some corresponding annotations..
    routes: [
      {
        path: '/'.page: 'basicLayout'.access: 'validUser'.menuTabs: [  //sideMenu is configured with route. Only one menuTabs can be configured on a routes.js.
          {
            path: '/'.name: 'menu-welcome'.// If the translation fails, use the name configuration value. If no globalization is required, use Chinese directly.
            icon: 'HomeOutlined'.// @/config/ ICONS specifies the ICONS configured in the ICONS. Lowercase ICONS also work
            access: 'dashboardOpen'.Static policies can be configured in // @/config/access. The permission entry is in @/config/pages.
            page: 'dashboard'.// Non-dynamic routes with page attributes are displayed in sideMmenu by default.
          },
          {
            // The menu with subs is a drop-down menu, indicating that it does not need routing and ignores the page attribute. However, it will be used as the parent route of subs subroutes and the Key of siderMenu. The internal count is +1
            name: 'sideMenu-usual'.path: '/ab'.icon: 'AppstoreOutlined'.subs: [{name: 'sideMenu-from1'.path: 'a'.// a /ab/a
                page: 'test1'.// Page is recommended to use lowercase, which is converted internally to uppercase, corresponding to the component. This parameter is consistent in the permission configuration
                access: 'test1Open'.For details, see @/models/useAccess
              },
              {
                name: 'sideMenu-from2'.path: 'b'.// this is /ab/b
                page: 'test2'.access: 'test2Open'}, {name: 'sideMenu-from3'.path: '/c'.// parse to /c
                page: 'test3'.access: 'test3Open',}]}, {name: 'Micro-front'.path: '/micro'.icon: 'PaperClipOutlined'.subs: [{name: 'material-ui'.path: 'material'.access: 'microOpen'.page: 'http://localhost:8002'
              },
              {
                name: 'vue2'.path: 'vue2'.access: 'microOpen'.page: 'http://localhost:8001',},]}]},],},Copy the code

8. Page and button level permissions

The choice of permission configuration mode mainly requires the design of both front and back ends. The author has weighed between ant Design Plus policy and umiJS/plugin-Access for a long time. The simulation results show that umiJS /plugin-access is a feasible way for simple button permission management. I can only think of one reason why the front end doesn’t need data-level permissions: for example, managers and directors, the component to view the data may be common, but the content to view should be a back-end API permission configuration issue. I wonder if this is sufficient. The following shows the dynamic management of data flow permissions in conjunction with HOX. SRC /models/ useaccess.js page-level permissions are configured in SRC /config/routes.js, and button-level permissions are controlled using the SRC /components/Access component.

import { useState } from 'react';
import { createModel } from 'hox';
// import useLoginModel from '@/models/useLogin';
import _ from 'lodash';

const useAccess = (a)= > {
  // const { isLogin, role, user, userId } = useLoginModel();

  const [access, setAccess] = useState({
    // This design was abandoned because naming conflicts would result in priority access under access.key.
    // test1: {
    // open: true,
    // deleteUserList: false,
    // adduserList: true
    // },
    // test2: {
    // open: false, // back end returns
    // },
    test1Open: true.test2Open: false.microOpen: true.test3Open: true.adminSubmit: false.// 'example': role === 'admin',
    // 'example2': some => some.prop === 'test'
  });

  // Change the permission to overwrite the existing permission.
  const updateAccess = (newAccess) = > {
    setAccess(_.merge(access, newAccess))
  }

  return { access, updateAccess }
};

export default createModel(useAccess);
Copy the code

9, multi-label, lead routing? How to save component state, is there any magic technology?

React – Keeper? It seems so complicated, and the concepts are a lot to learn. In fact, the native component comes with a key. As long as the component structure is the same. The component state remains after diff. What is a route? Is according to the input address, automatically select display corresponding components. With that in mind, dig up the 4KB reach/ Router code and find gold in it. You don’t have to duplicate the wheels. Multi-label routing uses only the routing algorithm. What also not much said, lu code: the code location of project: the SRC/models/useTabRoute. Js

  // Sometimes other page buttons trigger new routes, openRoute feels more appropriate. Easy compatibility with micro front ends.
  // In the case of the micro front end, the route may change. The latest address should be recorded after clicking TAB. To record its latest status.
  // The key is usually in the menu mode. The key is the route configuration of the page, such as /dist/:user/role
  OpenRoute ('/test');
  // keyLruSquence tag management Lru algorithm queue, just for humanization. At the same time, it is convenient to obtain the last historical path.
  // The Lru cache records the following information:
  /* menu The key is the page route configured in @/config/routes. It can be written in dynamic routing mode. Key: {page: // Display route component eg:'test' name: // page title eg:'pageTitile' curRoute: // The micro end may modify the current route. CurRoute =Key access: pickroute. access, @/config/routes/params // dynamic route /routes / */
  import { pick, resolve, match } from '@reach/router/es/lib/utils';  // Extract the routing algorithm of reach/ Router
  import memoized from 'nano-memoize';

  const memoizedPickRoute = memoized((routeConfig, route) = > pick(routeConfig, route).route);  / / cache
  const openRoute = (route) = > {
    // Call @reach/router to get the component matching the route.
  const pickRoute = memoizedPickRoute(menuTabConfig.tabRoutes, route);
    // Params parameters for dynamic routing are parsed.
    const result = match(pickRoute.path, route);
    // Is the parameter the props input of the component?
    const params = result
      ? {
        ...result.params,
        uri: result.uri,
        path: pickRoute.path
      }
      : null;
    if (keyLruSquence.get(route)) {
      setActiveKey(route);
    } else {
      const tab = {
        name: pickRoute.name,
        key: route,
        page: pickRoute.value,
        curRoute: route,
        access: pickRoute.access, // Is the component's permission
        params
      };
      setTabList([...tabList, tab]); / / configuration tabpane
      keyLruSquence.set(route, tab); 
      setActiveKey(route);  // synchronize sidemenu
    }
    navigate(route); // Change the current page URL.
  }
Copy the code

Project deployment

Git Clone or download and unzip to your computer. Go to the project directory. NPM I or YARN (CNPM or TYarn is recommended in China) NPM run build or NPM run devCopy the code

The author micro front-end test, currently using nGINx. The recommended configuration: [click here]. It can be used in your own environment, just modify SRC /config/routes.js. (If you need to share the state, you need to add the corresponding microterminal global status code)

If complete configuration is required, use npm-run-all to set up the preview complete environment.

added

1, because in many forums and groups found that many friends are looking for micro front end multi-label scheme. In order to solve the needs as soon as possible without affecting the use, the project is temporarily written by JS and kept original. If it needs to be used in TS, it needs to define its own type. Also welcome the TS version of pull Request

2. Since the project often uses NCU to manage dependencies, keep the library up to date. Currently less loader is still 5.0 (due to mini-CSS-extract-plugin)

3. The project will continue to pay attention to the latest technology in the industry, and maintain a good understanding of Parcel2, Webpack5, ESbuild, Babel/Macros.. Practice tracking, once stable, will be followed by practice.

4. Depending on Nanoid, the project may have high requirements on node version 13.5 or higher, so IT is recommended to use NVM (Windows) and NVM (MARCS \ Linux) to manage node version, which is convenient to switch freely. If you don’t like it, you can replace your own appropriate library.