新蜂商城开源仓库(内涵 Vue 2.x 和 Vue 3.x 的 H5 商城开源代码,带服务端 API 接口):https://github.com/newbee-ltd

Vue 3.x + Vant 3.x + Vue-Router 4.x 高仿微信记账本开源地址(带服务端 API 接口):https://github.com/Nick930826/daily-cost

本文章源码地址:https://github.com/Nick930826/vite-react-app

前言

最近公司要做一个小项目,我问老大能不能用 Vue 写,因为公司一直用 React, 主要是想尝试一下 ViteVite 又是祖师爷出的,所以我想试试用 Vue 作为技术栈。老大问我:“屎吃不吃。” 我隐约觉得老大是在骂祖师爷,但又没法反驳,于是就尝试用 Vite + React 的形式整一个项目架子。

这里默认大家都装了 Node 环境了。
Vite 2.0   React   Ant Design 4.0 搭建开发环境 - 图1

知识点

  • Vite 初始化 React 项目
  • 引入路由插件 react-router-dom
  • 引入 Ant Design 组件库
  • 配置 Ant Design 按需引入
  • 配置 Ant Design 主题色
  • 配置打包时和运行时的环境变量 env
  • axios 二次封装
  • 打包静态资源的路径
  • Vite 的一些配置如开发端口、 proxy 代理、 alias 别名等

    开动

    初始化 Vite + React 项目

    这里不得不感慨,年前还是 Vite 1.x,年后就变成 2.x 了。说明两个问题,祖师爷对这个项目很积极,还有就是不确定因素比较多。但这不妨碍我们去学习它,因为真的又香又快。放个官方中文文档,有兴趣的可以看看文档。
    Vite 2.0   React   Ant Design 4.0 搭建开发环境 - 图2
    Vite 官方提供两种初始化项目的方式,一种是:
    1. npm init @vitejs/app
    可以自由选择配置。还有一种是直接用官方提供的模板,一键生成: ```bash

    npm 6.x

    npm init @vitejs/app vite-react-app —template react

npm 7+, 需要额外的双横线:

npm init @vitejs/app vite-react-app — —template react

  1. 本教程采用第二种形式,生成项目如下:<br />![](https://cdn.nlark.com/yuque/0/2021/png/232355/1615517805566-252bb528-6024-4e58-a3ca-bedda83afd2f.png#align=left&display=inline&height=356&margin=%5Bobject%20Object%5D&name=&originHeight=356&originWidth=956&size=0&status=done&style=none&width=956)<br />按照上述步骤,进入 `vite-react-app` ,安装完包之后,启动项目:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/232355/1615517925012-21c9ab84-627b-41df-9ba3-2937f6763357.png#align=left&display=inline&height=1272&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1272&originWidth=2878&size=177940&status=done&style=none&width=2878)<br />此时你已经成功搭建出 `Vite` + `React` 的开发环境。🎉 🎉 🎉
  2. <a name="LFWD4"></a>
  3. #### 引入路由插件 react-router-dom
  4. 首选安装 `react-router-dom`,指令如下:
  5. ```bash
  6. npm i react-router-dom -S

在项目 src 目录下新增 container 目录用于放置页面组件,再在 container 下新增两个目录分别是 IndexAbout ,添加如下内容:

  1. // Index/index.jsx
  2. import React from 'react'
  3. export default function Index() {
  4. return <div>
  5. Index
  6. </div>
  7. }
  8. // About/index.jsx
  9. import React from 'react'
  10. export default function About() {
  11. return <div>
  12. About
  13. </div>
  14. }

image.png
再来新建 src/router/index.js 配置路由数组,添加如下内容:

  1. // router/index.js
  2. import Index from '../container/Index'
  3. import About from '../container/About'
  4. const routes = [
  5. {
  6. path: "/",
  7. component: Index
  8. },
  9. {
  10. path: "/about",
  11. component: About
  12. }
  13. ];
  14. export default routes

