自22年离开老东家,就没有试用过react了,目前也不知道react的最新版本更新到哪一个版本了,有那些新特性了。刚好最近被裁员,也有空看看react相关技术栈了,就浅浅的动手搭一下react的项目模板试试,了解一下react的新版和新特性。
1、准备工作
- 电脑上有JavaScript运行环境,如node,react 19 建议使用node 20 以上版本。
- 对应包管理器,如npm。
2、安装必要的包
基础包
javascript
react
react-dom
react-router-dom // web项目使用该路由包
vite // 编译器
babel-plugin-react-compiler // 编译器
rollup-plugin-terser // 代码压缩工具
sass // 编译scss|sass
typeScript支持包
javascript
@types/react // reat typeScript 类型支持
@types/react-dom // reactDom typeScript 类型支持
eslint支持包
javascript
eslint
eslint-plugin-import // import 语法支持
eslint-plugin-react // react 语法插件
eslint-plugin-react-hooks // react hooks 语法校验支持
eslint-plugin-react-compiler // eslint 编译器支持
typescript-eslint // eslint typescript 语法支持
@eslint/js // js语法支持包
globals // node 全局变量包
格式化工具
javascript
prettier
eslint-plugin-prettier // eslint-prettier 支持包
eslint-config-prettier // eslint 与 prettier 规则冲突解决包
3、相关配置
vite 配置
typescrit
import react from "@vitejs/plugin-react";
import { terser } from "rollup-plugin-terser";
import { defineConfig } from "vite";
const isProd = process.env.NODE_ENV === "production";
export default defineConfig({
plugins: [
react(),
// @ts-ignore
isProd && terser(), // 仅在生产环境使用压缩
],
build: {
outDir: "./dist",
minify: isProd, // 生产环境使用压缩
sourcemap: !isProd,
rollupOptions: {
output: {
manualChunks: {
// 第三方依赖库打包到一个文件
react: ["react-dom", "react"],
},
},
},
},
optimizeDeps: {
include: ["react", "react-dom"],
},
server: { port: 3000, open: true },
});
eslint 配置
eslint 8 版本配置,为以下格式,支持配置文件格式参考文档
typescript
export default {
root: true,
extends: ["eslint:recommended", "plugin:react/recommended"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
sourceType: "module",
ecmaVersion: 2020,
ecmaFeatures: {
jsx: true,
},
},
plugins: ["@typescript-eslint", "prettier"],
env: {
browser: true,
node: true,
},
rules: {
"prettier/prettier": "error",
},
};
eslint 9 以后,不在支持.eslintrc,json,yaml,yml格式的配置文件了,后续使用的文件名为 eslint.config.js|mjs|cjs|ts|mts|cts 文件。参考文档
typescript
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReact from "eslint-plugin-react";
/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
{ settings: { react: { version: "detect" } } },
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReact.configs.flat.recommended,
{
rules: {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off",
/**
* 不检查以下划线开头的 未使用的变量
* 包含了参数变量,解构变量,catch中的参数变量
*/
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
destructuredArrayIgnorePattern: "^_",
},
],
},
ignores: [],
},
];
prettier 配置
typescript
printWidth: 100, // 每行代码长度(默认80)
tabWidth: 2, // 每个tab相当于多少个空格(默认2)ab进行缩进(默认false)
useTabs: false, // 是否使用tab
semi: false, // 声明结尾使用分号(默认true)
vueIndentScriptAndStyle: false,
singleQuote: true, // 使用单引号(默认false)
quoteProps: "as-needed",
bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true)
trailingComma: "none", // 多行使用拖尾逗号(默认none)
jsxSingleQuote: false,
// 箭头函数参数括号 默认avoid 可选 avoid| always
// avoid 能省略括号的时候就省略 例如x => x
// always 总是有括号
arrowParens: "always",
insertPragma: false,
requirePragma: false,
proseWrap: "never",
htmlWhitespaceSensitivity: "strict",
endOfLine: "auto",
rangeStart: 0
入口文件
入口文件,是配置在package.json里的main字段,即:打包入口文件。
tsx
// 导入必要对象
import React from "react"
import ReactDOM from "react-dom/client" // DOM处理客户端渲染包
import App from "@/App"
import { BrowserRouter } from "react-router-dom" // 路由
ReactDOM.createRoot(document.getRElementById('app') as HTMLElement).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
)
路由配置
路由配置文件。
tsx
import Home from '@/pages/home/index'
import type { RouteObject } from 'react-router-dom'
import { Navigate } from 'react-router-dom'
// const Entry = lazy(() => import('@/pages/entry')) // 路由懒加载使用lazy
const routes: RouteObject[] = [
{ path: '/', element: <Navigate to={'/index'} /> },
{
path: '/index',
element: <Home />
}
]
export default routes
App.tsx 文件
在app.tsx文件里引入头尾部以及公共样式,路由渲染相关内容。
javascript
import AppHeader from '@/components/header'
import AppFooter from '@/components/footer'
import routes from '@/router'
import { useRoutes } from 'react-router-dom'
import '@/style/common.scss'
const App = () => {
console.log('App is running!')
const RoutePage = useRoutes(routes)
return (
<div className={'app'}>
<AppHeader />
<div className="main-container">{RoutePage}</div>
<AppFooter />
</div>
)
}
export default App