从零搭建React前端项目

记录一下学习 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",
  },