Vite创建一个 React + TS 的项目

一、创建基础项目

1、创建一个基础项目

lua 复制代码
yarn create vite 项目名

ps:输入命令后会依次选择 框架,ts/js 即可(命令没有输入项目名,则输入命令后第一个选项是名称输入)

Project目录主要结构如下

file 复制代码
|- public              // 这个文件夹内放的东西不会被构建工具打包,一般用来放网站的图标或者全局配置文件。
|- src
    |- App.tsx         // 自定义的第一个组件
    |- main.tsx        // 项目主入口
    |- vite-env.d.ts   // ts声明文件
    |- assets          // 静态资源文件夹
|- index.html          // 打包后,项目的主入口文件,也是react根节点挂在的文件
|- package.json        // 项目的依赖配置文件,所有安装在依赖以及仓库配置
|- package-lock.json   // 项目依赖锁定文件。防止依赖自动升级,导致项目无法启动
|- tsconfig.json       // 项目的ts配置文件,针对src下面的所有ts文件生效。
|- tsconfig.node.json  // 项目的ts配置文件,针对vite.config.ts文件。
|- vite.config.ts      //  vite构建工具的配置项,在这里可以使用一些第三方插件,做一些项目的配置。
|- .eslintrc.cjs       // 代码格式化校验的配置项,使代码编写更加规范
|- gitignore           // git提交时,忽略文件配置项

二、配置vite.config.ts

官方文档 : Vite官方中文文档

以及vite.config.js的配置项文档: Vite配置项

ts 复制代码
// vite.config.ts
import { defineConfig, loadEnv } from 'vite';
import * as path from 'path';
import react from '@vitejs/plugin-react';

export default defineConfig(({ mode }) => {
  // loadEnv中三个参数 (mode,dir,base) -> 返回一个包含环境变量的对象
  // mode: Vite的运行模式,通常是development 或 production
  // dir: 环境变量文件的查找目录,通常用 process.cwd() 获取当前工作目录
  // base:环境变量文件的基础名称,通常为空字符串,表示默认的 '.env' 文件
  const env = loadEnv(mode, process.cwd(), '');
  
  return {
    resolve: {
      // ↓路径别名
      // 如pages下Home页,可以用 '@/pages/Home/Home' 方式引入,及代表'src/pages/Home/Home'
      alias: {
        '@': path.resolve(__dirname, 'src')
      }
    },
    build: {
      // 类型: boolean | 'terser | 'esbuild'(默认)
      // true | 'terser : 使用Terser作为 JavaScript 代码压缩器,两者效果一样。设置terser需要npm add -D terser
      // false: 禁用 JavaScript 代码压缩, 构建输出的 JavaScript 文件将会保持未压缩状态
      // esbuild: 使用 ESbuild作为 JavaScript 代码压缩器。比terser快 20-40倍,但构建后的文件相对更大
      minify: 'terser',
      // 用于配置 Terser 的对象
      terserOptions: {
        compress: {
          // 构建时,去除 console.log 语句
          drop_console: true
        }
      },
      // 每次构建之前清空输出目录,及重新构建 dist 文件夹
      emptyOutDir: true,
      rollupOptions: {
        output: {
          // 静态资源文件输出到 assets 目录,子目录名称将根据文件扩展名([ext])而定,文件名使用原始文件名([name]),附加了哈希值([hash]),最后附加文件扩展名([extname])
          assetFileNames: 'assets/[ext]/[name].[hash][extname]',
          // 用于配置生产的代码分割 (chunk) 文件的命名规则
          // assets/js目录下,文件扩展名(.js)。name和hash与上述等同
          chunkFileNames: 'assets/js/[name].[hash].js'
        },
      }
    },
    // 初始化就有,代表Vite使用的插件是react
    plugins: [react()],
    server: {
      // 允许从本地网络访问
      host: '0.0.0.0',
      proxy: {
        '/api': {
          // 代理目标地址,从环境变量中获取(在config第一行.env中阐述),也可以直接写成字符串 如:'http://127.0.0.1:8000' (IP和端口号根据情况定)
          target: env.VITE_PROXY_API_URL,
          // 改变源地址,用于支持跨域请求
          changeOrigin: true
        }
      }
    }
  };
});

