Vite + React +TypeScript 构建标准化react应用

背景

之前公司项目采用的是umi脚手架一体化构建工具,得益于对webpack与各框架的集成和封装,使得快速上手的能力大大加强,但是随着项目的不断迭代与功能增加,依赖的库也是越来越多,目前最明显的感受就是每次启动与打包构建的时长,往往是好几分钟~,热更新有时也要耗费数秒,对于开发效率与体验影响很大。。。

之前尤大发布vite1.0时也了解了一点,最明显感受就是一个字“快”,不过一直没仔细研究过,只知道是基于`esbuild`和`rollup`,目前`vite2.0`已经发布,完全作为一个独立的构建工具,对`react`等其他非`vue`框架有着很好的支持。最近也算忙里偷闲,算是稍微研究了一下基本知识。本篇文章记录我以`vite`构建`react`的过程及细节,后续会继续深入研究输出`vite`相关系列文章,敬请期待

目标

我对构建项目的要求如下:

  • 支持Typescript
  • 支持ReactJSX语法
  • 支持ES6语法
  • 支持Less module
  • 支持EslintPrettierPre-commit hook
  • 支持HMR快速热更新
  • 支持Antd按需引入与主题样式覆盖
  • 支持Proxy代理、alias别名
  • 兼容传统浏览器
  • 开发启动速度要够快,以秒计算
  • 支持懒加载和chunk分割

介绍

前置条件之一

浏览器原生支持 ES 模块。

特点

  • 基于原生 ES 模块,即 <script type="module" >,做到快速加载
  • 使用 Esbuild 预构建依赖 (本地开发环境)
  • 使用 Rollup 打包代码(线上生产环境)
  • HMR 是在原生 ESM 上执行的
  • 利用对 HTTP 头信息的控制,优化缓存与重加载,高效率利用浏览器能力。
  • 开箱即用,内置多种支持,如:Typescript支持、JSX支持、CommonJSUMD兼容、css预处理器与css modules

vite对模块的分类

  • 依赖
    • 在开发时不会变动的纯 JavaScript。(如第三方依赖antdlodash等)
    • 在该场景采用具有优势的 Esbuild 处理。(大量模块的组件库、CommonJS格式的文件等)
  • 源码
    • 通常包含一些并非直接是 JavaScript 的文件,需要转换,时常会被编辑。(JSXCSSVue/React组件等)
    • 会根据路由拆分代码按需加载模块
    • Vite 以 原生 ESM 方式提供源码

概念

预构建:将有许多内部模块的 ESM 依赖关系转换为单个模块,以提高后续页面加载性能。简单来说就是尽量合并与减少请求。

例如:当我们引入的一个第三方模块依赖了大量其他模块时,在不合并请求的情况下,会请求上百次不等,造成网络拥塞影响性能,而通过预构建合并后只需要一个请求即可。(lodash-es 有超过个内置模块!当我们执行 import { debounce } from 'lodash-es' 时,浏览器同时发出 600 多个 HTTP 请求!通过预构建 lodash-es 成为一个模块,我们就只需要一个 HTTP 请求了!)

相较于传统的 webpack 构建工具,先打包构建所有的依赖和项目代码,然后再启动开发服务器。Vite 则利用浏览器对 ESM 的支持,先启动开发服务器,然后再根据代码执行按需加载剩下所需的对应模块。

因为缓存,在我们第二次启动时几乎可以做到秒开!非常的可怕~

官网图

官网图很清晰的描绘了区别:

Bundle based dev server

Native ESM based dev server

步骤

项目初始化

官方支持React模板预设有:reactreact-ts,因为我需要Typescript,所以直接用这个模板,省事了~

# npm 6.x
npm init @vitejs/app my-react-app --template react-ts

# npm 7+, 需要额外的双横线:
npm init @vitejs/app my-react-app -- --template react-ts

# yarn
yarn create @vitejs/app my-react-app --template react-ts

引入react三件套

这里有兴趣的可以尝试下 pnpm 包管理工具,安装速度很快,不了解的可以查看pnpm官方文档,相较于传统的npmyarn工具都有很好的性能提升与使用体验,这里不做过多介绍,放张图大家体会下~

注:就目前我的使用情况来看大部分场景几乎都没问题的,不过还是存在一小部分问题。如:安装precommit后Git hooks不生效等。

安装速度比较

安装依赖
# pnpm
pnpm add react react-dom react-router-dom
# or npm
npm i react react-dom react-router-dom
创建页面

src目录下创建pages目录放置页面组件模块,然后我们简单写两个页面测试下:

// pages/Home/index.tsx
import React from 'react';

const Home: React.FC = () => <div> Home </div>;

export default Home;

// pages/About/index.tsx
import React from 'react';

const About: React.FC = () => <div> About </div>;

export default About;
修改文件App.tsx
// App.tsx
import React, { Suspense } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from './pages/Home'
import About from './pages/About'

const App = () => {
  return (
    <Suspense fallback={<span>loading</span>}>
      <Router>
        <Switch>
          <Route key="/home" path="/home" component={Home}></Route>
          <Route key="/about" path="/about" component={About}></Route>
        </Switch>
      </Router>
    </Suspense>
  );
};

export default App;

vite-react-app-1

vite-react-app-2

配置路由/界面

新建layouts组件,主要用于区别渲染登录注册页面布局界面:

layouts/BasicLayout.tsxlayouts/UserLayout.tsx

这里就不一一做展示了,详细代码见仓库,地址贴在下面了。

新建路由配置文件router/index.ts:

import React from 'react';

const Page404 = React.lazy(() => import('../pages/404'));
const Home = React.lazy(() => import('../pages/Home'));
const Login = React.lazy(() => import('../pages/User/Login'));
const Register = React.lazy(() => import('../pages/User/Register'));

const routes: IRoute[] = [
  {
    path: '/user',
    component: React.lazy(() => import('../layouts/UserLayout')),
    meta: {
      title: '用户路由',
    },
    redirect: '/user/login',
    children: [],
  },
  {
    path: '/',
    component: React.lazy(() => import('../layouts/BasicLayout')),
    meta: {
      title: '系统路由',
    },
    redirect: '/home',
    children: [
      {
        path: '/home',
        meta: {
          title: '首页',
          icon: 'home',
        },
        component: <Home />,
      },
      {
        path: '/about',
        meta: {
          title: '关于',
          icon: 'about',
        },
        component: <About />,
      },
    ],
  },
]

export default routes;

创建store状态管理文件

react hooks诞生后,大部分场景使用hooksprops进行状态管理基本可以满足多数需求,少部分全局应用信息与用户信息等需要全局状态管理的,这里我觉得也不需要完整引入一个reduxmobx等这种库。当然还要结合具体场景和公司技术栈确定,较大型和复杂的项目等视情况而定~

我这里使用了zustand做了简单配置,使用起来也是比较的简单,详情参见官方文档

// 创建store
import create from 'zustand'

const useStore = create(set => ({
   
  bears: 0,
  increasePopulation: () => set(state => ({
    bears: state.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值