App.jsx 引入路由配置,实现切换浏览器路径,显示相应的组件:

  1. // App.jsx
  2. import React, { useState } from 'react'
  3. import {
  4. BrowserRouter as Router,
  5. Switch,
  6. Route
  7. } from "react-router-dom"
  8. import routes from '../src/router'
  9. function App() {
  10. return <Router>
  11. <Switch>
  12. {
  13. routes.map(route => <Route exact key={route.path} path={route.path}>
  14. <route.component />
  15. </Route>)
  16. }
  17. </Switch>
  18. </Router>
  19. }
  20. export default App

启动项目 npm run dev,如下图所示:
Vite 2.0   React   Ant Design 4.0 搭建开发环境 - 图4

引入 Ant Design UI 组件库

Ant Design 的官网没有给出 Vite 的配置方法,这边是我自己摸索的。首先我们下载安装包:

  1. npm i antd @ant-design/icons -S

目前最新版本 icon 包是分开的,所以这边顺带就把 @ant-design/icons 也安装了。

安装成功之后,我们先通过全局引入的方式,测试是否能成功跑通。打开 main.jsx 添加样式:

  1. ...
  2. import 'antd/dist/antd.css'
  3. ...

再回到 Index/index.jsx 修改如下:

  1. import React from 'react'
  2. import { Button } from 'antd'
  3. export default function Index() {
  4. return <div>
  5. <Button type='primary'>Index</Button>
  6. </div>
  7. }

重新启动项目,浏览器如下所示,代表引入 Ant Design 成功:
image.png
此时我们可以尝试着做一些优化,我们先看看,就目前现在这个情况,打完包之后,静态资源有多大。运行指令 npm run build ,如下所示:
image.png
腚眼一看,全局引入样式的形式,直接打完包, css 静态资源就 587.96k 了,我们尝试 按需加载 样式。

首先我们安装一个插件:

  1. npm i vite-plugin-imp -D

然后在 vite.config.js 配置文件内添加如下内容:

  1. import { defineConfig } from 'vite'
  2. import reactRefresh from '@vitejs/plugin-react-refresh'
  3. import vitePluginImp from 'vite-plugin-imp'
  4. // https://vitejs.dev/config/
  5. export default defineConfig({
  6. plugins: [
  7. reactRefresh(),
  8. vitePluginImp({
  9. libList: [
  10. {
  11. libName: "antd",
  12. style: (name) => `antd/lib/${name}/style/index.less`,
  13. },
  14. ],
  15. })
  16. ],
  17. css: {
  18. preprocessorOptions: {
  19. less: {
  20. // 支持内联 JavaScript
  21. javascriptEnabled: true,
  22. }
  23. }
  24. },
  25. })

再安装 less 插件包, npm i less -D,因为上述配置我们使用的是 less,并且我们需要配置 javascriptEnabledtrue,支持 less 内联 JS

这里我们将 main.jsximport 'antd/dist/antd.css' 去掉,再次启动 npm run dev,你会发现样式被按需引入了。我们看看插件 vite-plugin-imp 做了什么工作:
image.png
嚯喔~,这边在 index.jsx 内单独引入了按钮的样式组件。我们再看看打包后的静态资源大小:
image.png
css 样式包直接变成 40.29kb,好香啊~~
Vite 2.0   React   Ant Design 4.0 搭建开发环境 - 图9

有些同学可能会担心,在不同的页面都引入了 Button 组件,那么样式会不会重复引入。答案是不会的,打包构建的时候,会合并同类项,所以最后只会引入一次 Button 的样式文件。

自定义 Ant Design 主题色

开发时,会按照项目的需要,设计师的设计(瞎画),来定制一套主题样式,包括边距、文字大小、borderColor等等规则。可能以前用 webpack 那套的同学知道怎么玩,但是现在用 Vite,我们需要做如下操作。

首先打开 vite.config.js,添加如下代码:

  1. ...
  2. import path from 'path'
  3. import fs from 'fs'
  4. import lessToJS from 'less-vars-to-js'
  5. const themeVariables = lessToJS(
  6. fs.readFileSync(path.resolve(__dirname, './config/variables.less'), 'utf8')
  7. )
  8. ...
  9. css: {
  10. preprocessorOptions: {
  11. less: {
  12. // 支持内联 JavaScript
  13. javascriptEnabled: true,
  14. // 重写 less 变量,定制样式
  15. modifyVars: themeVariables
  16. }
  17. }
  18. }
  19. ...

