vite从零开始配置react项目介绍

551 阅读3分钟

一、Vite 的定义

Vite 是面向现代浏览器的一个更轻、更快的 Web 应用开发工具,核心基于 ECMAScript 标准原生模块系统(ES Modules)实现。

表象功能上看,Vite 可以取代基于 Webpack 的 vue-cli 或者 cra 的集成式开发工具,提供全新的一种开发体验。

具体细节往下看。

二、Vite 的由来

在此之前,如果我们所开发的应用比较复杂(代码量偏大),使用 Webpack 的开发过程相对没有那么「丝滑」,具体表现为以下两点:

  • Webpack Dev Server 冷启动时间会比较长,稍大一点的项目启动开发服务都需要等待 10 - 20 秒;
  • Webpack HMR 热更新的反应速度比较慢,修改完代码需要等待编译器全部编译完成才能开始同步到浏览器; 摘抄自:blog.zce.me/2020/10/vit…

三、相关项目具体配置如下

Vite 官方目前提供了一个比较简单的脚手架:create-vite-app,可以使用这个脚手架快速创建一个使用 Vite 构建的 react 应用 可以参考官方文档 https://vitejs.bootcss.com/guide/#scaffolding-your-first-vite-project

最终实现效果如图: 截屏2021-12-20 下午7.07.26.png

项目相关配置如下:

截屏2021-12-11 下午4.07.08.png

vite.config.ts中内容如下


import reactRefresh from '@vitejs/plugin-react-refresh';
import path from 'path';
import { defineConfig, loadEnv } from 'vite';
const DEV = 'development';
export default ({ mode }) => {
  const configEnv = loadEnv(mode, process.cwd());
  const productionBase = configEnv.VITE_PRODUCTION_BASE;

  return defineConfig({
    base: mode === DEV ? '/' : productionBase,
    plugins: [ reactRefresh() ],
    clearScreen: false,
    resolve: {
      alias: [
        { find: /^~/, replacement: '' },
        { find: 'services', replacement: path.resolve(__dirname, './src/services/') },
        { find: 'assets', replacement: path.resolve(__dirname, './src/assets') },
        { find: 'components', replacement: path.resolve(__dirname, './src/components') },
        { find: 'config', replacement: path.resolve(__dirname, './src/config') },
        { find: 'pages', replacement: path.resolve(__dirname, './src/pages') },
        { find: 'utils', replacement: path.resolve(__dirname, './src/utils') },
        { find: 'context', replacement: path.resolve(__dirname, './src/context') },
        { find: 'types', replacement: path.resolve(__dirname, './src/types') },
      ],
    },
    css: {
      modules: {
        scopeBehaviour: 'local',
        localsConvention: 'camelCase',
      },
      // less预加载
      preprocessorOptions: {
        less: {
          // 自定义样式,可用于修改antd原有样式
          modifyVars: {},
          javascriptEnabled: true,
        },
      },
    },
    server: {
      port: 3000,
      host: 'x.x.0.1',
      open: true,
      proxy: {
        '/api': {
          target: 'https://url',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, ''),
        },
      },
    },
    build: {
      // 打包输出
      rollupOptions: {
        output: {
          entryFileNames: '[name].js',
          assetFileNames: '[name][extname]',
          chunkFileNames: '[name].js',
        },
      },
    },
  });
};

utils/servers.js文件内容如下:统一封装发送请求

import axios from "axios";
const baseURL = (import.meta.env.VITE_BASE_URL)

const instance = axios.create({
    baseURL,
    timeout: 30 * 1000,
})

// 请求拦截
// 所有的网络请求都会先走这个方法,我们可以在它里面添加一些自定义内容
instance.interceptors.request.use(function (config) {
    console.group('全局请求拦截');
    console.groupEnd();
    config.headers.token = '111111';
    return config;
}, function (err) {
    return Promise.reject(err);
});

// 响应拦截
// 所有的网络请求返回数据之后都会先执行此方法
// 此处可以根据服务器的返回状态码作相应的数据 404 401 500
instance.interceptors.response.use(function (response) {
    console.group('全局响应拦截');
    console.log(response);
     // 请求超时 返回登录
    // if (data.retCode == '-100')         
    //     removeToken();
    //     localStorage.clear();
    //     router.push('/login');
    // }
    return response;   
}, function (err) {
    return Promise.reject(err);
});

export function get(url, params) {
    return instance.get(url, { params });

}

export function post(url, data) {
    return instance.post(url, data);
}

export function del(url, data) {
    return instance.delete(url, data);
}

export function put(url, data) {
    return instance.put(url, data)
}

router.js文件如下

import {Redirect, Route,RouteProps,BrowserRouter as Router,Switch} from "react-router-dom";
import React,{ FC, memo } from "react";
import Layout from 'components/Layout';

import Login from 'pages/Login';
import Home from 'pages/Home';
import Error from 'pages/Error';
import Base from 'pages/Base';
interface IRouteProps extends RouteProps{
    path:string,
    name:string,
    component:any,
}

const routes: IRouteProps[] = [
    { path: '/home',name:"首页", component: Home, exact: true },
    { path: '/base',name:"基础配置",component: Base, exact: true },
];

const RouterConfig: FC = ()=>(
    <Router>
        <Switch>
            <Route path="/login" component={Login}/>
            <Layout menu={routes}>
            <Switch>
                 <Redirect to='/home' exact from='/' />
                    {
                        routes.map((item,index)=>
                            <Route
                              key={index}
                              path={item.path}
                              component={item.component}
                              exact={item.exact}
                            />
                        )
                    }
                <Route path="/*" component={Error} />
            </Switch>
            </Layout>
        </Switch>
    </Router>
)
export default memo(RouterConfig)

home/index.tsx 页面如下

import { Link } from 'react-router-dom';
import React, { FC, memo ,useEffect,useState} from 'react';
import { Button ,Table} from 'antd';
import * as Api from "../../utils/servers.js";
import './index.less';


const columns = [
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    render:(text:any) => {
      return(<div>{text.title} {text.first} {text.last}</div>)

    }
  },
  {
    title: '性别',
    dataIndex: 'gender',
    key: 'gender',
  },
  {
    title: '电话',
    dataIndex: 'cell',
    key: 'cell',
  },

  {
    title: '邮箱',
    dataIndex: 'email',
    key: 'email',
  },
];
const Home: FC = () => {
   const [resdata,setResData] = useState([]);
  useEffect(()=>{
     queryUser();
  },[])

  const queryUser= async() => {
    await Api.get("api/api?results=55")
    //then获取成功;response成功后的返回值(对象)
    .then((response:any) => {
      console.log("response.data.results",response.data.results)
      setResData(response.data.results)
    })
    //获取失败
    .catch((error:any) => {
      console.log(error);
      alert("网络错误,不能访问");
    });
  
}

  return (
    <div>
      <div className="top">
        <Button type="primary" danger>
          Primary
        </Button>
        <Button danger>Default</Button>
        <Button type="dashed" danger>
          Dashed
        </Button>
        <Button type="text" danger>
          Text
        </Button>
        <Button type="link" danger>
          Link
        </Button>
      </div>
      <Table dataSource={resdata} columns={columns}  />
    </div>
  );
};

export default memo(Home);