记录一下学习 React + Vite + TypeScript 搭建项目的过程
一、初始化项目
1.创建项目
npm create vite
输入my-react-app,选择react、typescript

cd my-react-app
npm install
2.目录结构
没有的文件夹需要自己创建一下:
src/
├── assets/ # 静态资源
├── components/ # 公共组件
├── hooks/ # 自定义Hooks
├── layouts/ # 全局布局
├── pages/ # 页面组件
├── router/ # 路由配置
├── store/ # 状态管理
├── styles/ # 全局样式
├── utils/ # 工具函数
└── main.tsx # 入口文件
二、功能模块配置
1. 路由管理(React Router)
安装:
npm install react-redux react-router-dom
新建页面文件 src/pages/index.tsx :
function index() {
return ('hello world')
}
export default index
配置路由文件 src/router/index.tsx :
import React, { lazy } from "react";
import { RouteObject } from 'react-router-dom'
const Index = lazy(() => import('../pages/index'))
const Router: RouteObject[] = [
{
path: '/',
element: <Index />
}
]
export default Router;
引入 main.tsx :
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from "./App";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<BrowserRouter>
<App></App>
</BrowserRouter>
);
使用 app.tsx:
import React, { Suspense } from "react";
import { useRoutes, Link } from 'react-router-dom';
import routes from '../src/router';
function App() {
return <div className="App">
<Suspense fallback="Loading...">
<div className="main">
{useRoutes(routes)}
</div>
</Suspense>
</div>;
};
export default App;
启动项目,可以看到页面上展示hello world了
2. 状态管理(Redux)
安装:
npm install @reduxjs/toolkit
创建Store示例 src/store/features/user.ts :
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import type { RootState } from "../index";
interface CounterState {
// 定义初始化状态的类型
value: number;
}
const initialState: CounterState = {
// 初始化状态
value: 1,
};
export const counterSlice = createSlice({
name: "user",
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export const selectCount = (state: RootState) => state;
export default counterSlice.reducer;
src/store/index.tsx :
import { configureStore } from "@reduxjs/toolkit";
import counterSlice from "./features/user";
const store = configureStore({
reducer: {
user: counterSlice,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export default store;
修改 main.tsx :
import ReactDOM from "react-dom/client";
import store from "./store/index";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import App from "@/App";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<Provider store={store}>
<BrowserRouter>
<App></App>
</BrowserRouter>
</Provider>
);
组件中使用:
…
3. CSS方案(Tailwind CSS)
安装并生成配置文件:
npm install tailwindcss @tailwindcss/postcss postcss
npx tailwindcss init -p
配置 tailwind.config.js :
module.exports = {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: { extend: {} },
plugins: []
};
配置 postcss.config.mjs :
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
在 src/assets/globals.css 中引入:
@import "tailwindcss";
在main.tsx中引入全局样式文件:
import "@/assets/globals.css";
测试 tailwind css 是否生效,新建组件 src/components/RedButton.tsx :
function RedButton() {
return (
<div className="flex justify-center items-center h-screen">
<button className="bg-red-500 text-white font-bold py-2 px-4 rounded hover:bg-red-700">
I'm a button!
</button>
</div>
);
}
export default RedButton;
在 page/index.tsx 中引入使用:
import RedButton from "@/components/RedButton";
function index() {
return (
<div>
<RedButton />
</div>
);
}
export default index;
可以看到页面显示红色按钮说明样式已生效
三、配置环境变量
定义变量:
.env.development :
# 开发环境
VITE_BASE_URL = http://localhost:3000
.env.production :
# 生产环境
VITE_BASE_URL = http://www.xxxxx.com
使用变量:
const baseUrl = import.meta.env.VITE_BASE_URL;
修改 package.json 启动命令:
"scripts": {
"dev": "vite --mode development",
"build": "tsc -b && vite build --mode production",
},