Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vite 2 + React 实践 #1

Open
Ivocin opened this issue Mar 12, 2021 · 0 comments
Open

Vite 2 + React 实践 #1

Ivocin opened this issue Mar 12, 2021 · 0 comments
Labels
Blog blogs

Comments

@Ivocin
Copy link
Owner

Ivocin commented Mar 12, 2021

前言

Vite 无疑是当前最火热的项目之一,随着春节后 2.0 版本的发布,越来越多开发者开始关注起了这个项目。这个号称下一代前端构建工具的给我们最大的印象的就是。日常被缓慢的项目启动时间和 HMR 折磨,有了 Vite 之后,真的不要太爽。虽然 Vite 和框架无关,但应用较多的仍然是 Vue 工程,那么 React 工程是否能够顺利使用呢,这两周在工作之余,就开始了 Vite 2.0 + React 的尝试。当然其中踩了比较多的坑,比如 Antd 的引入带来的一系列问题,别名怎么写,代理如何配置,集成 ahooks 等等,希望能够帮助到使用 React 又想使用 Vite 提升开发效率的同学,少走弯路。当然,我们还可以从实践的过程中直观了解到 Vite 的预打包原理以及性能真实的感受。

本文源码地址在 vite-playgrounds 中,如果阅读中发现问题,欢迎 pr。

这段时间也参与了 Vite 中文文档 的翻译工作,欢迎有兴趣的同学前来优化和勘误。

另外做个预告,春节期间花了时间参与了尤大在 Twitch 上做客 Open Source Friday 节目的直播视频 —— Next generation frontend tooling with ViteJS ✨ Open Source Friday ✨ 的字幕翻译工作,在视频里有尤大关于 Vite 的各项功能的详细阐述、大神在线编码、在线 Debug、大佬 diss webpack 以及对 Vite 的哲学思考。视频总时长一个小时,假期复工后就没有太多精力投入了,估计下周会做好发出来,敬请期待。

好了,现在和我一起,Step by Step 进入 Vite 2 + React 实战之旅。

初始化项目

$ npm init @vitejs/app

选择项目名和模板:


安装依赖并启动:

$ cd vite-react
$ npm install
$ npm run dev

对比使用 webpack 搭建 React 环境可以看出,使用 Vite 后,添加 BabelReactwebpack-dev-server 的工作都可以省略了:

添加 Antd 爬坑记

样式爬坑记

$ npm install antd

App.jsx 中引入 antd

import { DatePicker } from ‘antd’;

保存后,页面 reload,注意不是 HMR,此时 Antd 已经被引入:

然后我们来添加 DatePicker,发现没有样式:

按照 antd 官网文档指引,引入 CSS 样式,稍微好了一些,但是仍然不正常:

尝试引入 Less,直接报错:

Vite 内置支持 Less,但是使用需要用户手动安装 Less,详见官网文档:Features # CSS Pre-processors

$ npm install -D less

安装完重新启动,又出现了新的错误:

熟悉的味道,是 Antd 的报错没错了。错误信息里提示可以看这个 Issue,没看这个 Issue 有两年了,发现这个 Issue 越来越大了,因为期间 less-loader 升级又带来了新坑。解决方案总结起来就是在 webpackless-loader 中开启 javascriptEnabled,详见这个 Commit

那么在 Vite 中怎么做呢,Vite 也开放了 CSS 预处理器的配置,详见官网文档 ,在 vite.config.js 文件中添加如下配置:

// vite.config.js
...
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
      },
    }
  }
...

终于,样式正常了:

有关使用全量 Antd 包的警告分析

另外需要注意的一点是,打开调试窗口,又一个熟悉的警告又出现了,相信早期使用 Antd 开发的同学都不陌生:

原来的项目使用的是 webpack,在 webpack@2 之后,就支持 ES 模块的 tree shaking 了,这个警告不会出现。

而在 Vite 中,我们可以查看官方文档Vite 会对 npm 依赖进行预构建并重写为合法的 url。在本项目中,ViteAntd 预构建到 /node_moduls/.vite 文件夹,并且将 url 重写为 /node_modules/.vite/antd.js?v=d2a18218,因此会出现这个警告。

不过不用担心,在生产包仍然会进行 tree shaking。而开发环境即使引入全量的 Antd 包,Vite 基于 esbuild 的预编译速度超快,而且之后浏览器会缓存住这个包,开发体验不降反升,这个警告就可以忽略了。

更换主题

再来试试改变主题是否有效:

按照官网的指引,使用 lessmodifyVar 来覆盖 less 变量,从而达到改变主题的目的,定制主题 - Ant Design
webpack 配置在 less-loader 里不同, 在 Vite 中则简单很多,仍然在 lessoption 里配置就可以了:

// vite.config.js
...
      less: {
        javascriptEnabled: true,
        modifyVars: {
          "primary-color": "#1DA57A",
          "link-color": "#1DA57A",
          "border-radius-base": "2px",
        },
      },
...

可以看到样式生效了:

