# CRA
官方简介:
Create React App (opens new window) (简称 CRA)让你仅通过一行命令,即可构建现代化的 Web 应用
# 一、脚手架使用
简单描述:
CRA 同样是基于 webpack 的,同时还要借助 babel 进行 jsx 解析
# 1、创建项目
- 全局方式
npm install create-react-app -g
create-react-app my-app
cd my-app
npm start
- 本地方式
npx create-react-app my-app
cd my-app
npm start
# 2、项目结构
什么是 PWA
首先,PWA 是一个网页,可以通过 web 技术编写一个网页应用。
通过在网页应用中添加上 App Manifest 和 Service Worker 可以实现 PWA 的安装和离线等功能。
web 应用的这种存在形式,我们也称之为 Web App。我的当前网站就支持 PWA
cra_project
├─ public
│  ├─ index.html(页面模板)
│  ├─ manifest.json(PWA相关)
│  └─ robots.txt(爬虫相关)
├─ src
│  ├─ index.js(程序入口)
│  └─ reportWebVitals(PWA相关)
├─ package.json
└─ README.md
# 二、React 项目分析
# 1、index.js
import ReactDOM from 'react-dom/client'
import App from './App'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<App />)
# 2、App.jsx
我们可以把 App 当成一个根组件,然后就可以像 vue-cli 中组件化开发一样,进行项目开发了。
import React from 'react'
class App extends React.Component {
  //
  render() {
    return <h1>Hello, world!</h1>
  }
}
export default App
# 3、webpack 配置
# 三、React 项目配置
# 1、jsconfig.json
这个文件在 vue 项目中是会自动生成的,但在 CRA 创建将的项目中并没有。
jsonfig.json 是给编辑器 vscode 等识别的(方便配置别名后 vscode 能够有路径提示)
{
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "baseUrl": "./",
    "moduleResolution": "node",
    "paths": {
      "@/*": ["src/*"]
    },
    "jsx": "preserve",
    "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
  }
}
# 2、craco.config.js
CRA 创建的 react 项目默认是隐藏了 webpack 配置的。我们可以通过其提供的 npm 方式进行配置(不方便):
npm run eject
为了方便,我们可以使用 craco (opens new window) 库。
步骤 1:
// package.json
"scripts": {
  "start": "craco start"
  "build": "craco build"
  "test": "craco test"
}
步骤 2:
// craco.config.js
const path = require('path')
const resolve = (pathname) => {
  return path.resolve(__dirname, pathname)
}
module.exports = {
  webpack: {
    alias: {
      '@': resolve('src'),
      components: resolve('src/components'),
      utils: resolve('src/utils')
    }
  }
}
# 四、配套库引入
# 1、react 路由
安装:
npm install react-router-dom
配置:
// index.js
import { BrowserRouter, HashRouter } from 'react-router-dom'
// ……
root.render(
  // 懒加载
  <Suspense fallback={<div>Loading</div>}>
    <HashRouter>
      <App />
    </HashRouter>
  </Suspense>
)
路由:
// App.jsx
import { useRoutes } from 'react-router-dom'
import routes from '@/router/index.js'
// 根据项目在指定的位置放置
;<div>{useRoutes(routes)}</div>
// @/router/index.js
const routes = [
  //
]
export default routes
# 2、React-Redux 引入
安装:
npm install redux react-redux
配置:
// index.js
import { Provider } from 'react-redux'
import store from './store'
// ……
root.render(
  // 解决:重复 1
  <Provider store={store}>
    <App />
  </Provider>
)
store:
store 的目录结构
├── store
    ├── index.js
    ├── cart
    │   ├── index.js
    │   ├── constants.js
    │   ├── reducer.js
    │   └── actionCreators.js
    └── products
        ├── index.js
        ├── constants.js
        ├── reducer.js
        └── actionCreators.js
import { createStore, applyMiddleware, combineReducers } from 'redux'
import thunk from 'react-thunk'
import cartReducer from './cart.js'
import productsReducer from './products.js'
const reducer = combineReducers({
  cart: cartReducer,
  products: productsReducer
})
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
export default createStore(reducer, composeEnhancers(applyMiddleware(thunk)))
# 3、Redux Toolkit 引入
安装:
npm install @reduxjs/toolkit react-redux
配置:
// index.js
import { Provider } from 'react-redux'
import store from './store'
// ……
root.render(
  // 解决:重复 1
  <Provider store={store}>
    <App />
  </Provider>
)
store:
store 的目录结构
├── store
    ├── index.js
    └── featres
        ├── cart.js
        └── products.js
// @/store/index.js
import { configureStore } from '@reduxjs/toolkit'
import cartReducer from './features/cart.js'
import productsReducer from './products.js'
export default configureStore({
  reducer: {
    cart: cartReducer,
    products: productsReducer
  }
})
