Nuevo proyecto de 0-1, versión completa de react+ts

Directorio de artículos


prefacio

Resume una serie de comandos y pasos de instalación para crear un proyecto desde 0


提示:以下是本篇文章正文内容,下面案例可供参考

En primer lugar, la construcción del entorno.

1. Instala node.js

        Dirección del sitio web oficial: Node.js

2. Instalar hilo 

La premisa de la instalación yarnes que primero debe instalarse npmy las variables de entorno se han configurado antes de que pueda usarse.

下载全局安装
npm install yarn -g  
安装完检查版本 
yarn --version 、
配置镜像源
yarn config set registry https://registry.npm.taobao.org -g
yarn config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/ -g
检查镜像源
yarn config get registry // https://registry.npm.taobao.org
yarn config get sass_binary_site // https://npm.taobao.org/mirrors/node-sass/


一些常用的yarn 的命令
yarn init // 生成package.json文件
yarn install // 安装yarn.lock的所有依赖
yarn install --force // 重新安装依赖
yarn remove moduleName // 删除依赖
yarn add moduleName // 安装某个依赖
yarn add moduleName --dev/-D // 安装到开发环境
yarn run scriptName // 执行package.json命名的脚本命令

2. Instala el proyecto de reacción

1. Instalar reaccionar + ts

        npx create-react-app my-app --template typescript
        npx create-react-app <项目名> --template typescript
        npm init @vitejs/app <项目名称>--template react-ts

 La siguiente instalación opcional

2. Instalar detección de código eslint

yarn add eslint
npx eslint --init

Aparecerán tres elementos después de la inicialización de eslint, según el proyecto

1. ¿Qué tipo de eslint usar? (Aquí elijo 3)

To check syntax only // 只检测语法性错误
To check syntax and find problems // 检查语法错误并发现问题代码
To check syntax, find problems, and enforce code style // 检查语法错误,发现问题代码,校验代码风格

2. ¿Qué tipo de módulos utiliza el proyecto? (Aquí elijo 1)

JavaScript modules (import/export) // 允许import/export
CommonJS (require/exports) // 允许require/exports
None of these // 没有任何模块化

3. ¿Qué marco utiliza el proyecto ? (elija 1)

React
Vue.js
None of these

4. El proyecto utiliza Ts? (Sí)

Does your project use TypeScript? › No / Yes

5. ¿Entorno de ejecución de código? (navegador)

Browser // 浏览器
Node // node环境

6. ¿Cómo definir el estilo de definición del artículo? (utilizando guías de estilo populares)

Use a popular style guide // 使用流行的风格指南
Answer questions about your style // 问答定义形成一个风格

7. ¿Qué estilo popular sigues? (Se puede definir de acuerdo a las necesidades de tu proyecto, elijo Airbnb)

Airbnb: https://github.com/airbnb/javascript
Standard: https://github.com/standard/standard
Google: https://github.com/google/eslint-config-google
XO: https://github.com/xojs/eslint-config-xo

8. ¿En qué formato quiere que esté su archivo de configuración? (JavaScript, otros pueden ser Baidu por ti mismo)

JavaScript
YAML
JSON

9. ¿Los estás instalando ahora? (Sí, hilo)

9、你现在就安装他们吗?(Yes,yarn)

