搭建react项目

507 阅读3分钟

前言

搭建react企业级项目框架 react+ts+eslint+react-router+react-redux+sass(包括全局变量自动引入)

工具版本

node     v14.18.1
yarn     v1.22.15

开始搭建

1.安装脚手架create-react-app

// yarn/npm安装
yarn global add create-react-app     
npm install -g create-react-app

2.初始化项目

npx create-react-app my-app --template typescript
cd my-app // 进入新建项目
code .   //使用vscode打开项目
// 删除多余文件,项目目录如下所示

3.安装eslint(使用airbnb规范)

3.1安装插件

npx install-peerdeps --dev eslint-config-airbnb

3.2配置 .eslintignore 忽略文件(根目录下创建此文件)

在该文件中配置不需要被 ESLint 检测的文件

/.git//.vscode/node_modules//dist/

4.安装Perttier

4.1安装插件

yarn add --dev prettier
yarn add --dev stylelint-config-prettier
yarn add --dev eslint-config-prettier
yarn add --dev eslint-plugin-prettier

4.2配置规则 

根目录下新建.prettierrc.js文件

module.exports = {    tabWidth: 4,    printWidth: 140,    singleQuote: true,    endOfLine: 'auto'}

5.eslint+perittier规则文件配置(3-4完成后添加此文件)

根目录下新建.eslintrc.js

module.exports = {    extends: ['airbnb', 'airbnb/hooks', 'prettier'],    parser: '@typescript-eslint/parser', // ESLint默认使用esprima作为其解析器,也可以在配置文件中指定一个不同的解析器(它必须是一个Node模块,且它必须符合parserinterface)    env: {        // 要在配置文件里指定环境,使用env关键字指定你想启用的环境,并设置它们为true        browser: true,        node: true,        mocha: true,        es6: true,        commonjs: true    },    globals: {        // 要在配置文件中配置全局变量,对于每个全局变量键,将对应的值设置为"writable"以允许重写变量,或"readonly"不允许重写变量        // "Babel":"writable",        // "React":"writable"    },    plugins: [        // 在配置文件里配置插件时,可以使用plugins关键字来存放插件名字的列表。插件名称可以省略eslint-plugin-前缀。        'react',        'jsx-a11y',        'react-hooks',        'import',        'prettier'    ],    rules: {        indent: ['error', 4],        semi: [            'error',            'always',            {                omitLastInOneLineBlock: true            }        ],        'react/jsx-indent': ['error', 4],        'no-use-before-define': 'off',        'linebreak-style': ['off', 'windows'],        'react/jsx-filename-extension': [            'error',            {                extensions: ['.js', '.jsx', '.ts', '.tsx']            }        ],        'class-methods-use-this': 'off',        'import/extensions': 'off',        'import/no-unresolved': 'off'        // 'prettier/prettier': [        //     'error',        //     {        //         trailingComma: 'es5',        //         singleQuote: true,        //         printWidth: 100,        //         tabWidth: 4,        //         semi: true,        //         endOfLine: 'auto',        //     },        // ],    }};

配置完毕请重启编辑器vscode!!!

6.全局配置sass

6.1安装插件 请安装固定版本sass否则会出现兼容问题

yarn add --dev node-sass@4.14.1 sass-loader@6.0.1
yarn add customize-cra react-app-rewired sass-resources-loader

6.2配置文件

根目录下新建config-overrides.js文件,导入scss文件路径请自行修改

const { override, adjustStyleLoaders, addWebpackAlias } = require('customize-cra');const path = require('path');module.exports = override(    // 配置指定文件为sass全局文件,可以不用导入就可以使用    adjustStyleLoaders((rule) => {        if (rule.test.toString().includes('scss')) {            rule.use.push({                loader: require.resolve('sass-resources-loader'),                options: {                    resources: ['./src/assets/public.scss']                }            });        }    }),    addWebpackAlias({        '@': path.resolve(__dirname, './src')    }));

修改package.json文件

"scripts": {        "start": "set PORT=8888&&react-app-rewired start",        "build": "react-app-rewired build",        "test": "react-app-rewired test",        "eject": "react-app-rewired eject"},

public.scss文件

$defaultColor: red;

index.scss引用无需导入public.scss文件

.App{    background-color: $defaultColor;}

7.安装router

7.1安装插件

yarn add react-router-dom
yarn add --dev @types/react-router-dom // 解决ts类型报错

7.2创建router文件夹-index.ts文件

import React from 'react';const Home = React.lazy(() => import('../page/login'));const routes = [    {        path: '/login',        component: Home    }];export default routes;

7.3修改App.tsx

import React, { Suspense } from 'react';import { BrowserRouter as Router, Route } from 'react-router-dom';import routes from './router';import './index.scss';function App() {    return (        <div className="App">            <Suspense fallback={<div />}>                <Router>                    <div>                        {routes.map((route) => (                            <Route key={route.path} path={route.path} component={route.component} />                        ))}                    </div>                </Router>            </Suspense>        </div>    );}export default App;

8.安装redux

8.1安装插件

yarn add redux react-redux

8.2配置

创建store文件夹-index.ts

import { createStore } from 'redux';import reducers from './reducers';import initState from './state';const store = createStore(reducers, initState);export default store;

state.ts文件

const initState = {    card: {        name: 'Jack'    },    dialog: {        status: false    }};export default initState;

reducers文件夹-index.ts文件

import { combineReducers } from 'redux';import initState from '../state';function card(state: any = initState, action: any) {    switch (action.type) {    case 'CHANGE_NAME':        return {            name: action.name // 使用action携带的新name        };    default:        return state; // 没有匹配的action type,返回原来的state    }}function dialog(state: any = initState, action: any) {    switch (action.type) {    case 'SHOW_DIALOG':        return {            status: true        };    case 'CLOSE_DIALOG':        return {            status: false        };    default:        return state; // 没有匹配的action type,返回原来的state    }}export default combineReducers({    card,    dialog});

修改入口文件index.tsx

import React from 'react';import ReactDOM from 'react-dom';import { Provider } from 'react-redux';import App from './App';import store from './store';ReactDOM.render(    <Provider store={store}>        <React.StrictMode>            <App />        </React.StrictMode>    </Provider>,    document.getElementById('root'));

login.tsx同目录下创建widthStore.ts

function mapStateToProps(state: any) {    return state;}function mapDispatchToProps(dispatch: any) {    return {        changeName() {            dispatch({                type: 'CHANGE_NAME',                name: '葬爱'            });        },        showDialog() {            dispatch({                type: 'SHOW_DIALOG'            });        }    };}export { mapStateToProps, mapDispatchToProps };

修改login.tsx

import React from 'react';import { connect } from 'react-redux';import { mapStateToProps, mapDispatchToProps } from './widthStore';interface TypePorps {    card: any;    dialog: any;    showDialog: Function;}function Login(props: TypePorps) {    const { card, dialog, showDialog } = props;    const { name } = card;    const { status } = dialog;    return (        <div className="login" onClick={() => showDialog()} aria-hidden="true">            login{name}            {status ? 'true' : 'false'}        </div>    );}export default connect(mapStateToProps, mapDispatchToProps)(Login);

9.项目地址

github.com/wangxiangsh…