less-vars-to-js 是将 less 样式转化为 json 键值对的形式,当然你也可以直接在 modifyVars 属性后写 json 键值对。

然后在根目录新建 config 目录,添加 variables.less 内容如下:

  1. // 自定义覆盖 =============================================================
  2. @primary-color: green; // 全局主色
  3. // 下面你可以各种写一些覆盖的样式,这里就简单覆盖一个主题色的样式,我们改为绿色

重新运行下面如下所示:
image.png
这样主题色就改造好了。

环境变量如何获取

我搜了很多资料,但是以目前 Vite 的生态,还是没能找到我需要的答案,我把最后的希望寄托在 Vite 的仓库 issue,还真搜出了一些东西。这里插一句题外话,有什么问题,先自己解决,去相应的仓库里瞅瞅,有没有已经解决掉的类似问题。不要动不动就去群里问大佬,大佬不忙啊,免费给你解决问题?

好,我们圆规正转。咱们平时开发项目的时候,基本上有三个环境,开发环境、测试环境、正式环境,这三个环境需要配置三种不同的资源,如图片、接口地址、埋点、百度统计等等。

打包时
那么我们如何在打包时,在 vite.config.js 中拿到环境变量呢?
首先我们先修改 package.jsonscripts 属性,如下所示:

  1. scripts: {
  2. "dev": "vite --mode development",
  3. "build:beta": "vite build --mode beta",
  4. "build:release": "vite build --mode release",
  5. "serve": "vite preview"
  6. }

--mode 后代表的是各个环境对应的环境变量值,这里为什么一定要用 --mode 呢?官方定的,后续可以在页面中拿到这个变量值。

我们在 vite.config.js 打印如下所示:

  1. console.log('process:::env', process.argv)

重新运行 npm run dev 如下所示:
image.png
最后一个参数,便是我们设置好的环境变量。所以我们可以通过如下获取环境变量:

  1. const env = process.argv[process.argv.length - 1]

我们可以在 vite.config.js 里配置 index.html 内,静态资源的路径前缀。改动如下:

  1. ...
  2. const env = process.argv[process.argv.length - 1]
  3. const base = config[env]
  4. ...
  5. export default defineConfig({
  6. base: base.cdn
  7. })

在根目录的 config 目录内,添加 index.js 文件,添加如下内容:

  1. export default {
  2. development: {
  3. cdn: './',
  4. apiBaseUrl: '/api' // 开发环境接口请求,后用于 proxy 代理配置
  5. },
  6. beta: {
  7. cdn: '//s.xxx.com/vite-react-app/beta', // 测试环境 cdn 路径
  8. apiBaseUrl: '//www.beta.xxx.com/v1' // 测试环境接口地址
  9. },
  10. release: {
  11. cdn: '//s.xxx.com/vite-react-app/release', // 正式环境 cdn 路径
  12. apiBaseUrl: '//www.xxx.com/v1' // 正式环境接口地址
  13. }
  14. }

我们来打个测试包试试,运行如下指令:

  1. npm run build:beta

结果如下所示:
image.png
同理可得正式环境的鸟样。

运行时
那么运行代码的时候,我们如何获取到相应的环境变量呢?答案是 import.meta.env 。我们在 Index/index.jsx 里打印一下便可知晓:

  1. import React from 'react'
  2. import { Button } from 'antd'
  3. export default function Index() {
  4. console.log('import.meta.env', import.meta.env)
  5. return <div>
  6. <Button type='primary'>Index</Button>
  7. </div>
  8. }

image.png
返回了一个对象,对象内分别是相应的参数,我们这里我们需要的是 MODE 属性对应的参数,便是我们要的当前环境变量。

二次封装 axios

开发项目时,服务端会为我们提供测试接口和正式接口,这里我们需要配置相应的变量来动态的获取请求地址。
首先我们先安装 axiosqs

  1. npm i axios qs -S