Una vez completada la instalación, el archivo .eslitrc.js se generará en el directorio raíz del proyecto y luego cambiará las reglas (puede aumentar o disminuir las reglas según sus necesidades)

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'plugin:react/recommended',
    'airbnb',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      tsx: true,
    },
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  plugins: [
    'react',
    '@typescript-eslint',
  ],
  rules: {
    'react/jsx-filename-extension': [
      2,
      { 'extensions': ['ts', 'tsx'] }
    ],
    'import/no-unresolved': 0,
    'import/extensions': 0,
    
    // 最后一个对象属性要有逗号
    'comma-dangle': 1,
    
    // 定义但从未使用的变量
    'no-unused-vars': 1,
    
    // 赋值但从未使用
    'react/jsx-no-bind': 1,
    
    // 空标签
    'react/self-closing-comp': 0,
    
    // 具有单击处理程序的可见非交互元素必须至少有一个键盘侦听器
    'jsx-a11y/click-events-have-key-events': 0,
    
    // 具有“按钮”交互作用的元素必须是可聚焦的
    'jsx-a11y/interactive-supports-focus': 0,
    
    // 带有事件处理程序的静态HTML元素需要一个角色
    'jsx-a11y/no-static-element-interactions': 0,
    
    // return ;
    'semi-spacing': 0,
    
    // <>只包含不能只包含一个标签
    'react/jsx-no-useless-fragment': 0,
    
    // 值对于布尔属性必须省略
    'react/jsx-boolean-value': 0,
    
    // 必须默认导出
    'import/prefer-default-export': 0,
    
    // 默认变量放到最后一个
    'default-param-last': 0,
    
    // 对参数进行赋值
    'no-param-reassign': 0,
    
    // 使用未声明的函数
    'no-use-before-define': 0,
    
    'no-new': 0,
    
    // 不能使用自增
    'no-plusplus': 0,
    
    // button必须是静态type
    'react/button-has-type': 0,
  },
};

        Agregue @alias para apuntar al directorio src (React no tiene @alias como vue por defecto) modifique el archivo config-overrides.js, el código es el siguiente

const {
  override,
  addWebpackAlias,
  addWebpackModuleRule,
} = require('customize-cra');
const path = require('path');

module.exports = override(
  // @别名
  addWebpackAlias({
    '@': path.resolve('./src'),
  }),

  // scss全局变量
  addWebpackModuleRule({
    test: /\.scss$/,
    use: [
      'style-loader',
      'css-loader',
      'sass-loader',
      {
        loader: 'sass-resources-loader',
        options: {
          resources: ['./src/assets/scss/varable.scss'],
        },
      },
    ],
  }),
);

Luego cambie el código en el archivo tsconfig.json en el directorio raíz de la siguiente manera

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    },
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

3. Operación del proyecto

Debido a que eslist se abre directamente, eslist se informará cuando se ejecute directamente. El proyecto predeterminado debe cambiarse en dos lugares.

instalar antd 

yarn add antd 

主入口引入样式
import “antd/dist/antd.css”   
这种情况会有警告
出现这个问题是因为 react-script 升级到5.0.0.
通过npx create-react-app 创建的项目,
引入antd.css 之后会看到这个警告。


解决方法就是
import “antd/dist/antd.css”
替换为
import “antd/dist/antd.min.css”

1. Cambie el archivo App.tsx a

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

2. Primero cambie el archivo package.json (busque los scripts y cámbielo al siguiente código)

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-scripts eject"
},

3. Luego ejecuta el proyecto directamente con yarn start

4. Estructura del marco del proyecto

|- node_modules // 项目依赖包
|- public // 一般用于存放静态文件,打包时会被直接复制到输出目录(./buidle)
|- src // 项目源代码
  |  |- assets // 静态资源文件夹,用于存放静态资源,打包时会经过 webpack 处理
  |  |- components // 组件文件夹,存放 React 组件,一般是该项目公用的无状态组件
          |  |- MLayout
                  |  |- MLayout.js
                  |  |- MLayout.module.less
  |  |- containers // 页面视图文件夹
          |  |- Index
                  |  |- Index.js
                  |  |- Index.module.less
  |  |- redux // redux文件夹
          |  |- actions
                  |  |- actions.js
          |  |- reducers
                  |  |- reducers.js
          |  |- store
                  |  |- store.js
          |  |- state.js
  |  |- router // 路由配置文件夹
          |  |- router.js // 路由文件配置
  |  |- service // 服务请求文件夹
          |  |- http.js // 请求接口文件
          |  |- request.js // 请求配置文件
  |  |- App.js // 入口文件
  |  |- App.less
  |  |- index.js //注册路由与服务
  |  |- index.css
  |  |- serviceWorker //开发配置
