[create-react-app] 使用教程

405 阅读5分钟

前言

跟着官网学习总结的,操作每一步都自己试过,官网教程有部分文章过旧了,我做了修正。如果你是刚学react,需要了解cra框架,学习怎么使用它,文章一定对你有帮助。

框架主要特点

开发不需要手动配置 webpack 、 babel 等构建工具,由框架来管理构建工具的配置,开发只需要专注于代码。以后升级也只用执行一条命令就能更新构建工具。

命令和使用说明

创建项目:npx create-react-app [项目名称] --template typescript

升级(更新构建工具):npm i react-scripts@latest

预览构建产物:

  1. npm i -g serve
  2. npm run build
  3. serve -s build [-l 端口]

弹出配置文件,此后需要手动维护配置(不建议,框架最大优势就没了):npm run eject

eject的替代方案:CRACO

补充说明:由于cra框架年久失修,已经谈不上一键更新了,项目基本都直接eject。


修改package.json后不会立即生效。这是由于babel-loader未检测到package.json,快速解决方案是删除 node_modules/.cache 文件夹并重试。

兼容旧版浏览器:react-app-polyfill、使用autoprefixer自动添加样式前缀(自带)

在生产构建时,src内的脚本和样式文件都会被压缩合并到一起,生成的文件名包含内容哈希,浏览器不会缓存旧版。而public内的资源webpack仅做复制不会处理,每次变更需要刷新缓存。

一般都是将资源放入src然后import导入,除非是以下情况才会放入public:

  1. 需要文件名保持不变

  2. 大量图片需要动态引用

  3. 小脚本

  4. 不兼容webpack的库

public内的资源引用:process.env.PUBLIC_URL + 相对public的路径

扩展ESLint配置

"eslintConfig": {
    "extends": [ // 基本配置(最好保持不变)
        "react-app",
        "react-app/jest"
    ],
    "rules": { // 适用于所有 js 和 ts 文件的新规则
        "no-alert": "error"
    },
    "overrides": [
        {
            "files": [
                "**/*.ts?(x)"
            ],
            "rules": {}  // 仅针对 ts文件的新规则
        }
    ]
},

vscode内断点调试

{
    "version": "0.2.0",
    "configurations": [
      {
        "name": "Chrome",
        "type": "chrome",
        "request": "launch",
        "url": "http://localhost:3000",
        "webRoot": "${workspaceFolder}/src",
        "sourceMapPathOverrides": {
          "webpack:///src/*": "${webRoot}/*"
        }
      }
    ]
}

在 git 提交时自动格式化代码

  1. npm i -D husky lint-staged prettier

  2. npx husky init

  3. pre-commit写入:npx lint-staged

  4. .prettierrc写入:适合团队的格式化配置

  5. 首次格式化整个项目:./node_modules/.bin/prettier --write "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"

"husky": {
    "hooks": {
        "pre-commit": "lint-staged"
    }
},
"lint-staged": {
    "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
        "prettier --write"
    ]
}

分析生产构建的包大小

  1. npm i -D source-map-explorer

  2. scripts添加命令:"analyze": "source-map-explorer 'build/static/js/*.js'"

  3. npm run build

  4. npm run analyze

在开发中使用HTTPS

scripts添加命令:"start:https": "HTTPS=true npm start"

PS:可以设置自定义证书。

css-modules

[name].module.[css|scss] => [filename]_[classname]__[hash]

原理:通过生成唯一的类名,来解决css全局作用域的问题

好处:防止样式污染、方便命名

使用:

import styles from './xxx.module.css';
className={styles.error}

其他特征:

@value 变量名: 变量值;

@value 变量名 from 'other module';

composes: 类名;

composes: 类名 from 'other module';

:global(选择器)

变量用来复用值,composes用来复用样式,:global能把选择器的作用域提升到全局。

:global中可以使用变量,但不能使用composes。

添加saas预处理器

npm i -D sass

saas可以和css modules一起使用,带来嵌套、mixin的增强。