三、环境变量 .env

1、创建三个文件,分别对应 dev开发环境,test测试环境,prod生产环境.env 文件

书写方式

env 复制代码
# 根据实际使用情况配置
# ENV根据环境书写不同的值, dev、test、prod 方便在配置文件中动态使用
ENV='dev'
# 在配置 axios 
VITE_BASE_API_URL='/api'
# 在 vite.config.ts 中替换proxy的target值,及实际请求地址
VITE_PROXY_API_URL='http://127.0.0.1:8000'

四、配置路由

1、安装路由

cmd 复制代码
npm install --save react-router react-router-dom

src文件夹下,创建如下目录结构

file 复制代码
|- router
    |- modules
        |- routes.tsx
        |- useRoutes.tsx
    |- index.tsx

配置路由的类型 routes.tsx

ts 复制代码
// routes.tsx
import React from 'react';

export interface RouteType {
    path?: string;  // 对应路由
    key: string;    // key值
    element?: React.ReactNode | null;   // 对应的页面
    // 根据情况使用
    title: string,
    icon?: React.ReactNode;     // icon图标,如为 url路径 则为string类型
    hidden?: boolean;           // 可用于显示与否,根据情况使用
    children?: RouteType[];     // 子路由数组
}

配置路由 useRoutes.tsx

tsx 复制代码
// useRoutes.tsx
import { lazy } from 'react'
import RouteType from './routes'

// 利用路由懒加载
const Home = lazy(() => import('@/pages/Home/Home'))

const useRoutes: Array<RouteType> = [
    // 配置路由...
    {
        title:"首页",
        key:"/home",
        path:"/home",
        element:<Home/>,
    }    
]

export default useRoutes;

创建浏览器路由器实例 index.tsx

tsx 复制代码
// index.tsx
import { createBrowserRouter, RouteObject } from "react-router-dom";
import useRoutes from "./modules/useRoutes";

const router = createBrowserRouter(useRoutes as RouteObject[])

export default router;

五、配置axios

官方文档 : Axios中文文档

javascript 复制代码
// 引入axios 
import axios { AxiosRequestConfig } from 'axios'
// 处理JSON 数据中大整数的插件
import JSONBIG from 'json-bigint';
// 根据需求安装,只是用于提供接口请求报错消息提醒
import { message } from 'antd';


// 请求的基础 URL,请求路径会和baseURL拼接,用于发送请求.
let baseURL;
if(process.env.ENV === 'dev') {
    baseURL = 'xxx本地环境xxx';
} else if(process.env.ENV === 'prod') {
    baseURL = 'xxx生产环境xxx';
}

const options:AxiosRequestConfig = {
    baseURL: baseURL,
    timeout: 30000
}