|- .env // 环境配置文件
|- .env.development // dev环境配置文件
|- .env.test // test环境配置文件
|- .env.production // prd环境配置文件
|- craco.config.js // craco配置文件
|- package.json // 包管理代码
|- .gitignore // Git忽略文件

Cinco, integración y configuración de uso común

1. React  Router (gestión de configuración de enrutamiento)

React Router es una poderosa biblioteca de enrutamiento basada  en React  que le permite agregar rápidamente vistas y flujos de datos a su aplicación mientras mantiene sincronizadas las páginas y las URL.

1.1 Instalar el enrutador de reacción

npm install [email protected] --save
或者用 yarn add 

Solo puede haber una etiqueta de cuadro debajo del enrutador, similar al div aquí. 
Enlace representa un enlace, que se analizará en una etiqueta en la interfaz html. Como enlace, debe haber un atributo to, que representa la dirección del enlace. Esta dirección de enlace es una ruta relativa. 
Ruta, que tiene un atributo de ruta y un atributo de componente (puede ser componente, representación, etc.).

uso básico

render () {
    return (
          <Router>
             <div>
                <ul>
                   <li><Link to="/index">首页</Link></li>
                   <li><Link to="/other">其他页</Link></li>
                 </ul>
                 <Route path="/index" component={Index}/>
                 <Route path="/other" component={Other}/>
             </div>
          </Router>
    )
}

Uso anidado de enrutamiento

const Test = () => (
   <div>
      <Switch>
         <Route
            path="/"
            render={props => (
               <App>
                  <Switch>
                     <Route path="/" exact component={Index} />
                     <Route path="/index" component={Index} />
                     <Route path="/other" component={Other} />
                     <Route path="/message/:id/:TestId" component={Message} />
                      {/*路由不正确时,默认跳回home页面*/}
                     <Route render={() => <Redirect to="/" />} />
                  </Switch>
               </App>
            )}
         />
      </Switch>
   </div>
);
 
export default Test;

Escriba la ruta de enrutamiento en un archivo de configuración router.js, el código de muestra es el siguiente

import Login from '../containers/Login/Login.js';
import Index from '../containers/Index/Index.js';
import Home from '../containers/Home.js';
import New from '../containers/New.js';
import NewOne from '../containers/NewOne.js';
 
let routes = [
  {
    path: "/",
    component: Home,
    exact: true
  },
  {
    path: "/login",
    component: Login,
    exact: true
  },
  {
    path: "/index",
    component: Index,
    exact: true
  },
  {
    path: "/news",
    component: New,
    routes: [  // 嵌套路由
      {
        path: "/news/newsone",
        component: NewOne,
        exact: true
      }
    ]
  }
];
 
export default routes;

Importar y usar en App.js 

import './App.less';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import routes from './router/router';
import Home from './containers/Home.js';
 
// 默认语言为 en-US,如果你需要设置其他语言,推荐在入口文件全局设置 locale
import moment from 'moment';
import 'moment/locale/zh-cn';
import locale from 'antd/lib/locale/zh_CN';
import { ConfigProvider } from 'antd';
 
function App() {
  return (
    <ConfigProvider locale={locale}>
      <div className="App">
      <Router>
        <Switch>
        {
          routes.map((route, key) => {
            console.log(route)
            if (route.exact) {
              return <Route key={key} exact path={route.path} component={route.component}/>
            } else {
              return <Route key={key} path={route.path}
                render={props => <route.component {...props} routes={route.routes} />
              }/>
            }
          })
        }
        <Route component={Home}/>
        </Switch>
      </Router>
      </div>
    </ConfigProvider>
  );
}
 
export default App;

new.js (página principal)

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
 
function New(props) {
  return <div>
    new
    {
      props.routes.map((route, key) => {
        console.log(route.path)
        return <Route key={key} exact path={route.path} component={route.component}/>
      })
    }  
  </div>
}
 
export default New

newOne.js (subpáginas anidadas)

function NewOne() {
  return <div>new one</div>
}
 
export default NewOne

2. redux (gestión de datos) 

Detalles de uso del proyecto Redux

React es un flujo de datos unidireccional, por lo que, en algunos casos, confiar solo en React no puede lograr la comunicación entre los componentes, por lo que se necesita redux .

