React Front-end architecture React front-end architecture Attach source code addressGitee.com/SongTaoo/re…

Initialize the React scaffolding

NPX create-react-app xx, wait for it to complete, then CD to xx, run NPM run eject to unpack the scaffolding configuration items, because we need to do some configuration

  1. Found in the scripts folder below start. Js line 43 const DEFAULT_PORT = parseInt (process. The env. PORT, 10) | | 9999 modify our PORT

  2. I prefer less so let’s configure less, Find webpack.config.js in config folder and fill line 63 with const lessRegex = /.less/ const lessModuleRegex = /\.module\.less/ copy the sass configuration. To install less and less-loader, run NPM install –save less less-loader

Note that there is a catch: an error will be reported if the less-Loader version is installed too high, so let's just drop it to 6.0.0

  1. Delete files, delete useless files that are not generated by default according to personal preference, I only keep the index.js app.js reportWebvitals.js

Models (redux)

If you’ve ever used DVA, dVA encapsulates the Redux router so that you can do dumb things

  1. performnpm install --save dvaInstall the dva
  2. Once installed, create the Models file under the SRC target to store the data, our old Redux
  3. Create base.js under models. This is used to store common data, such as user information, global loading…

The code is as follows:

const base = {
    namespace: 'base'.state: {
        name: 'Autumn water without trace'
    },
    reducers: {},
    effects: {}}export default base
Copy the code

This is our configuration file, if there are more than one, directly create multiple js in the SRC directory to create dvaapp.js to configure some dVA information

import dva from 'dva'
import { createHashHistory } from 'history'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'

const persistConfig = {
    // Redux persistent configuration
    key: 'root'.storage: storage,
    blacklist: []}// Build the DVA application, configure some hooks
const app = dva({
    history: createHashHistory(),
    onError(e) {
        // Catch an error in effect execution
        // Error triggered by done in subscription
        console.log(e)
    },
    onAction() {
        return (next) = > (action) = > next(action)
    },
    // Listen for state changes
    onStateChange() {},

    onReducer(reducer) {
        return persistReducer(persistConfig, reducer)
    }
})
window.onload = () = > persistStore(app._store)

export default app

Copy the code

I use redux-persist to store the data persistently. The file name under Models is added to the blacklist array to store the current data persistently, that is, to save a copy of the original localstrong. Because dVA models are injected based on routes, here we need to create routes to combine the data with the page

Create a Router

JSX RouterView.jsx history.js routes.js Create the router folder in the SRC directory and create the index.jsx RouterView.jsx history.js routes

1: creates history.js to obtain routing information

const { createHashHistory } = require('history')
export default createHashHistory()
Copy the code

2: create index. JSX

import React from 'react'
// import { BrowserRouter as Router } from 'dva/router';
import { HashRouter as Router } from 'dva/router'
import routes from './routes'
import RouterView from './routerView'
export default function SetRouter() {
    if(! routes || routes.length ===0) return null
    return (
        <Router>
            <RouterView routes={routes} />
        </Router>)}Copy the code

3: Create RouterView. JSX and iterate over routes to generate a route display

import React from 'react'
import { Switch, Route } from 'dva/router'

function RouterView(props) {
    const { routes } = props
    if(! routes || routes.length ===0) return null
    return (
        <Switch>
            {routes.map((item) => {
                const { path } = item
                return (
                    <Route
                        key={item.path}
                        path={path}
                        exact={item.exact}
                        render={(renderProps)= >{ const Component = item.component if (! Component) return null return<Component {. renderProps} {. item} / >/ >)})}}}</Switch>
    )
}
RouterView.defaultProps = {
    routes: []}export default RouterView

Copy the code

4: Create a routes file and associate models

import dynamic from 'dva/dynamic'
import app from '.. /appDva'

// If there is common data to share, write it in base
const commonArr = [import('.. /models/base')]

const createComponent = (component, arr = []) = >
    dynamic({
        app,
        models: () = > [...commonArr, ...arr],
        component
    })

// [import('../models/...')] // This is used to import Rudux
const Home = createComponent(() = > import('@/pages/home'))
const Login = createComponent(() = > import('@/pages/login'))
const Center = createComponent(() = > import('@/pages/center'))
const HomeName = createComponent(() = > import('@/pages/homename'))
If you want to make it simple, you can negotiate with the backend to return the following data. If it is complicated, you need to return the user's permission. We recursively generate a new array.
const routes = [
    {
        path: '/home'.component: Home,
        name: 'My Homepage'.routes: [{path: '/home/name'.component: HomeName,
                exact: true.name: 'My Message'}]}, {path: '/center'.component: Center,
        name: 'Personal Centre'
    },
    {
        path: '/login'.component: Login,
        name: 'login'}]export default routes