// 创建实例
const service = axios.create(options)
// 请求拦截器
service.interceptors.request.use(
  config => {
    // 判断是否具有 请求头 和 请求方法
    if (!config?.headers || !config?.method) {
      return Promise.reject(new Error('缺少重要参数!'));
    }
    // 传参数据转字符串
    config.data = JSON.stringify(config.data);
    // 设置 HTTP 请求的头部信息中的 Content-Type 字段为 application/json
    // 用于指定请求的数据格式,告诉服务器请求的主体部分是以 JSON 格式提交的。
    config.headers['Content-Type'] = 'application/json';
    // 获取token
    const token = localStorage.getItem('token');
    if (token) {
      // 设置请求头中用于 token 的键值
      config.headers['access-token'] = token;
    }
    // 定义在接收到响应数据之前,对响应数据进行的自定义转换。
    // 该选项允许你指定一个或多个转换函数,这些函数将在 Axios 处理响应数据之前执行。
    config.transformResponse = [
      function (data) {
        // 使其在解析 JSON 时将大整数以字符串形式表示,以防止数值截断或转换为科学计数法。
        const json = JSONBIG({
          storeAsString: true
        });
        const res = json.parse(data);
        return res;
      }
    ];
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);
// 响应拦截器
service.interceptors.response.use(
  response => {
    const res = response.data;

    const { code, msg } = res;

    if (code !== 0) {
      message.error(msg || 'Error');
      if ([100001, 100002].includes(code)) {
          localStorage.clear();
          location.replace('/login');
      }
      return Promise.reject(res);
    }

    return res;
  },
  error => {
    httpErrorStatusHandle(error);
    return Promise.reject(error);
  }
);

// 处理异常的函数
function httpErrorStatusHandle(error: any) {
  // 处理被取消的请求
  let msg = '';
  if (error && error.response) {
    switch (error.response.status) {
      case 302:
        msg = '接口重定向了!';
        break;
      case 400:
        msg = '参数不正确!';
        break;
      case 401:
        msg = '您未登录,或者登录已经超时,请先登录!';
        break;
      case 403:
        msg = '您没有权限操作!';
        break;
      case 404:
        msg = `请求地址出错: ${error.response.config.url}`;
        break; // 在正确域名下
      case 408:
        msg = '请求超时!';
        break;
      case 409:
        msg = '系统已存在相同数据!';
        break;
      case 500:
        msg = '服务器内部错误!';
        break;
      case 501:
        msg = '服务未实现!';
        break;
      case 502:
        msg = '网关错误!';
        break;
      case 503:
        msg = '服务不可用!';
        break;
      case 504:
        msg = '服务暂时无法访问,请稍后再试!';
        break;
      case 505:
        msg = 'HTTP版本不受支持!';
        break;
      default:
        msg = '异常问题,请联系管理员!';
        break;
    }
  }
  if (error.message.includes('timeout')) msg = '网络请求超时!';
  if (error.message.includes('Network'))
    msg = window.navigator.onLine ? '服务端异常!' : '您断网了!';
  message.error(msg || 'Error');
}

export default service;

六、package.json

配置package.json中scripts,用于启动和打包时,针对不同的环境

json 复制代码
  // 当前模块\包名称
  "name": "react_project_demo",
  // 表示这是一个私有项目
  "private": true,
  // 当前包的版本号
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    // 
    "dev": "vite --mode dev",
    //
    "dev-prod": "vite --mode prod",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router": "^6.18.0",
    "react-router-dom": "^6.18.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.15",
    "@types/react-dom": "^18.2.7",
    "@typescript-eslint/eslint-plugin": "^6.0.0",
    "@typescript-eslint/parser": "^6.0.0",
    "@vitejs/plugin-react": "^4.0.3",
    "eslint": "^8.45.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.3",
    "typescript": "^5.0.2",
    "vite": "^4.4.5"
  }
}
相关推荐
APP 肖提莫1 分钟前
MyBatis-Plus分页拦截器,源码的重构(重构total总数的计算逻辑)
java·前端·算法
问道飞鱼13 分钟前
【前端知识】强大的js动画组件anime.js
开发语言·前端·javascript·anime.js
k093314 分钟前
vue中proxy代理配置(测试一)
前端·javascript·vue.js
傻小胖16 分钟前
React 脚手架使用指南
前端·react.js·前端框架
程序员海军28 分钟前
2024 Nuxt3 年度生态总结
前端·nuxt.js
m0_7482567838 分钟前
SpringBoot 依赖之Spring Web
前端·spring boot·spring
web135085886351 小时前
前端node.js
前端·node.js·vim
m0_512744641 小时前
极客大挑战2024-web-wp(详细)
android·前端
若川1 小时前
Taro 源码揭秘:10. Taro 到底是怎样转换成小程序文件的?
前端·javascript·react.js
潜意识起点2 小时前
精通 CSS 阴影效果:从基础到高级应用
前端·css