Las dependencias relacionadas con Redux deben instalarse. Dado que puede haber problemas de compatibilidad entre diferentes versiones, es mejor especificar la versión al instalar. Después de la instalación, puede introducir redux en el proyecto.

npm install [email protected] --save
 
npm install [email protected] --save
 
npm install [email protected] --save

state.js (declarar valores predeterminados de variables)

// state的默认值统一放置在state.js文件
 
// state.js
// 声明默认值
// 这里我们列举两个示例
// 同步数据:pageTitle
// 异步数据:infoList(将来用异步接口获取)
 
export default {
  pageTitle: '首页',
  infoList: []
}

actions.js (define eventos desencadenantes)

// actions.js
// action也是函数
 
export function increaseAction (data) {
  return (dispatch, state) => {
    dispatch({ type: 'increase', data: data })
  }
}
 
export function setInfoList (data) {
  return (dispatch, getState) => {
    // // 使用fetch实现异步请求
    // window.fetch('/api/getInfoList', {
    //     method: 'GET',
    //     headers: {
    //         'Content-Type': 'application/json'
    //     }
    // }).then(res => {
    //     return res.json()
    // }).then(data => {
    //     let { code, data } = data
    //     if (code === 0) {
    //         dispatch({ type: 'SET_INFO_LIST', data: data })
    //     }
    // })
  }
}

 reducers.js (obtener y procesar datos)

// reducers.js
// 工具函数,用于组织多个reducer,并返回reducer集合
import { combineReducers } from 'redux'
// 默认值
import defaultState from '../state.js'
 
// 一个reducer就是一个函数
function pageTitle (state = defaultState.pageTitle, action) {
  // 不同的action有不同的处理逻辑
  switch (action.type) {
    case 'SET_PAGE_TITLE':
      return action.data
    default:
      return state
  }
}
 
function infoList (state = defaultState.infoList, action) {
  switch (action.type) {
    case 'SET_INFO_LIST':
      return action.data
    default:
      return state
  }
}
 
// 导出所有reducer
export default combineReducers({
    pageTitle,
    infoList
})

store.js (crear instancia de tienda)

// applyMiddleware: redux通过该函数来使用中间件
// createStore: 用于创建store实例
 
// 中间件,作用:如果不使用该中间件,当我们dispatch一个action时,
// 需要给dispatch函数传入action对象;但如果我们使用了这个中间件,那么就可
// 以传入一个函数,这个函数接收两个参数:dispatch和getState。这个dispatch可
// 以在将来的异步请求完成后使用,对于异步action很有用
 
import { applyMiddleware, createStore } from 'redux'
import thunk from 'redux-thunk'
// 引入reducer
import reducers from '../reducers/reducers.js'
 
 
// 创建store实例
let store = createStore(
  reducers,
  applyMiddleware(thunk)
)
 
export default store

Se utiliza en el archivo raíz index.js para representar la aplicación del componente contenedor en el elemento de destino

El proveedor de componentes aquí es un componente especial en react-redux

1. Solo hay un subcomponente en el Proveedor (aquí está el componente contenedor de la aplicación, no necesariamente el componente contenedor, opere usted mismo de acuerdo con sus propias necesidades comerciales)

2. La ventaja de usar el componente Proveedor es que solo necesita establecer propiedades para el componente Proveedor, luego sus subcomponentes y los subcomponentes en sus subcomponentes pueden usar directamente sus propiedades correspondientes

3. Evite la complicada operación de pasar componentes uno por uno después de anidar
 

import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
 
// Provider是react-redux两个核心工具之一,作用:将store传递到每个项目中的组件中
// 第二个工具是connect,稍后会作介绍
import { Provider } from 'react-redux'
// 引入创建好的store实例
import store from './redux/store/store.js'
 
ReactDOM.render(
  <div>
    {/* 将store作为prop传入,即可使应用中的所有组件使用store */}
    <Provider store = {store}>
      <App />
    </Provider>
  </div>,
  document.getElementById('root')
);
 
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 Usar en la página de la interfaz de usuario

