create React App

Create React App
创建项目
TypeScript模版增加配置请查看

# 默认创建项目
yarn create react-app <项目名>

# 使用typescript创建项目
yarn create react-app <项目名> --template typescript
优化package.json
将原来的dependencies、scripts改为以下

{
  "scripts": {
    "dev": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "dependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "react-scripts": "3.4.1"
  }
}
跨域代理
在package.json中添加

{
  "proxy": "http://192.168.0.11"
}
环境变量配置
开发环境,项目根目录创建.env.development文件
# 运行时不自动在浏览器中打开
BROWSER=none
# 修改端口
PORT=8009
生产环境,项目根目录创建.env.production文件
# 打包后子路径,/ 为默认根目录,如需修改为 /app/xxx,则 PUBLIC_URL=/app
PUBLIC_URL=/app
# 打包不生成sourcemap 
GENERATE_SOURCEMAP=false
常用依赖
axios 基于Promise的HTTP客户端,用于浏览器和node.js
qs 查询字符串解析和字符串化库
mobx 状态管理
mobx-react mobx在react使用支持
prop-types 检查 react props,TypeScript模版不需要
react-router-dom 路由,会自动添加react-router依赖
@types/react-router-dom 路由类型定义(TypeScript模版),会自动添加@types/react-router依赖
react-app-rewired
在不eject也不创建额外react-scripts的情况下修改create-react-app内置的webpack配置

(1)安装依赖
相关依赖

react-app-rewired 修改create-react-app内置的webpack配置
customize-cra 提供了一些实用程序,通过react-app-rewired来自定义配置create-react-app核心功能
eslint js校验
eslint-config-standard eslint的standard校验规则
eslint-plugin-import eslint插件
eslint-plugin-node eslint插件
eslint-plugin-promise eslint插件
eslint-plugin-standard eslint插件
node-sass scss支持,自带scss配置,默认支持scss module
react-hot-loader 热加载
@hot-loader/react-dom hot loader支持hooks,安装时需与react版本一致
# 安装依赖
yarn add react-app-rewired customize-cra -D
# eslint
yarn add eslint eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard -D
# scss
yarn add node-sass -D
# 热加载依赖
yarn add react-hot-loader @hot-loader/react-dom -D
/* 当前依赖版本 */
{
  "devDependencies": {
    "@hot-loader/react-dom": "^16.13.0",
    "customize-cra": "^0.9.1",
    "eslint": "^6.8.0",
    "eslint-config-standard": "^14.1.1",
    "eslint-plugin-import": "^2.20.2",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.1",
    "node-sass": "^4.13.1",
    "react-app-rewired": "^2.1.5",
    "react-hot-loader": "^4.12.20"
  }
}2)配置
项目根目录创建config-overrides.js文件,配置为以下
const path = require('path')
const {
  addBabelPlugin,
  addDecoratorsLegacy,
  addWebpackAlias,
  useEslintRc
} = require('customize-cra')

const resolve = dir => path.resolve(__dirname, 'src', dir)

// hot-loader配置
const rewireHotLoader = (config, env) => {
  if (env === 'production') {
    return config
  }
  // Find a rule which contains eslint-loader
  const condition = u => typeof u === 'object' && u.loader && u.loader.includes('eslint-loader')
  const rule = config.module.rules.find(rule => rule.use && rule.use.some(condition))
  if (rule) {
    const use = rule.use.find(condition)
    if (use) {
      // Inject the option for eslint-loader
      use.options.emitWarning = true
    }
  }
  // If in development, add 'react-hot-loader/babel' to babel plugins.
  return addBabelPlugin('react-hot-loader/babel')(config)
}

// 别名
const alias = env => Object.assign(env === 'production' ? {} : {
  'react-dom': '@hot-loader/react-dom'
}, {
  '@src': resolve(''),
  '@api': resolve('api'),
  '@store': resolve('store'),
  '@routes': resolve('routes'),
  '@pages': resolve('pages'),
  '@layouts': resolve('layouts'),
  '@components': resolve('components'),
  '@styles': resolve('assets/styles'),
  '@images': resolve('assets/images')
})

/**
 * 修改默认配置
 */
module.exports = function (config, env) {
  // 开发模式使用react-hot-loader
  rewireHotLoader(config, env)

  // 使用自定义.eslintrc
  useEslintRc('./.eslintrc')(config)

  // 装饰器,主要用于mobx
  addDecoratorsLegacy()(config)

  // 别名
  addWebpackAlias(alias(env))(config)

  // 返回config
  return config
}
修改package.json文件中scripts为以下
{
  "scripts": {
    "dev": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  }
}
ESLint配置
删除package.json文件中eslintConfig
根目录创建.eslintrc文件,配置eslint,当前使用standard校验规则
注意:需要与相关开发工具设置配合

