• 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(基础篇)


    背景

    最近因为要做一个新的管理后台项目,新公司大部分是用vue写的,技术栈这块也是想切到react上面来,所以,这次从0到1重新搭建一个react项目架子,需要考虑的东西的很多,包括目录结构、代码规范、请求封装等等,
    涉及内容较多,所以我分成了几个部分来记录搭建的过程:

    1. 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(基础篇)
    2. 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(引入redux)
    3. 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(菜单路由)
    4. 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(权限)

    项目我已经上传到github,有需要的可以自取,记得star哦!也欢迎大家在上面提issue~

    项目初始化

    1. 通过create-react-app并使用typescript模板创建项目
    yarn create react-app react-antd-adminMT  --template typescript
    
    1. 目录结构调整

    为了便于开发和管理代码,我们在src下创建components、navigation、pages、redux、services、utils子文件夹

    ├── LICENSE
    ├── README.md
    ├── build
    ├── mock        			---本地mock服务
    │   ├── server.js
    │   └── test.js
    ├── package.json
    ├── public
    ├── src
    │   ├── components    ---组件
    │   ├── config        ---配置文件
    │   ├── index.css
    │   ├── index.tsx
    │   ├── navigation    ---路由导航
    │   ├── pages        	---页面组件
    │   ├── redux
    │   ├── services      ---接口文件
    │   ├── setupProxy.js
    │   ├── setupTests.ts
    │   └── utils         ---工具相关
    ├── tsconfig.json
    └── yarn.lock
    

    多环境打包配置

    例如我们需要配置多个不同的环境,加载不同的变量

    .env.development
    .env.staging
    .env.production
    

    每个文件里面对应不同的变量值

    PORT=3000
    REACT_APP_ENV=staging
    REACT_APP_BASE_URL=https://www.zhihu.com
    

    打包时加载不同环境变量文件

    两种方式:

    • env-cmd
    • dotenv-cli
    "scripts": {
        "dev": "env-cmd -f .env.development react-scripts start",
        "dev:stg": "env-cmd -f .env.staging react-scripts start",
        "build": "react-scripts build",
        "build:stg": "env-cmd -f .env.staging yarn build",
        "build:prod": "env-cmd -f .env.production yarn build",
        "test": "react-scripts test",
        "eject": "react-scripts eject"
      },
    

    这里我使用的是env-cmd,通过在脚本命令配置env-cmd -f .env.development,这样我们就可以再执行yarn dev的时候加载.env.development文件里面的变量,类似,每个不同环境打包加载对应不同的环境变量

    配置代码规范

    prettier配合eslint

    eslint主要用于语法校验,prettier保持风格统一

    1. 安装相关包
    $ yarn add C eslint-plugin-prettier eslint-config-prettier --dev
    

    上面安装包中eslint、 prettier肯定是必不可少的。eslint-plugin-prettier插件会调用prettier对你的代码风格进行检查,eslint-config-prettier插件可以关闭一些不必要的或者与prettier冲突的lint选项

    1. 在根目录下创建.eslintrc.js文件
    module.exports = {
      root: true,
      parserOptions: {
        ecmaFeatures: {
          jsx: true
        }
      },
      env: {
        browser: true,
        es6: true
      },
      extends: ['react-app', 'plugin:prettier/recommended'],
      plugins: ['prettier'],
      rules: {
        'prettier/prettier': 'error',
        'react-hooks/rules-of-hooks': 'error',
        'react-hooks/exhaustive-deps': 'off'
      }
    }
    
    

    eslint配置项有很多,例如:
    Parser、parserOptions、Environments、Globals、Plugins、extends、Rules

    详情可以查看eslint手册 https://eslint.bootcss.com/docs/user-guide/configuring

    这里主要介绍下extends、plugins和rules选项

    1. extends

    一个配置文件可以从基础配置中继承已启用的规则。extends 里面可以引入 共享配置包,可以引入 插件

    • 可共享的配置

    可共享的配置 是一个 npm 包,它输出一个配置对象。extends 属性值可以省略包名的前缀 eslint-config-。

    • 插件

    插件 是一个 npm 包,通常输出规则。plugins 属性值 可以省略包名的前缀 eslint-plugin-。

    • extends 属性值可以由以下组成:

    (1)、plugin: (2)、包名 (省略了前缀,比如,react) (3)、/ (4)、配置名称 (比如 recommended)
    例如:extends: ['react-app', 'plugin:prettier/recommended']

    1. plugins

    ESLint 支持使用第三方插件。在使用插件之前,你必须使用包管理工具安装它,插件名称可以省略 eslint-plugin- 前缀

    1. rules

    ESLint 附带有大量的规则,可以使用注释或配置文件修改你项目中要使用的规则。要改变一个规则设置,你必须将规则 ID 设置为off、warn、error三者之一。

    1. 根目录下创建.prettierrc.js文件
    module.exports = {
        semi: false,						// 句末加分号
        singleQuote: true,      // 用单引号
        printWidth: 80,    			// 换行字符串阈值
        jsxSingleQuote: true,   // 在jsx中使用单引号代替双引号
        trailingComma: 'none',	// 最后一个对象元素加逗号
        arrowParens: 'avoid'    // (x) => {} 是否要有小括号
    }
    

    1. 上面将eslint和prettier配置完了之后,但是要能够自动格式化,那么我们还需要做一些集成。例如,在修改代码保存后,能够自动格式化代码

    打开VScode的配置文件,添加如下配置

    {
      "eslint.alwaysShowStatus": true,
      "editor.formatOnSave": true,
      "[javascript]": {
        "editor.formatOnSave": false
      },
      "[html]": {
        "editor.formatOnSave": false
      },
      "editor.formatOnPaste": false,
      "editor.tabSize": 2,
      "javascript.updateImportsOnFileMove.enabled": "never",
      "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
      }
    }
    

    上面添加配置因为是全局的,为了能够在团队开发时统一,我们也可以为项目单独配置,在项目根目录下创建.vscode文件夹并新建settings.json文件,然后将上面内容拷贝进去

    配置husky

    husky,是一个git hooks工具,它可以再我们代码commit或push的时候做一些事情,以保证我们提交的代码是符合规范的

    1. 安装husky
    $ yarn add husky --dev
    
    1. 在package.json中设置我们需要的git hooks
    "husky": {
        "hooks": {
          "pre-commit": "lint-staged",//commit前检查暂存区文件进行规则校验
          "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",//校验commit时添加的备注信息是否符合我们要求的规范
        }
      },
    

    这里我们需要下面安装几个包

    $ yarn add @commitlint/cli @commitlint/config-conventional lint-staged eslint-plugin-simple-import-sort -D
    

    lint-staged,在代码提交之前,进行代码规则检查能够确保进入git库的代码都是符合代码规则的,如果在整个项目上运行lint速度会很慢,lint-staged能够让lint只检测暂存区的文件,速度很快。

    @commitlint/cli @commitlint/config-conventional,这两个主要是用来规范代码提交的信息

    type支持以下类型:

    • build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
    • ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
    • docs:文档更新
    • feat:新增功能
    • fix:bug 修复
    • perf:性能优化
    • refactor:重构代码(既没有新增功能,也没有修复 bug)
    • style:不影响程序逻辑的代码修改(修改空白字符,补全缺失的分号等)
    • test:新增测试用例或是更新现有测试
    • revert:回滚某个更早之前的提交
    • chore:不属于以上类型的其他类型(日常事务)

    例如:

    $ git commit -m 'feat: 新增xxx功能'
    $ git commit -m 'fix: 修复xxxbug'
    

    如果不符合以上支持type的规范,提交的时候会报错

    1. 根目录下新建.lintstagedrc.js文件
    module.exports = {
      '**/*.{js,jsx,ts,tsx}': [
        'prettier --write',
        'eslint --fix --plugin=simple-import-sort --rule=simple-import-sort/imports:error',
        'git add'
      ],
      '**/*.{json,md,mdx,css,html,yml,yaml,scss}': ['prettier --write', 'git add']
    }
    
    
    1. 根目录下新建.commitlintrc.json文件
    {
      "extends": [
        "@commitlint/config-conventional"
      ]
    }
    
    1. 最后,需要注意的是,配置好了husky之后commit不生效,发现是husky 6.0版本做了破坏性的更新,这里我们通过移除husky包并添加低版本的方式来解决
    $ yarn remove husky 
    $ yarn add husky@4.3.8 -D
    

    Http请求封装

    1. 新一个apiClient.js文件用来配置axios,最后返回axios实例
    import axios from 'axios'
    
    const baseURL = process.env.REACT_APP_BASE_URL
    
    const instance = axios.create({
      baseURL,
      timeout: 15000
    })
    
    // Add a request interceptor
    instance.interceptors.request.use(
      function (config) {
        // Do something before request is sent
        return config
      },
      function (error) {
        // Do something with request error
        return Promise.reject(error)
      }
    )
    
    // Add a response interceptor
    instance.interceptors.response.use(
      function (response) {
        // Any status code that lie within the range of 2xx cause this function to trigger
        // Do something with response data
        return response
      },
      function (error) {
        // Any status codes that falls outside the range of 2xx cause this function to trigger
        // Do something with response error
        return Promise.reject(error)
      }
    )
    
    export default instance
    
    1. 引入apiClient并调用axios的请求方法
    import apiClient from './apiClient'
    
    export const getContractList = () => apiClient.get(`/api/v4/search/top_search`)
    
    1. get、post传参形式

    这里需要注意一点是,get和post传参形式有点区别,get请求传参需要带上params字段

    //get请求
    axios.get('/user', {
        params: {
          ID: 12345
        }
      })
    // post请求
    axios.post('/user', {
        firstName: 'Fred',
        lastName: 'Flintstone'
      })
    

    本地跨域请求

    在src目录下创建setupProxy.js文件配置代理接口,这样我们在请求带有/proxy-api接口的时候,就能代理到http://localhost:3001服务上,从而解决跨域的问题

    const { createProxyMiddleware } = require('http-proxy-middleware')
    
    module.exports = function (app) {
      app.use(
        '/proxy-api',
        createProxyMiddleware({
          target: 'http://localhost:3001',
          changeOrigin: true,
          secure: false,
          pathRewrite: {
            '^/proxy-api': '' // 请求中去除/api
          }
        })
      )
    }
    
    

    搭建本地Mock服务

    1. 根目录下创建mock文件夹,新建server.js文件 ,这里我使用express开启一个node服务
    const express = require('express')
    const app = express()
    const port = 3001
    
    app.use(express.json())
    app.use(express.urlencoded({ extended: false }))
    
    app.get('/', (req, res) => {
      res.send('Hello World!')
    })
    
    // 加载路由
    app.use('/api', require('./test'))
    
    app.listen(port, () => {
      console.log(`mock server listening at http://localhost:${port}`)
    })
    
    
    1. 接口路由,返回mock数据
    var express = require('express')
    var router = express.Router()
    // http://mockjs.com/
    var Mock = require('mockjs')
    
    router.get('/hello', function (req, res) {
      res.json({ user: 'hello' })
    })
    
    router.get('/mock', function (req, res) {
      console.log(req.body)
      var data = Mock.mock({
        top_search: {
          'words|10': [
            {
              query: '一人之下',
              display_query: '《一人之下》565'
            }
          ]
        }
      })
      return res.json(data)
    })
    
    
    module.exports = router
    
    

    1. 访问mock接口数据
    "scripts": {
        "mock": "nodemon ./mock/server.js",
      },
    

    我们在scripts下添加一个mock脚本命令,执行yarn mock就能开启mock服务,例如访问上面接口http://localhost:3001/api/mock

    文章最后

    本文作者阿健Kerry,高级前端工程师,转载请注明出处。如果觉得本文对你有帮助,记得点赞三连哦,也可以扫码关注我新建立的前端技术公众号【有你前端】,之后我所有文章会同步发到这个公众号上面。另外,我建了一个可以帮助咱们程序员脱单的公众号,每周都会推送几个优秀的单身小姐姐,如果你是程序员技术好又正好是单身,那你可以下面扫码关注【缘来你是程序猿】公众号开启你的脱单之旅。

    作者:fozero
    文章出处:https://www.cnblogs.com/fozero
    声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    物理分辨率与逻辑分辨率,pt与px
    JBPM学习(四):执行流程实例
    JBPM学习(三):管理流程定义
    JBPM学习(二):ProcessEngine与Service API
    JBPM学习(一):实现一个简单的工作流例子全过程
    jbpm与spring hibernate struts整合
    代理模式 自己写的
    java反射与代理模式
    使用freemarker生成html
    freemarker 数字,字符的操作
  • 原文地址:https://www.cnblogs.com/fozero/p/14941977.html
Copyright © 2020-2023  润新知