import { Layout, Button, Form, Input } from 'antd';
import style from './Login.module.less';
import { useRef } from 'react'
 
// connect方法的作用:将额外的props传递给组件,并返回新的组件,组件在该过程中不会受到影响
import { connect } from 'react-redux';
// 引入action
import { increaseAction, setInfoList } from '../../redux/actions/actions.js'
 
const { Header, Footer, Content } = Layout;
 
function Login(props) {
 
  const formRef = useRef(null);
 
  const onReset = () => {
    formRef.current.resetFields();
  };
 
  const onFinish = (values) => {
    console.log('Success:', values);
    props.history.push('/index')
  };
 
  const onFinishFailed = (errorInfo) => {
    console.log('Failed:', errorInfo);
  };
  
 
  return <Layout style={
   
   {height: '100vh'}}>
            ...省略代码
          </Layout>
}
 
// mapStateToProps:将state映射到组件的props中
const mapStateToProps = (state) => {
  return {
    pageTitle: state.pageTitle,
    infoList: state.infoList
  }
}
// mapDispatchToProps:将dispatch映射到组件的props中
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    increaseAction (data) {
        // 如果不懂这里的逻辑可查看前面对redux-thunk的介绍
        dispatch(increaseAction(data))
        // 执行increaseAction会返回一个函数
        // 这正是redux-thunk的所用之处:异步action
        // 上行代码相当于
        /*dispatch((dispatch, getState) => {
            dispatch({ type: 'SET_PAGE_TITLE', data: data })
        )*/
    },
    setInfoList (data) {
        dispatch(setInfoList(data))
    }
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(Login)

3. configuración de axios

Axios es una biblioteca HTTP basada en promesas que se puede usar en el navegador y en node.js.

Instalar

npm install axios

Código de muestra

solicitud.js

import axios from 'axios'
 
const BASE_URL = process.env.BASE_URL;
const TIMEOUT = 5000;
 
const instance = axios.create({    // 创建axios实例,在这里可以设置请求的默认配置
  timeout: TIMEOUT, // 设置超时时间
  baseURL: BASE_URL // 根据自己配置的反向代理去设置不同环境的baeUrl
})
 
// 文档中的统一设置post请求头。下面会说到post请求的几种'Content-Type'
instance.defaults.headers.post['Content-Type'] = 'application/json'
 
let httpCode = {        //这里我简单列出一些常见的http状态码信息,可以自己去调整配置
  400: '请求参数错误',
  401: '权限不足, 请重新登录',
  403: '服务器拒绝本次访问',
  404: '请求资源未找到',
  500: '内部服务器错误',
  501: '服务器不支持该请求中使用的方法',
  502: '网关错误',
  504: '网关超时'
}
 
/** 添加请求拦截器 **/
instance.interceptors.request.use(config => {
  config.headers['token'] = sessionStorage.getItem('token') || ''
  // hide = message.loading({content: 'Loading...', duration: 0});
  // 在这里:可以根据业务需求可以在发送请求之前做些什么:例如我这个是导出文件的接口,因为返回的是二进制流,所以需要设置请求响应类型为blob,就可以在此处设置。
  if (config.url.includes('pur/contract/export')) {
    config.headers['responseType'] = 'blob'
  }
  // 我这里是文件上传,发送的是二进制流,所以需要设置请求头的'Content-Type'
  if (config.url.includes('pur/contract/upload')) {
    config.headers['Content-Type'] = 'multipart/form-data'
  }
  return config
}, error => {
  // 对请求错误做些什么
  return Promise.reject(error)
})
 