按照这个思路,我们修改为暗黑主题也比较简单了:

import { defineConfig } from "vite";
import reactRefresh from "@vitejs/plugin-react-refresh";
import { getThemeVariables } from "antd/dist/theme";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [reactRefresh()],
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
        modifyVars: {
          ...getThemeVariables({
            dark: true,
          }),
          ...{
            "primary-color": "#1DA57A",
            "link-color": "#1DA57A",
            "border-radius-base": "2px",
          },
        },
      },
    },
  },
});

没问题,暗黑主题生效:

配置代理,能通过 RESTFul 的方式访问

参考官网的 server.proxy 配置,这里需要特别注意 proxy 的写法和我们之前使用的 webpack-dev-server 里面的 proxy 配置稍有不同,如下:

// vite.config.js
  server: {
    proxy: {
      '/api': {
        target: 'http://jsonplaceholder.typicode.com/',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },

此时我们访问 http://localhost:3000/api/users ,就能访问到 jsonplaceholder.typicode.com/users 的数据了

集成 React Router

下面我们来添加菜单和路由,首先引入 React Router

$ npm i react-router-dom

新建 index.jsx 文件:

import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import App from "./App";

export default function Index() {
  return (
    <Router>
      <Switch>
        <Route path="/app">
          <App />
        </Route>
      </Switch>
    </Router>
  );
}

修改 main.jsx 文件,将 App 替换为 Index

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
- import App from './App'
+ import Index from './index'

ReactDOM.render(
  <React.StrictMode>
-   <App />
+   <Index />
  </React.StrictMode>,
  document.getElementById('root')
)

此时访问 http://localhost:3000/app 可以访问到 App 页面,路由生效。

我们再来增加一个菜单,新建 Layout.jsx 文件:

import React from "react";
import { Menu } from "antd";
import { Link } from "react-router-dom";

export default function Layout() {
  return (
    <Menu selectedKeys="App" mode="horizontal">
      <Menu.Item key="App">
        <Link to="/app">App</Link>
      </Menu.Item>
    </Menu>
  );
}

最后在 index.jsx 引入 Layout 文件,以上过程详见 这个 Commit

注意别名的用法 —— breaking change

注意 Vite@2UserConfig.alias 已经过时,改为使用 resolve.alias 替代,写法也和 Vite@1 不一样,详见 官网文档 - resolve-aliasrollup plugins 文档

// vite.config.js
...
import path from "path";
...
  resolve: {
    alias: [
      {
        find: /^~/,
        replacement: path.resolve(__dirname, "src"),
      },
    ],
  },

...

然后我们调整文件结构,然后使用别名代替相对路径,详见 这个
Commit

用户列表页面

接下来我们开发一个模拟真实接口的用户列表 ,参考 umi@2 + dva,完成用户管理的 CURD 应用 的步骤

新建 User 页面

添加 User 路由和页面,详见这个 Commit

此时访问 http://localhost:3000/user 就能看到新增的 User 页面了:

请求接口爬坑记

请求接口数据,这里使用 ahooksuse-request

这里使用 npm 7 安装 会报错:

因为 npm 7 会自动安装 peerDependency,而 ahookspeerDependencyreact@^16.8.6 ,导致与本项目的 react@17 版本冲突报错,这个问题已经在 这个 pr里修复了,但是目前还没有发包,暂时使用 yarn 绕过这个问题:

$ yarn add @ahooksjs/use-request

现在就可以使用 use-request 请求 /api/users 获取用户信息了:

  const { data, error, loading } = useRequest('/api/users')

展示数据

接口请求的坑填好后,就可以展示用户信息了。我们来添加一个表格展示用户信息,详见 这个 Commit

use-request 返回了 loading,再结合 antd table 组件的 loading,处理 loading 就很方便了:

至此,模拟接口请求数据的页面就完成了。

关于分页的坑

由于我们接口采用模拟接口,分页信息在 Response Headers 里面,请求 http://jsonplaceholder.typicode.com/users?_page=1&_limit=5 可以看到:

查看了 ahooksAPI,发现并没有对 Response Headers 的处理功能,查看 源码 发现确实目前没有办法拿到 Headers 里的值:

真实接口一般分页信息都会在 Response Body 中,分页数据就很容易处理了,这个坑就不费时间填了。

What Else

当然没有结束,不过剩下的过程就比较常规了,罗列如下:

  • 集成 Redux,或者使用封装过的 dva.js
  • 约定式路由
  • 还记得 babel-plugin-import 吗,在 Vite 中,如果想样式按需加载,可以尝试使用这个插件:vite-plugin-style-import,现在已经支持 Vite 2
  • 想使用 TypeScript,可以使用 @vitejs/create-appreact-ts 模板,然后按照本文的步骤配置即可
  • Production ModeSSR,参照官网配置即可,遇到什么坑可以一起讨论。

本文首发于掘金:Vite 2 + React 实践

@Ivocin Ivocin added the Blog blogs label Mar 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Blog blogs
Projects
None yet
Development

No branches or pull requests

1 participant