介绍

项目中常用 Webpack 构建 React 项目,但随着项目的依赖和架构越来越臃肿,无论是初始启动调试开发,或者构建依赖包都需要很长的时间,非常影响前端开发时的幸福感。

所以,Vue的作者尤雨溪开发基于原生系统ES模块的构建工具Vite@2,将应用的模块分为 依赖 和 源码 两类进行单独处理。

  1. 依赖:多数为ESM或者CommonJs模块依赖,例如 node_moduels 中的很多组件库,这些模块在开发时,几乎变化不大,所以Vite会将依赖拆分成大量的小模块系统中,不再进行编译处理。并且 Vite使用 ESBuild 预构建依赖,Esbuild使用Go编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
  2. 源码:通常包含非JS文件,例如JSX、CSS或者Vue组件,并且变化较大,但不是所有的源码都同时被加载,可能存在路由分割页面代码。

Vite 将会议 原生ESM 方式服务源码,这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入的代码,即只在当前屏幕上实际使用时才会被处理。

1. 基于Bundle包形式的构建开发流程

基于 Vite 搭建 React Antd TS Router 项目 - 图1

2. 基于 Native ESM 包形式的构建开发流程:

基于 Vite 搭建 React Antd TS Router 项目 - 图2
可以看到,使用Vite来处理源码包的构建,可以做到按需取用,按需构建和替换,能够加快构建速度。

开始搭建

环境

  1. Node12+
  2. yarn 1.22.10 +

技术栈

使用Vite@2创建React项目,使用的技术栈包含:

  1. React@17
  2. React-Router
  3. Antd@4
  4. Typescript
  5. Less —- 处理Antd的主题
  6. Sass —- 编写样式

工程化配置

其中项目配置包括:

  1. Antd的动态加载/打包
  2. Atnd的主题替换
  3. Alias别名
  4. 打包路径的更换
  5. 路由组件懒加载

初始化项目

  1. yarn create @vitejs/app

通过上述命令创建 vite 项目,可以选择使用 react、typescript技术栈。
创建完成后,项目结构如下:

  1. ├── README.md
  2. ├── dist
  3. ├── assets
  4. ├── favicon.svg
  5. ├── index.html
  6. └── logo.svg
  7. ├── index.html
  8. ├── package.json
  9. ├── public
  10. ├── favicon.svg
  11. └── logo.svg
  12. ├── src
  13. ├── About
  14. ├── App
  15. ├── Index
  16. ├── Route
  17. ├── main.tsx
  18. ├── source
  19. └── style
  20. ├── tsconfig.json
  21. ├── vite.config.ts
  22. └── yarn.lock

通过运行:

  1. # 启动 dev 调试
  2. $ yarn dev
  3. # 启动构建
  4. $ yarn build
  5. # 启动构建server预览
  6. $ yarn server

上述运行完成后,可以感受到基于 Vite 的快速启动/热更新替换的效果,非常快。。。

入口文件

index.html是该 Vite 项目的入口文件, 在项目根目录。

  1. <script type="module" src="/src/main.tsx"></script>

配置 React-Router

安装 react-router-dom 来处理单页面应用逻辑:

  1. $ yarn add react-router-dom -S
  1. src 目录下创建 Route 目录,并创建 index.ts 文件,内容如下: ```typescript import { lazy } from ‘react’;

// 此处使用 react.lazy 进行组件懒加载 const Index = lazy(() => import(‘../Index’)); const About = lazy(() => import(‘../About’));

const routes = [ { path: “/“, component: Index }, { path: “/about”, component: About } ];

export default routes

  1. 2. `src` 目录下分别创建 Index About 组件:
  2. About 组件:
  3. ```typescript
  4. // src/About/index.tsx
  5. import React from 'react';
  6. import { Button } from 'antd';
  7. import { useHistory } from "react-router-dom";
  8. const About = () => {
  9. let history = useHistory();
  10. return (
  11. <div>
  12. <h1>about page</h1>
  13. <Button type="default" onClick={() => {
  14. history.push("/");
  15. }}>跳转到index page</Button>
  16. </div>
  17. )
  18. }
  19. export default About;