/** 添加响应拦截器  **/
instance.interceptors.response.use(response => {
  // hide()
  if (response.statusText === 'ok') {     // 响应结果里的statusText: ok是我与后台的约定,大家可以根据实际情况去做对应的判断
    return Promise.resolve(response.data)
  } else {
    message.error('响应超时')
    return Promise.reject(response.data.message)
  }
}, error => {
  // hide()
  if (error.response) {
      // 根据请求失败的http状态码去给用户相应的提示
      // let tips = error.response.status in httpCode ? httpCode[error.response.status] : error.response.data.message
      // message.error(tips)
      if (error.response.status === 401) {    // token或者登陆失效情况下跳转到登录页面,根据实际情况,在这里可以根据不同的响应错误结果,做对应的事。这里我以401判断为例
        // 针对框架跳转到登陆页面
        this.props.history.push(LOGIN);
      }
      return Promise.reject(error)
  } else {
      message.error('请求超时, 请刷新重试')
      return Promise.reject('请求超时, 请刷新重试')
  }
})
 
/* 统一封装get请求 */
export const get = (url, params, config = {}) => {
  return new Promise((resolve, reject) => {
    instance({
        method: 'get',
        url,
        params,
        ...config
    }).then(response => {
        resolve(response)
    }).catch(error => {
        reject(error)
    })
  })
}
 
/* 统一封装post请求  */
export const post = (url, data, config = {}) => {
  return new Promise((resolve, reject) => {
    instance({
      method: 'post',
      url,
      data,
      ...config
    }).then(response => {
      resolve(response)
    }).catch(error => {
      reject(error)
    })
  })
}

http.js

import {get, post} from './request'
 
export const requestIndex = () => {
    return get('api/index').then((res) => {
        // return res.data
        console.log(res)
    })
}

4. Componentes de la interfaz de usuario 

Aquí se recomiendan dos componentes de interfaz de usuario basados ​​en React, uno es Ant Design de Ant Financial y el otro es Material-UI .

Ambos son bastante buenos, y aquí se usa Ant Design.

Instalar

npm install antd --save

 Modificar  src/App.jse introducir componentes antd

import React from 'react';
import { Button } from 'antd';
import './App.css';
 
const App = () => (
  <div className="App">
    <Button type="primary">Button</Button>
  </div>
);
 
export default App;

Configuración avanzada

En este ejemplo, todavía hay espacio para la optimización en el desarrollo real, como la imposibilidad de configurar el tema.

En este punto, debemos personalizar la configuración predeterminada de create-react-app, aquí usamos craco (una solución comunitaria para la configuración personalizada de create-react-app).

Ahora instalamos craco y modificamos la propiedad de scripts en package.json.
 

npm install @craco/craco
/* package.json */
"scripts": {
-   "start": "react-scripts start",
-   "build": "react-scripts build",
-   "test": "react-scripts test",
+   "start": "craco start",
+   "build": "craco build",
+   "test": "craco test",
}

Luego cree uno en el directorio raíz del proyecto  craco.config.js para modificar la configuración predeterminada.

/* craco.config.js */
module.exports = {
  // ...
};

 tema personalizado

De acuerdo con los requisitos de configuración del tema, los temas personalizados deben usar la función de cobertura menos variable similar a la proporcionada por less-loader. Podemos introducir craco-less para ayudar a cargar menos estilos y modificar variables.

Primero, modifique el archivo src/App.css a src/App.less y luego modifique la referencia de estilo al archivo less.
 

/* src/App.js */
- import './App.css';
+ import './App.less';
/* src/App.less */
- @import '~antd/dist/antd.css';
+ @import '~antd/dist/antd.less';

 Luego instale  craco-less y modifique  craco.config.js el archivo de la siguiente manera

npm install craco-less
const CracoLessPlugin = require('craco-less');
 
module.exports = {
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            modifyVars: { '@primary-color': '#1DA57A' },
            javascriptEnabled: true,
          },
        },
      },
    },
  ],
};

Aquí, modifyVars de less-loader se usa para configurar el tema. Las variables y otros métodos de configuración pueden consultar el documento de configuración del tema. Reinicie npm start después de la modificación, si ve un botón verde, la configuración se realizó correctamente.

antd tiene un tema oscuro y un tema compacto integrados, puede consultar el uso del tema oscuro y el tema compacto para acceder.

expulsar

También puede usar el comando de expulsión de ejecución de hilo proporcionado por create-react-app para exponer todas las configuraciones integradas. Sin embargo, este método de configuración requiere que lo explore usted mismo, lo cual está más allá del alcance de este artículo.