添加css样式重置

样式入口添加:@import-normalize;

.vscode/settings.json添加:"[css|scss].lint.unknownAtRules": "ignore"

引入图片或svg

import logo from './logo.png';
<img src={logo} alt="Logo" />

import { ReactComponent as Logo } from './logo.svg';
<Logo title="logo" width="1em" fill="#f00" />

svg文件可以直接作为react组件引入,方便挂载属性到svg标签上(除了title)。

使用绝对路径导入模块

// tsconfig.json

compilerOptions.baseUrl: "src"

// 使用

import Button from 'components/Button';

使用全局变量

方法一:const $ = (window as any).$;

方法二(推荐,扩展Window类型):

declare global {
    interface Window {
        $: any; // jQuery
    }
}

export {};

(坑:名称不能是index.d.ts,因为会和index.tsx冲突导致无法加载)

添加自定义的环境变量

环境变量就是特殊的占位符,在构建时会用值对占位符进行字符串替换。

通过process.env访问环境变量(index.html中通过 %变量名% 访问),其中内置变量NODE_ENV表示当前环境,可以用于在不同环境执行不同代码。

自定义的环境变量在env文件中声明,必须以 REACT_APP_ 开头,建议全大写,单词间以 _ 连接。

# 通用环境变量

# 网站标题
REACT_APP_WEBSITE_NAME="React 开发模板"

# 网站描述
REACT_APP_WEBSITE_DESCRIPTION="一个基于 Create-React-App 的 React 开发模板,用于项目初始化"

# 版本号(读取 package.json 的 version 字段值)
REACT_APP_VERSION=$npm_package_version

注意:修改env文件后需要重启开发服务器。

对生产构建使用缓存控制

安全有效的起点:(后面可以根据自己项目做针对控制)

build/static:Cache-Control: max-age=31536000

其他所有资源:Cache-Control: no-cache

这样浏览器会始终检查index.html,并把build/static的资源都缓存一年。

注意:如果build/static的资源更新了也会获取最新版本,因为文件名带有文件内容哈希,内容变了,URL也变了。

开发代理

方式一:在package.json中添加proxy选项,支持HTTP、HTTPS 和 WebSocket 连接。

// package.json
"proxy": "后端服务地址",

// .env.development
# 服务器主机。如果代理出现 Invalid Host header,则必须明确指定 HOST

# HOST=mypublicdevhost.com

# 如果指定 HOST 无效,只有打开下面设置(注意:这很危险,因为计算机可能会遭受恶意网站的远程代码执行)

# DANGEROUSLY_DISABLE_HOST_CHECK=true

方式二:自定义代理配置(不要和proxy选项混用)

  1. npm i http-proxy-middleware

  2. 创建src/setupProxy.js

// 这个文件仅支持 Node 的 JavaScript 语法,不支持 ES 模块
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function (app) {
    app.use(
        '/api/*',
        createProxyMiddleware({
            target: 'https://jsonplaceholder.typicode.com',
            ws: false,
            changeOrigin: true,
            pathRewrite: (path) => path.replace(/^\/api/, ''),
            // logLevel: 'debug',
        }),
    );
};

项目部署

package.json添加homepage字段,确定生成的HTML文件中使用的根路径。

没有homepage ==> /static/xxx
"homepage": "." ==> ./static/xxx
"homepage": "http://mywebsite.com/relativepath" ==> /relativepath/static/xxx

一般情况设置为“.”即可,相对路径,方便部署到不同位置。

或者设置PUBLIC_URL环境变量,强制将资源引用到指定路径(包括主机名),优先级大于homepage

PUBLIC_URL=http://mywebsite.com/relativepath
=> http://mywebsite.com/relativepath/static/xxx

另外,如果build时报错找不到XXX,很可能是文件名大小写不对导致。

最后

如果文章有哪里写的不对,理解的不对,可以提出我会修改,帮到你了可以点个赞。

2024-07-04 补充eject说明
2024-07-03 发布