Index 组件:

  1. // src/Index/index.tsx
  2. import React, { useState } from 'react';
  3. import { Button } from 'antd';
  4. import { useHistory } from "react-router-dom";
  5. const Index = () => {
  6. let history = useHistory();
  7. return (
  8. <div className="count" >
  9. <h1>Index Page</h1>
  10. <Button type="default" onClick={() => {
  11. history.push("/about");
  12. }}> 跳转到about page </Button>
  13. </div>
  14. )
  15. }
  16. export default Index;
  1. 在 App.tsx 入口文件中配置路由: ```typescript import React, { Suspense } from ‘react’ import { HashRouter as Router, Switch, Route } from “react-router-dom”; import routes from ‘./Route/index’

export const App = () => { return ( // React 懒加载组件需要使用 Suspense 包裹才能加载 loading}> { routes.map(route => ) } ) }

  1. 如上配置,即可完成 单页面 的配置,在构建打包时,也能看到对应的组件进行了分包处理:<br />![](https://cdn.nlark.com/yuque/0/2021/png/115206/1618643070781-609a21b5-422d-481a-9fb8-519e93be2825.png#clientId=ua70d76e9-75b0-4&from=paste&height=512&id=ub0fb03ef&margin=%5Bobject%20Object%5D&originHeight=512&originWidth=884&originalType=binary&size=583432&status=done&style=none&taskId=u8bd849a8-d407-4750-8e33-0091ce3874c&width=884)
  2. <a name="mTPnr"></a>
  3. ### 配置 Antd
  4. 安装Antd组件库:
  5. ```bash
  6. $ yarn add antd -S

安装 lessvite-plugin-imp
其中 less 用来处理 antd 组件的默认主题,vite-plugin-imp 用来处理 antd 的样式的按需打包。

  1. $ yarn add less vite-plugin-imp -D

安装完成后,在 vite.config.js 中配置:

  1. import vitePluginImp from "vite-plugin-imp";
  2. export default defineConfig({
  3. plugins: [
  4. // 配置 antd 样式的按需打包
  5. vitePluginImp({
  6. libList: [
  7. {
  8. libName: "antd",
  9. style: (name) => `antd/es/${name}/style`,
  10. },
  11. ],
  12. }),
  13. // 其他插件
  14. ...,
  15. ],
  16. css: {
  17. preprocessorOptions: {
  18. less: {
  19. // 支持内联 JavaScript
  20. javascriptEnabled: true,
  21. // 配置 antd 的主题颜色
  22. modifyVars: {
  23. "@primary-color": "green",
  24. },
  25. }
  26. },
  27. },
  28. });

配置完成后,在项目中使用:

  1. import { Button } from 'antd';
  2. <Button type="default" onClick={() => {
  3. history.push("/about");
  4. }}> 跳转到about page </Button>

配置 Alias

在项目的 vite.config.js 中配置别名:

  1. export default defineConfig({
  2. plugins: [
  3. reactRefresh(),
  4. ],
  5. base: "./",
  6. // 配置别名
  7. resolve: {
  8. alias: {
  9. image: "/src/source/image",
  10. },
  11. }
  12. });

在项目中使用:

  1. .bg {
  2. width: 200px;
  3. height: 200px;
  4. margin: 20px 0;
  5. background: url("image/1.jpeg") no-repeat center center;
  6. background-size: 100%;
  7. }

构建输出:
基于 Vite 搭建 React Antd TS Router 项目 - 图3
同样的,使用 import 导入语法,路径同样会被替换掉。

插件

如果需要其他插件,可查看Awesome Vite 仓库是否有合适的工具。

体验

经过直观的测试,Vite 的初始启动服务、实时编译替换文件的速度非常的快,经过和内部的项目集成测试,发现整体的速度提升非常明显,能够达到秒级别开发体验。

整个项目搭建完成后,构建的结果也非常满意,其中包含 react+antd+router+sass+ts 的项目构建数据如下:
基于 Vite 搭建 React Antd TS Router 项目 - 图4
可以看到,主包的大小为148kb,分包的大小也非常小,相比于使用 CRA 搭建的 React 项目,同样的技术栈,包的大小能够减少非常多。

引用

  1. Vite
  2. Antd
  3. ESBuild
  4. vite-plugin-imp