5, craco

Instalar

$ yarn add @craco/craco
 
# OR
 
$ npm install @craco/craco --save

2. Cree un nuevo craco.config.jsarchivo en el directorio raíz del proyecto

3. Modifique  package.jsonla configuración de inicio en

/* package.json */
"scripts": {
-   "start": "react-scripts start",
+   "start": "craco start",
-   "build": "react-scripts build",
+   "build": "craco build",
-   "test": "react-scripts test",
+   "test": "craco test",
}

A través de los 3 pasos anteriores, la configuración del paquete web se puede expandir y luego se puede configurar de acuerdo con las necesidades.

Código de muestra:

/* craco.config.js */
/**
 * TODO: 区分环境 —— NODE_ENV
 * - whenDev ☞ process.env.NODE_ENV === 'development'
 * - whenTest ☞ process.env.NODE_ENV === 'test'
 * - whenProd ☞ process.env.NODE_ENV === 'production'
 */
 
const CracoLessPlugin = require('craco-less');
const CompressionPlugin = require("compression-webpack-plugin");
 
const path = require('path')
const pathResolve = pathUrl => path.join(__dirname, pathUrl)
 
console.log(process.env)
const dev = process.env.REACT_APP_ENV === 'development'
const test = process.env.REACT_APP_ENV === 'test'
const prod = process.env.REACT_APP_ENV === 'production'
const outputDirName = dev ? 'dev-dist' : (test ? 'test-dist' : 'dist')
 
 
module.exports = {
  webpack: {
    // 别名配置
    alias: {
      '@': pathResolve('src'),
    },
    /**
     * 重写 webpack 任意配置
     *  - configure 能够重写 webpack 相关的所有配置,但是,仍然推荐你优先阅读 craco 提供的快捷配置,把解决不了的配置放到 configure 里解决;
     *  - 这里选择配置为函数,与直接定义 configure 对象方式互斥;
     */
    configure: (webpackConfig, {
      env, paths
    }) => {
      // paths.appPath='public'
      paths.appBuild = outputDirName // 配合输出打包修改文件目录
        // webpackConfig中可以解构出你想要的参数比如mode、devtool、entry等等,更多信息请查看webpackConfig.json文件
        /**
         * 修改 output
         */
      webpackConfig.output = {
        ...webpackConfig.output,
          path: path.resolve(__dirname, outputDirName), // 修改输出文件目录
          publicPath: process.env.REACT_APP_PUBLICPATH // 设置的是部署应用包的基本 URL,不是项目打包出来的文件存放的位置
      }
      
      // 返回重写后的新配置
      return webpackConfig
    },
    plugins: [
      // compression-webpack-plugin 因为版本问题,2.x将 asset 改为了 filename
      new CompressionPlugin({
        filename: '[path].gz[query]', // 目标资源名称。[file] 会被替换成原资源。[path] 会被替换成原资源路径,[query] 替换成原查询字符串
        algorithm: 'gzip', // 算法       
        test: new RegExp('\\.(js|css)$'), // 压缩 js 与 css
        threshold: 10240, // 只处理比这个值大的资源。按字节计算
        minRatio: 0.8 // 只有压缩率比这个值小的资源才会被处理
      }),
    ]
  },
  plugins: [
    {
      plugin: CracoLessPlugin,
      options: {
        lessLoaderOptions: {
          lessOptions: {
            modifyVars: { 
              // '@primary-color': '#1DA57A',
              '@heading-color': '#1890ff' // 标题色
            },
            javascriptEnabled: true,
          },
        },
      },
    }
  ],
  // devServer: {
  //   port: 9000,
  //   proxy: {
  //     '/api': {
  //       target: 'https://placeholder.com/',
  //       changeOrigin: true,
  //       secure: false,
  //       xfwd: false,
  //     }
  //   }
  // }
};

6. Empaquetado multientorno y configuración de ejecución

1.1 Entorno incorporado

Hay una  NODE_ENV variable de entorno integrada especial llamada . Puedes leerlo process.env.NODE_ENV desde .