Copy the code

Dva provides dynamic functions for lazy loading of routes to optimize project performance. I have encapsulated a function here that will inject base data into all routing pages by default. If additional data is needed, just pass the second parameter to the createComponent function

Modify the entry file to make the project run

Change app.js to the following

import React from 'react'
import SetRouter from './router'
import './app.less'
export default function App() {
    return <SetRouter />
}

Copy the code

Change index.js to the following

import reportWebVitals from './reportWebVitals'
import dvaApp from './appDva'
import App from './App'
dvaApp.router(App)
dvaApp.start('#root')

reportWebVitals()

Copy the code

Create a Pages folder under the SRC folder, write some pages corresponding to our route, execute NPM start, and then you can see our running project.

5. Configure ANTD

So this is pretty easy just look at the API, if you don’t understand it you can look here, the portal

Configure ESLint constraint code

Since we are using the latest react17.0.2, we can directly override the default configuration of ESLint and create.eslintrc.js in the SRC file as follows:

module.exports = {
    env: {
        node: true.mocha: true.jest: true.es6: true.browser: true
    },
    extends: [
        'eslint:recommended'.'plugin:react/recommended'.'plugin:react-hooks/recommended'].parser: 'babel-eslint'.parserOptions: {
        ecmaFeatures: {
            jsx: true
        },
        ecmaVersion: 6.sourceType: 'module'
    },
    plugins: ['react'.'jsx-a11y'.'react-hooks'.'prettier'].settings: {
        react: {
            version: 'detect'}},globals: {
        JSX: true.React: true.NodeJS: true.Promise: true
    },
    rules: {
        'no-console': 'off'.'consistent-return': 2.curly: [2.'multi-or-nest'].'dot-location': 0.eqeqeq: 2.'no-alert': 2.'no-eq-null': 2.'no-lone-blocks': 2.'no-return-await': 2.'no-unused-expressions': 2.'no-label-var': 1.'array-bracket-spacing': 2.'brace-style': 0.'comma-spacing': 1.'consistent-this': 1.'eol-last': 0.'multiline-ternary': [1.'always-multiline'].'new-cap': [
            2,
            {
                capIsNew: false}].'no-trailing-spaces': 0.semi: ['error'.'never'].'space-before-blocks': 2.'space-in-parens': 2.'spaced-comment': 2.'switch-colon-spacing': [
            'error',
            {
                after: true.before: false}].'arrow-spacing': 2.quotes: [0.'single'].'key-spacing': 2.'comma-dangle': ['error'.'never'].'react-hooks/exhaustive-deps': 0.'no-empty-function': 0.'react-native/no-inline-styles': 0.'react/forbid-prop-types': 0.'react/prop-types': 0.'react/display-name': 0.'prefer-promise-reject-errors': 0.'react/no-array-index-key': 2.'react/no-unused-state': 2.'react/jsx-indent-props': 2.'react/jsx-no-comment-textnodes': 1.'react/jsx-no-duplicate-props': 2.'react/jsx-no-target-blank': [
            1,
            {
                enforceDynamicLinks: 'always'}].'react/jsx-no-undef': 2.'react/jsx-props-no-multi-spaces': 1.'react/jsx-tag-spacing': 1.'react/jsx-uses-vars': 2.'react/jsx-wrap-multilines': 2.'react-hooks/rules-of-hooks': 2}}Copy the code

Create an.eslintignore file under the SRC folder to hold files that are ignored for esLint checks

node_modules
dist/
test
build/
public/
scripts/
static/
config/
Copy the code

If you are using the vscode editor, you can fix it when you save the code after installing the eslint plugin. To be more rigorous with the ESLint specification, I’ve added comIT validation

Package. json is added. You can install pre-commit on the console

"scripts": {
        "start": "node scripts/start.js"."build": "node scripts/build.js"."test": "node scripts/test.js"."lint": "eslint . --fix" // Add to modify the code
    },
    "pre-commit": [
        "lint" // Add validation].Copy the code

Ok, up to this point our architecture has been built perfectly, isn’t it very simple ah! Don’t forget to bookmark the likes!