一、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
最终实现效果如图:
项目相关配置如下:
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);