Cuando corres  npm start siempre es igual a 'development' 

Cuando corres  npm test siempre es igual a 'test' 

Cuando ejecuta  npm run build para generar un paquete de producción, siempre es igual a 'production' 

No puede anularlo manualmente NODE_ENV.  Esto evita que los desarrolladores implementen por accidente compilaciones de desarrollo lento en producción.

Agregue variables de entorno de desarrollo en  .env :

REACT_APP_BASE_URL=123
REACT_APP_ENV=desarrollo

  

NOTA: Debe  REACT_APP_ crear variables de entorno personalizadas que comiencen con . Cualquier otra variable que no sea  NODE_ENV .será ignorada para evitar exponer accidentalmente la clave privada en una computadora que podría tener el mismo nombre . Cambiar cualquier variable de entorno requiere reiniciar el servidor de desarrollo en ejecución.

De hecho, mirando la documentación oficial de create-react-app, podemos encontrar que create-react-app admite múltiples archivos de configuración de entorno de forma predeterminada:

  • .env: predeterminado.
  • .env.local: anulaciones locales. Todos los entornos, excepto la prueba, cargan este archivo.
  • .env.development, .env.test, .env.production: Establecer entornos específicos.
  • .env.development.local, .env.test.local, .env.production.local: establezca anulaciones locales específicas del entorno.
  • Los archivos de la izquierda tienen mayor prioridad que los archivos de la derecha:
  • inicio de npm: .env.desarrollo.local, .env.desarrollo, .env.local, .env
  • npm ejecutar compilación: .env.production.local, .env.production, .env.local, .env
  • Prueba npm: .env.test.local, .env.test, .env (tenga en cuenta que no hay .env.local)

1.2, dotenv

Podemos usar  dotenv  para administrar las variables de entorno ( dotenv las variables de entorno se pueden cargar desde archivos .env  process.env)

Instalar dotenv-cli:

npm install dotenv-cli -g

Modifique el comando en package.json

"scripts": {
    "dev": "GENERATE_SOURCEMAP=false cross-env PORT=5000 craco start",
    "test": "craco test",
    "prd": "dotenv -e .env.production craco start",
    "build": "craco build",
    "build:dev": "dotenv -e .env.development craco build",
    "build:test": "dotenv -e .env.test craco build",
    "start-old": "cross-env PORT=5000 react-scripts start",
    "build-old": "react-scripts build",
    "test-old": "react-scripts test",
    "eject": "react-scripts eject"
  },

7. Usar proxy proxy (http-proxy-middleware)

Instalar

npm install http-proxy-middleware

Cree un archivo src/setupProxy.js para configurar varios proxies

const proxy = require("http-proxy-middleware");
 
module.exports = function(app) {
  app.use(
    proxy("/base/**", {
      target: "http://45.32.15.21:8090/",
      changeOrigin: true
    })
  );
  app.use(
    proxy("/fans/**", {
      target: "https://easy-mock.com/mock/5c0f31837214cf627b8d43f0/",
      changeOrigin: true
    })
  );
};

Documentación de referencia de aprendizaje:
documentación china oficial de React: una biblioteca de JavaScript para crear interfaces de usuario

Crea la documentación en chino de la aplicación React · Crea aplicaciones web modernas ejecutando un solo comando.

Introducción | Documentación en chino de React Router

React Router: enrutamiento declarativo para React.js

Tutorial de React Router: blog de Ruan Yifeng

Ant Design: el segundo framework React UI más popular del mundo

Documentación china Redux

Tutorial de introducción a Redux (1): Uso básico - Ruan Yifeng's Weblog

Tutorial introductorio de Redux (3): El uso de React-Redux - Ruan Yifeng's Weblog

sitio web en chino de axios | documentación en chino de la API de axios | axios


Resumir

Este contenido es para su propia referencia y aprendizaje, si hay alguna modificación, se actualizará con el tiempo.

Supongo que te gusta

Origin blog.csdn.net/weixin_66709443/article/details/127515162
Recomendado
Clasificación