一、关于React
英文官网:reactjs.org/ ===》 react.dev/
中文官网:zh-hans.reactjs.org/ ===》zh-hans.react.dev/
React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。
react在发展过程中,一直跟随原生js的脚步,特别是从v16.0版本开始(用到了class来创建组件)
2015年推出了使用react来编写移动端的app ---- react-native www.react-native.cn/ v0.73
重要版本发版时间
| 序号 | 版本号 | 发版时间 | 重要更新 |
|---|---|---|---|
| 1 | 16 | 2017年9月26 | 引入es6的类组件 |
| 2 | 16.3 | 2018年4月3日 | 生命周期更新 |
| 3 | 16.4 | 2018年5月23日 | 生命周期更新 |
| 4 | 16.8 | 2019年2月6日 | 引入 react hooks |
| 5 | 17.0 | 2020年10月20日 | 过渡版本 |
| 6 | 18.0 | 2022年3月29日 | 写法改变,严格模式发生改变 |
React目前版本是 18.2.0,是2022年6月14日
二、脚手架
中文官网:create-react-app.bootcss.com/
yarn npm cnpm pnpm
配置cnpm
npm install -g cnpm --registry=https://registry.npmmirror.com以后就可以使用 cnpm 代替 npm
补充:react的脚手架并不是只有
create-react-app,还有dva-cli,umi等vite
$ npm init vite@latest
# 或者
$ yarn create vite
# 或者
$ pnpm create vite
vue-cli以及create-react-app底层都是基于nodejs的webpack
2.1 create-react-app脚手架的使用
npm install --global smart-npm --registry=https://registry.npm.taobao.org/第一次通过create-react-app 或者 通过webstorm等编译器创建react项目时,因为要安装很多相关的包,而这些包的安装基本都是在内部通过npm进行安装。 由于npm在访问有些国外的资源会非常卡,有的时候即使开了VPN也一样很卡,因此这个时候创建过程可能会异常缓慢,这里其实我们可以使用国内的数据源。 如果 window 用户安装最新版本不成功的话,可以试试安装 smart-npm@1
npm install --global smart-npm@1 --registry=https://registry.npm.taobao.org/上面命令并不是必须得执行
Create React App 让你仅通过一行命令,即可构建现代化的 Web 应用。
本文档之后称之为cra
创建项目的方式:
需要保证电脑安装node版本在14以上,系统在win7以上
npx: npm可以看成第三方的资源包,npx可以看成各种基于node的脚手架的工具
# 方式1:使用npx
$ npx create-react-app react-basic
# 等价于
$ npm i create-react-app -g # npm 使用cnpm 代替 cnpm i create-react-app -g
$ create-react-app react-basic
如果需要使用ts开发项目,创建项目时可以通过--template typescript指定模版
$ npx create-react-app myapp --template typescript
如果出现如下内容,即代表项目创建成功
Success! Created react-model-app at E:\workspace\bj2304\code\react-course\react-model-app
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!
We suggest that you begin by typing:
cd react-model-app
npm start
2.2 项目目录解析
项目创建完毕生成目录结构如下:
react-basic
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── reportWebVitals.js // 做性能测试
└── setupTests.js // 测试
src/reportWebVitals.js
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry); // 衡量视觉稳定性。为了提供一个好的用户体验,CLS应该小于0.1
getFID(onPerfEntry); // 衡量可交互性。为了提供一个好的用户体验,FID应该在100毫秒内。
getFCP(onPerfEntry); // 首次内容绘制
getLCP(onPerfEntry); // 衡量加载性能。为了提供一个好的用户体验,LCP应该在2.5秒内
getTTFB(onPerfEntry); // 到第一个字节的时间
});
}
};
export default reportWebVitals;
react官方文档已经给了我们性能提升的方案:zh-hans.legacy.reactjs.org/docs/optimi…
打开package.json,发现可运行命令如下:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
start指令用于启动开发者服务器
build指令用于打包项目
test指令用于测试
eject指令用于抽离配置文件
cra脚手架基于webpack,默认webpack的配置在node_modules下的react-scripts内部,但是一般情况下,传输代码时,不会上传node_modules,那么在必要情况下就必须得抽离配置文件。
如果项目创建不成功,复制别人的项目(不复制node_modules)
2.3 抽离配置文件
通过npm run eject或者cnpm run eject 或者yarn eject指令抽离配置文件
抽离配置文件过程中注意事项
- 1.确保项目的git仓库是最新的
- 2.如果不需要对于webpack进行配置,那么不需要抽离配置文件
- create-react-app v2 默认支持 ts 以及sass 以及css的模块化,如果使用 sass作为css预处理器,那么不需要抽离配置文件
Copying files into E:\workspace\bj2304\code\react-course\react-basic
Adding \config\env.js to the project
Adding \config\getHttpsConfig.js to the project
Adding \config\modules.js to the project
Adding \config\paths.js to the project
Adding \config\webpack.config.js to the project
Adding \config\webpackDevServer.config.js to the project
Adding \config\jest\babelTransform.js to the project
Adding \config\jest\cssTransform.js to the project
Adding \config\jest\fileTransform.js to the project
Adding \scripts\build.js to the project
Adding \scripts\start.js to the project
Adding \scripts\test.js to the project
Adding \config\webpack\persistentCache\createEnvironmentHash.js to the project
Updating the dependencies
Removing react-scripts from dependencies
Adding @babel/core to dependencies
Adding @pmmmwh/react-refresh-webpack-plugin to dependencies
Adding @svgr/webpack to dependencies
Adding babel-jest to dependencies
Adding babel-loader to dependencies
Adding babel-plugin-named-asset-import to dependencies
Adding babel-preset-react-app to dependencies
Adding bfj to dependencies
Adding browserslist to dependencies
Adding camelcase to dependencies
Adding case-sensitive-paths-webpack-plugin to dependencies
Adding css-loader to dependencies
Adding css-minimizer-webpack-plugin to dependencies
Adding dotenv to dependencies
Adding dotenv-expand to dependencies
Adding eslint to dependencies
Adding eslint-config-react-app to dependencies
Adding eslint-webpack-plugin to dependencies
Adding file-loader to dependencies
Adding fs-extra to dependencies
Adding html-webpack-plugin to dependencies
Adding identity-obj-proxy to dependencies
Adding jest to dependencies
Adding jest-resolve to dependencies
Adding jest-watch-typeahead to dependencies
Adding mini-css-extract-plugin to dependencies
Adding postcss to dependencies
Adding postcss-flexbugs-fixes to dependencies
Adding postcss-loader to dependencies
Adding postcss-normalize to dependencies
Adding postcss-preset-env to dependencies
Adding prompts to dependencies
Adding react-app-polyfill to dependencies
Adding react-dev-utils to dependencies
Adding react-refresh to dependencies
Adding resolve to dependencies
Adding resolve-url-loader to dependencies
Adding sass-loader to dependencies
Adding semver to dependencies
Adding source-map-loader to dependencies
Adding style-loader to dependencies
Adding tailwindcss to dependencies
Adding terser-webpack-plugin to dependencies
Adding webpack to dependencies
Adding webpack-dev-server to dependencies
Adding webpack-manifest-plugin to dependencies
Adding workbox-webpack-plugin to dependencies
Updating the scripts
Replacing "react-scripts start" with "node scripts/start.js"
Replacing "react-scripts build" with "node scripts/build.js"
Replacing "react-scripts test" with "node scripts/test.js"
Configuring package.json
Adding Jest configuration
Adding Babel preset
Running npm install...
up to date in 13s
Ejected successfully!
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/env.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/getHttpsConfig.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/jest/babelTransform.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/jest/cssTransform.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/jest/fileTransform.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/modules.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/paths.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/webpack.config.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/webpack/persistentCache/createEnvironmentHash.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/config/webpackDevServer.config.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/scripts/build.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/scripts/start.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in code/react-course/react-basic/scripts/test.js.
The file will have its original line endings in your working directory
Staged ejected files for commit.
Please consider sharing why you ejected in this survey:
http://goo.gl/forms/Bi6CZjk1EqsdelXk1
$ npm start
$ npm build
2.4 webpack二次封装
2.4.1 集成css预处理器
- 集成less预处理器
$ npm i less less-loader -D
-
集成sass预处理器
虽然已经默认支持了sass,但是得需要安装以下模块
$ npm i node-sass -D # cnpm i node-sass -D
- 集成stylus预处理器
$ cnpm i stylus stylus-loader -D
具体配置如下:
React-basic/config/webpack.config.js
// style files regexes 可以搜索此关键字快速定位
const cssRegex = /.css$/;
const cssModuleRegex = /.module.css$/;
const sassRegex = /.(scss|sass)$/;
const sassModuleRegex = /.module.(scss|sass)$/;
const lessRegex = /.less$/; // +++++++
const lessModuleRegex = /.module.less$/;// +++++++
const stylusRegex = /.(styl|stylus)$/;// +++++++
const stylusModuleRegex = /.module.(styl|stylus)$/;// +++++++
// "postcss" loader applies autoprefixer to our CSS.可以搜索此关键字快速定位
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'icss',
},
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'icss',
},
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
},
'sass-loader'
),
},
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'icss',
},
},
'less-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
},
'less-loader'
),
},
{
test: stylusRegex,
exclude: stylusModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'icss',
},
},
'stylus-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: stylusModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
},
'stylus-loader'
),
},
2.4.2 配置@解析别名
vue项目中可以使用@代替src目录,那么react中抽离配置文件之后也可以实现此功能
react-basic/config/webpack.config.js
alias: {
'@': path.resolve('src'), // +++++++++++++
// Support React Native Web 搜索此关键词快速定位
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
// Allows for better profiling with ReactDevTools
...(isEnvProductionProfile && {
'react-dom$': 'react-dom/profiling',
'scheduler/tracing': 'scheduler/tracing-profiling',
}),
...(modules.webpackAliases || {}),
},
src/index.js 测试
import React from 'react';
import ReactDOM from 'react-dom/client';
import '@/index.css'; // ++++++
import App from '@/App';// ++++++
import reportWebVitals from '@/reportWebVitals';// ++++++
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// 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();
如果控制台报错如下,说明@别名没有配置成功
Failed to compile.
Module not found: Error: Can't resolve '@/index.css' in '/Users/wudaxun/Desktop/workspace/code/bk2207A/code/react-course/react-basic/src'
ERROR in ./src/index.js 6:0-21
Module not found: Error: Can't resolve '@/index.css' in '/Users/wudaxun/Desktop/workspace/code/bk2207A/code/react-course/react-basic/src'
ERROR in ./src/index.js 7:0-24
Module not found: Error: Can't resolve '@/App' in '/Users/wudaxun/Desktop/workspace/code/bk2207A/code/react-course/react-basic/src'
ERROR in ./src/index.js 8:0-48
Module not found: Error: Can't resolve '@/reportWebVitals' in '/Users/wudaxun/Desktop/workspace/code/bk2207A/code/react-course/react-basic/src'
webpack compiled with 3 errors
如果没有错误说明配置是成功的。
如果不抽离配置文件,但是也需要配置别名@
$ cnpm i @craco/craco -D项目根目录中创建 craco 的配置文件:
craco.config.jsconst path = require('path') module.exports = { webpack: { alias: { '@': path.resolve(__dirname, 'src') } } }修改
package.json中运行命令"scripts": { "start": "craco start", "build": "craco build" "test": "craco test" }重启服务器即可生效
2.5 setupProxy代理
即使不抽离配置文件,也是在此处配置代理
如果整个项目只有一个服务器且有跨域问题,可以直接在package.json中做如下配置:
"proxy": "http://121.89.205.189:3000/api",
然后在项目中可以如下访问:
// cnpm i axios -S
// src/index.js
fetch('/pro/list').then(res => res.json()).then(res => {
console.log(res.data)
})
了解:那么如果有多个服务器 并且也需要解决跨域问题 - 本项目不做配置
首先,http-proxy-middleware使用 npm 或 Yarn 安装:
$ cnpm install http-proxy-middleware -S
$ # or
$ yarn add http-proxy-middleware -S
接下来,创建src/setupProxy.js并在其中放置以下内容:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
// ...
};
您现在可以根据需要注册代理了!这是使用上述内容的示例http-proxy-middleware:
const { createProxyMiddleware } = require('http-proxy-middleware'); // 此处不使用import语法
module.exports = function (app) {
// http://121.89.205.189:3001/api/pro/list ==> /myapi/pro/list
app.use('/myapi', createProxyMiddleware({
target: 'http://121.89.205.189:3001/api',
changeOrigin: true,
pathRewrite: {
'^/myapi': ''
}
})
);
}
注意: 您不需要在任何地方导入此文件。当您启动开发服务器时,它会自动注册。
注意: 此文件仅支持 Node 的 JavaScript 语法。确保只使用受支持的语言功能(即不支持 Flow、ES 模块等)。
注意: 将路径传递给代理函数允许您在路径上使用通配符和/或模式匹配,这比快速路由匹配更灵活。