{
  "extends": [
    "standard",
    "plugin:react/recommended"
  ],
  "env": {
    "browser": true,
    "commonjs": true,
    "node": true,
    "es6": true
  },
  "parser": "babel-eslint",
  "parserOptions": {
    "ecmaVersion": 7,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true,
      "legacyDecorators": true
    }
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "arrow-parens": [
      "error",
      "as-needed"
    ],
    "object-curly-spacing": [
      1,
      "always"
    ]
  }
}
部分组件使用
scss、scss module使用
创建style.scss文件,直接在需要的页面或者组件中引入即可

import './style.scss'
创建style.module.scss文件,直接在需要的组件中引入,然后className引用里面的样式即可

import styles from './style.module.scss'

<div className={styles.box}></div>
输出样式

.<filename>_<class name>__<hash code> {
}
react-hot-loader使用
相关配置参照上方的配置说明,配置主要针对开发模式
(1)react-hot-loader/babel
(2)webpack配置别名'react-dom': '@hot-loader/react-dom'支持hooks

import { hot } from 'react-hot-loader/root'

// 处理入口文件引入的 App 组件,开发模式需要使用 react-hot-loader 处理
const AppComponent = process.env.NODE_ENV === 'development' ? hot(App) : App

ReactDOM.render(
  <React.StrictMode>
    <AppComponent />
  </React.StrictMode>,
  document.getElementById('root')
)
TypeScript模版增加配置
eslint 此处eslint有版本要求
eslint-plugin-react eslint react组件
@typescript-eslint/parser typescript eslint解析器
@typescript-eslint/eslint-plugin typescript eslint插件
# 安装依赖
yarn add @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react -D
# 此处eslint版本要求^6.6.0,版本不符会提示安装eslint@^6.6.0,后续版本可根据相关提示安装对应版本的eslint
yarn add eslint@^6.6.0 -D
/* 当前依赖版本 */
{
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.31.0",
    "@typescript-eslint/parser": "^2.31.0",
    "eslint": "^6.6.0",
    "eslint-plugin-react": "^7.19.0"
  }
}
增加.eslintignore,添加以下内容

config-overrides.js
node_modules
.eslintrc修改为以下
@typescript-eslint/explicit-function-return-type:强制函数返回类型有声明,关闭
@typescript-eslint/no-non-null-assertion:非空断言,关闭

{
  "extends": [
    "standard",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "env": {
    "browser": true,
    "commonjs": true,
    "node": true,
    "es6": true
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 7,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true,
      "legacyDecorators": true
    }
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  },
  "plugins": [
    "@typescript-eslint",
    "react"
  ],
  "rules": {
    "arrow-parens": [
      "error",
      "as-needed"
    ],
    "object-curly-spacing": [
      1,
      "always"
    ],
    "@typescript-eslint/explicit-function-return-type": [
      "off"
    ],
    "@typescript-eslint/no-non-null-assertion": [
      "off"
    ]
  }
}
根目录创建paths.json增加别名(paths)

{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@/*": [
        "src/*"
      ]
    }
  }
}
继承paths.json,识别定义别名
paths直接写在tsconfig.json,项目启动会被重置
装饰器(experimentalDecorators)支持
tsconfig.json添加以下属性

{
  "extends": "./paths.json",
  "compilerOptions": {
    ···
    "experimentalDecorators": true,
    ···
  }
  ···
}
部分代码示例
// test.tsx,test组件

import React, { Component } from 'react'
import { inject, observer } from 'mobx-react'

interface Props {
  // mobx给count赋值,引用组件不用给count传值
  count?: {
    num: number;
    add: Function;
  };
}

@inject('count')
@observer
// 如果包含state,则需定义interface State,Component<Props, State,Component>
export default class Test extends Component<Props> {
  render () {
    // 使用非空断言(mobx一定会给count赋值)
    const { num, add } = this.props.count!
    return (
      <div>
        <p>num -- {num}</p>
        <button onClick={() => add()}>add</button>
      </div>
    )
  }
}

// ----------------------------------------------------------

// App.tsx,App页面,使用test组件

import React, { Component } from 'react'
import Test from '@/test'

interface StateType {
  name: string;
}

export default class App extends Component<{}, StateType> {
  // 如果Props为{},可不定义interface,直接Component<{}, State>,此时constructor (props: {}) {}
  constructor (props: {}) {
    super(props)
    // 定义state
    this.state = {
      name: 'name'
    }
  }

  render () {
    return (
      <div>
        {/* test组件可不传值 */}
        <Test />
      </div>
    )
  }
}
相关问题
// eslint warning
// Warning: React version not specified in eslint-plugin-react settings. 

// 在.eslintrc中添加以下内容,指定react版本即可
"settings": {
  "react": {
    "version": "detect"
  }
}
# 控制台警告
React-Hot-Loader: react-🔥-dom patch is not detected. React 16.6+ features may not work.

# 同时配置了 react-hot-loader、@hot-loader/react-dom 不会出现该警告
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值