然后在 src 目录下新建 utils 目录,专门用于存放各种工具方法。在 utils 下新建 index.js,添加如下代码:

  1. import axios from 'axios'
  2. import { message } from 'antd'
  3. import { stringify } from 'qs'
  4. import config from '../../config'
  5. const MODE = import.meta.env.MODE // 环境变量
  6. const getRequest = (method) => {
  7. return (url, data, options = {}) => {
  8. let base = config[MODE] // 获取环境变量相对应的属性值
  9. return axios({
  10. baseURL: base.apiBaseUrl, // 请求域名地址
  11. method,
  12. url,
  13. ...(method === 'POST'
  14. ? {
  15. data: options.string ? stringify(data) : data,
  16. }
  17. : {}),
  18. params: method === 'GET' ? data : options.params,
  19. headers: {
  20. 'X-Requested-With': 'XMLHttpRequest',
  21. 'Content-Type': options.string
  22. ? 'application/x-www-form-urlencoded'
  23. : 'application/json',
  24. ...options.headers,
  25. },
  26. withCredentials: true,
  27. })
  28. .then((res) => {
  29. if (typeof res.data !== 'object') {
  30. console.error('数据格式响应错误:', res.data)
  31. message.error('前方拥挤,请刷新再试')
  32. return Promise.reject(res)
  33. }
  34. if (res.data.errcode) {
  35. if (res.data.errcode == 401) {
  36. window.location.href = 'login' // 登录失效跳转登录页
  37. return
  38. }
  39. // silent 选项,错误不提示
  40. if (res.data.message && !options.silent)
  41. message.error(res.data.message)
  42. return Promise.reject(res.data)
  43. }
  44. return res.data
  45. })
  46. .catch((err) => {
  47. message.error('系统错误', 2)
  48. return Promise.reject(err)
  49. })
  50. }
  51. }
  52. export const get = getRequest('GET')
  53. export const post = getRequest('POST')

这里通过 config[MODE] 获取开发、测试、正式相对应的属性值,从而拿到 apiBaseUrl 变量值。

顺带我们把开发环境的请求代理也添加一下,我们打开 vite.config.js ,添加如下属性:

  1. ...
  2. export default defineConfig({
  3. ...
  4. server: {
  5. port: 3001, // 开发环境启动的端口
  6. proxy: {
  7. '/api': {
  8. // 当遇到 /api 路径时,将其转换成 target 的值,这里我们为了测试,写了新蜂商城的请求地址
  9. target: 'http://47.99.134.126:28019/api/v1',
  10. changeOrigin: true,
  11. rewrite: path => path.replace(/^\/api/, '') // 将 /api 重写为空
  12. }
  13. }
  14. }
  15. })

测试接口是否请求成功,我们在 Index/index.jsx 内添加如下代码:

  1. import React, { useEffect } from 'react'
  2. import { Button } from 'antd'
  3. import { get } from '../../utils'
  4. export default function Index() {
  5. useEffect(() => {
  6. get('/index-infos').then(() => {
  7. })
  8. }, [])
  9. return <div>
  10. <Button type='primary'>Index</Button>
  11. </div>
  12. }

重新启动项目,结果如下图所示:
image.png
Vite 2.0   React   Ant Design 4.0 搭建开发环境 - 图15

resolve.alias 别名设置

和大多数的配置项类似,别名的配置也在 vite.config.js 中,我们打开它,添加如下代码:

  1. export default defineConfig({
  2. ...
  3. resolve: {
  4. alias: {
  5. '~': path.resolve(__dirname, './'), // 根路径
  6. '@': path.resolve(__dirname, 'src') // src 路径
  7. }
  8. }
  9. ...
  10. })

配置完后,我们重写上述代码中的一些路径如下:

  1. // router/index.js
  2. import Index from '@/container/Index'
  3. import About from '@/container/About'
  4. // utils/index.js
  5. import config from '~/config'
  6. // App.jsx
  7. import routes from '@/router'

方便又简介,后续还能继续增加一些路径,少些几个字,提高开发效率。

总结

这篇文章到此就告一段落了。什么?你还要 TSCSS ModuleEslint,别闹了,自己去仓库下载代码,慢慢玩耍吧,我都写吐了,求赞啊兄弟萌~~~。破 500 赞,我再码一篇 Vite + Vue + element-plus 的。溜溜球~~~