Skip to content

Latest commit

 

History

History
1853 lines (1002 loc) · 39.7 KB

Vite学习笔记.md

File metadata and controls

1853 lines (1002 loc) · 39.7 KB

Vite学习笔记


本文是在 vite 官方文档教程:https://cn.vitejs.dev/ 基础上,学习整理而来。


接下来我将通过对比 create-react-app 或 webpack 的形式来学习 vite。

本文目录:

  • vite与webpack 的目标不同之处

  • 创建初始化 react 或 vue 项目

  • 使用TypeScript

  • 关于CSS、sass样式

  • px 转 viewport

  • 引入静态文件资源

  • 命令参数

  • 使用插件

  • 构建生产版本

  • 项目常见配置

    • 配置调试IP和端口
    • 使用husky
    • 配置vscode
    • 使用prettier
    • 使用sass
    • 配置路径映射alias
    • 依赖优化选项中添加esbuild配置选项
  • 使用过程中的一些常见问题

    • 清除 node_modules/.vite 缓存
    • 执行 node.js 文件所需要的改动

vite与webpack 的目标不同之处

vite 的目标就是构建适用于现代浏览器,根本不考虑旧版浏览器,例如 IE 11 等。

并且 vite 支持编译目标 JS 的版本最低为 ES2015。

所以如果你的项目需要适配旧的浏览器,那么建议你别使用 vite,还继续使用 webpack 吧。

当然你也可以选择安装使用 @vitejs/plugin-legacy 这个插件,用来适配到旧版浏览器。


创建初始化 react 或 vue 项目


创建一个 React 项目:

//创建 React 项目
- yarn create react-app xxx
+ yarn create vite xxx --template react

//创建 React + TypeScript 项目
- yarn create react-app xxx --template typescript
+ yarn create vite xxx --template react-ts

创建一个 Vue 项目:

//创建 Vue 项目
yarn create vite xxx vue

//创建 Vue + TypeScript 项目
yarn create vite xxx --template vue-ts

针对 React + TypeScript 的注意事项:

由于最新版 vite react-ts 模板中使用的 TypeScript 版本为 5+,因此需要比较新的 VSCode 才可以支持。

准确来说需要的是 VSCode 1.77 以上的版本才可以支持到 TS 5+,如果你的 VSCode 版本低于此版本,那么由于对 TS 5+ 的不支持,你会收到一些莫名其妙的错误警告,例如:

Module '"xxxx/node_modules/@types/react/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

如果你真的不方便升级 VSCode (不建议),那么你需要修改 tsconfig.json

- "moduleResolution": "bundler",
+ "moduleResolution": "node",
- "allowImportingTsExtensions": true,

安装其他框架:

vite 除了 react 或 vue 外还支持其他众多框架,可以执行:

yarn create vite xxx

然后在候选框架中选择你要使用的框架。


补充说明:

对于 create-react-app 来说,当创建项目时会自动创建安装 node_modules 包。

对于 vite 来说,默认是不会创建安装 node_modules 包的,需要你自己手工安装。

yarn

初始化项目的文件区别:

对于 create-react-app 来说,其网页模板位于 /public/index.html。

对于 vite 来说,其网页模板位于 /index.html

vite 把当前项目目录作为 "静态文件服务根目录",甚至可以配置多个不同的目录作为默认页


关于public目录:

public 目录用于存放一些站点静态文件,例如:favicon.ico 、robots.txt 等

/index.html 中可以直接使用这些静态文件:

<link rel="icon" type="image/x-icon" href="/favicon.ico" />

是否创建git:

对于 vite 创建的项目来说,默认是不包含 git 的。


使用TypeScript


使用 TS 的一些注意事项:

  • vite 天然支持 .ts 文件

  • vite 只负责编译 .ts 文件,但不负责校验 TS 类型,TS 校验还是有 编辑器(VSCode) 和 eslint 完成

  • 若只引入类型,推荐添加 type 字段,以明确仅引入类型

    - import xx from 'xx'
    + import type xx from 'xx'

TS 配置选项:

和 TS 相关的一共有 4 个配置文件:

  • tsconfig.json
  • tsconfig.node.json
  • vite.config.ts
  • src/vite-env.ts

他们的继承关系是:

  • tsconfig.json 中引入了 tsconfig.node.json

  • tsconfig.node.json 中引入了 vite.config.ts

    vite.config.ts 相当于 webpack 中的 webpack.config.js 配置项

  • 而 src/vite-env.ts 为独立文件,用于定义某些 "客户端文件类型",其内容默认值为:/// <reference types="vite/client" />


tsconfig.json 中 几个非常重要的配置项:

  • isolatedModules:默认值为 true

    isolated 单词翻译为 "隔离、孤立"

  • skipLibCheck:默认值为 true

  • useDefineForClassFields:默认值为 true


关于增加非 src/ 目录下的文件 lint 检查:

首先我们看一下默认 Vite 中都检查哪些文件或目录:

  • tsconfig.json 文件中的 "include": ["src"]

  • tsconfig.node.json 文件中的 "include": ["vite.config.ts"]

    vite.config.ts 文件位于项目根目录,并不在 src/ 目录下

也就是说默认 Vite 配置 lint 检查的文件或目录分别是:src/vite.config.ts

假设我们出于某种目的,在项目根目录创建了一个名为 xxx.js 的文件,当我们执行 yarn lint 时可能会收到这样的错误:

Parsing error: ESLint was configured to run on `<tsconfigRootDir>/xxx.js` using `parserOptions.project`: ...

这是 ESLint 在警告我们:没有正确配置 xxx.js 文件!


你可能会想那我直接将 xxx.js 添加到 .eslintignore 中不就行了?

答案是:不行!你会收到这样的错误:

File ignored because of a matching ignore pattern. Use "--no-ignore" to override

原因很简单:因为 .eslintignore 是针对 "检查范围内" 的文件,可此时 xxx.js 根本不在检查范围内,所以也谈不上忽略它!


正确的解决办法是:将 xxx.js 添加到检查范围内即可

tsconfig.node.json

"include": ["vite.config.ts", "xxx.js"]

提醒:既然 xxx.js 已添加到检查范围内了,若此时再在 .eslintignore 中添加忽略 xxx.js 才会生效,当然你没必要这样做,还是检查一下比较好。


特殊的三斜杠:

src/vite-env.ts 中的 /// <reference types="vite/client" /> 等同于 在 tsconfig.json 中:

{
  "compilerOptions": {
    "types": ["vite/client"]
  }
}

"vite/client"、"客户端类型" 可以暂时理解为 "通用的静态资源文件",例如 .jpg、.svg 格式的文件

reference 单词意思为:参考


单独定义某种文件类型:

假设想单独针对 .svg 文件进行某种类型定义,则:

创建 src/vite-env-override.d.ts 文件

declare module '*.svg' {
   const content: React.FC<React.SVGProps<SVGElement>>
   export default content
}

会把 .svg 文件视作是 React 的某种类型,然后再向 src/vite-env.ts 中添加刚才定义的:

+ /// <reference types="./vite-env-override.d.ts">
/// <reference types="vite/client">

注意要把自定义的 vite-env-override.d.ts 写在 "vite/client" 前面


关于CSS、sass样式

组建中引入某样式文件的方式和 create-react-app 是相同的。

import './xx.css'

Vite内置支持sass:

无需像 webgpack 那样需要安装 sass-loader,可以直接在 vite 项目中使用 sass。

唯一需要做的就是需要安装 sass:

yarn add sass --dev

除 sass 外还内置支持 less、stylus。

yarn add less --dev
yarn add stylus --dev

也就是说 vite 天然支持 .sass、.scss、.less、.styl、.stylus 样式文件。


以包的形式引入样式:

- import './xx.css'
+ import xx from './xx.css'

//然后可以有针对性的使用 xx 中的某些样式名称 xx.aa
mydiv.className = xx.aa

仅引入包名称,但不引入样式实质内容:

我们上面说的 "引入样式" 准确里说是 "注入样式",vite 支持在样式文件后面增加 ?inline 来表明仅引入包名称,不实质引入(注入)样式内容:

import xx from './xx.css?inline'

px 转 viewport

需要将 css 或 scss 中的 px 单位 自动转成 viewport 单位,可以使用:postcss-px-to-viewport 这个插件


第1步:安装该插件

pnpm add -D postcss-px-to-viewport

第2步:修改postcss配置项

vite.config.ts

export default defineConfig({
    ...
    css: {
        postcss: {
            plugins: [
                postcsspxtoviewport({
                    viewportWidth: 375, //假定设计稿宽度为 375px
                    ... //还有其他配置,不设置则使用默认值
                })
            ]
        }
    },
})

具体都有哪些配置值,可查阅:

https://github.com/evrone/postcss-px-to-viewport/blob/master/README_CN.md#%E9%85%8D%E7%BD%AE%E5%8F%82%E6%95%B0


引入静态文件资源


公共静态资源目录:

默认为项目根目录中的 public 目录。

  • 对于 public 目录中的资源引用时应使用 绝对根目录 '/'
  • 你可以在 css 中使用 public 目录中的某些资源文件
  • 但请不要在 js 中引入 public 中的资源

引入某个静态资源:

若为图片,可获得该图片被编译后的路径地址:

import imgUrl from './img.png'

myImage.src = imgUrl

若为 .json 可自动解析转换成对象

import json from './xx.json'

//或直接使用该 json 某根节点
import { field } from './xx.json'

动态获取引入的资源路径:

可以通过 new URL() + import.meta.url 形式获取:

const filePath = './xx/aa.jpg'

const fileUrl = new URL(filePath, import.meta.url).href

动态导入:

const module = await import(`./dir/${file}.js`)

文件后缀可增加的参数:

像上面提到的可以在 .css 文件后面增加 ?inline 参数来表明 "引入css文件" 的某些特殊处理。

vite 还支持其他几种后缀参数,用于表明引入不同静态文件资源的特殊处理含义。


?inline:针对 css 文件

表明仅引入样式名称模块,并不会真正引入(注入)样式内容


?url:用于显式获取文件边以后地址

对于一般的静态资源文件,引入后本身就可以获取其被编译后的路径地址,但是对于一些未被包含在内部列表中的文件资源,可以通过增加 ?url 显式明确获取编译后的路径地址。

import xxUrl from 'xxx/xx.js?url'

?raw:以原始纯文本(字符串) 形式引入

例如引入 WebGPU 着色器代码(纯文本)

import xx from ./xx.wgsl?raw

引入 WebGL 着色器代码

import xx from './xx.glsl?raw'

?worker:以 web worker 形式引入

我们知道 web worker 文件需要是独立的文件,如果在 webpack 中需要使用 worker-loader 加载器才能正确编译并找到编译后的 .js 文件。

vite 天然支持,无需 worker-loader。

import MyWorker from './xx.js?worker'

const myWorker = new MyWorker()

?sharedworker:同源共享类型的 web worker

sharedWorker 是一种特殊的 web worker,使用 ?sharedworker 可以引入

import MySharedWorker from './xx.js?sharedworker'

参数组合:?worker&inline

以内联为 base64 字符串形式引入 web worker

import InlineWorker from './xx.js?worker&inline'

目前我还没用过这种方式,具体应用场景暂时不清楚


?init:针对 .wasm 文件的导入和初始化

import init from './xx.wasm?init'

init().then((instance) =>{ instance.exports.test() })

特别说明:web worker 的另外一种推荐导入方式

除了 ?worker?sharedworker 这种形式导入 worker 外,更加推荐使用 new Worker() 和 new SharedWorker() 方式来导入。

这种方式和原生的创建 web worker 方式极为相似,只不过是用 new URL() + import.meta.url 形式。

//在JS原生中的写法
const myWorker = new Worker('./xx.js')

//在vite中之前的写法
import MyWorker from './xx.js?worker'
const myWorker = new MyWorker()

//在vite中新的推荐写法
const myWorker = new Worker(new URL('./xx.js', import.meta.url))

还可以增加第2个配置参数:

const myWorker = new Worker(new URL('./xx.js', import.meta.url), { type:'module' })

命令参数


Vite 命令参数划分:

我们使用 vite 大体上可以划分为 3 种目的方向:

  • 开发过程
  • 构建
  • 其他(预构建依赖、本地预览构建产物)

为了更加方便理解,我们现明确一下命令参数含义:

  • --xxx:命令参数名
  • -x:命令参数的简写形式
  • [xx]:可选值,若不填则使用默认值
  • <xx>:必填值

参数名与参数值支持以下 2 种方式:

  • 使用 等号 相连:--xxx=xx
  • 使用 空格 相连:--xxx xx

开发过程中的配置参数:

vite [参数]
  • --host [host]:指定主机名称,默认仅为 'http://localhost' (不含局域网IP),若设置为 true 或 '0.0.0.0' 表示本机全部网络 IP (含公网IP)

  • --port :指点启用端口

  • --strictPort:明确若端口已被占用则直接退出,并不会尝试下一个可用端口

  • --open [path]:启动时自动打开浏览器,[path] 为指定打开的路径

  • --base :公共基础路径,默认值为 '/'

  • --https:请注意该配置参数已经在 v5 版本中废弃,请勿再使用

  • --cors:启用 CORS

  • --force:忽略 node_modules/.vite 中的缓存,强制不使用缓存情况下重新构建

  • -c、--config :使用指定的配置文件

  • -m、--mode :设置环境模式

  • -v、--version:显式版本号

  • -h、--help:显式可用的 CLI 选项

  • -d、--debug [feat]:现实调试日志

  • -f、--filter :过滤某些调试日志

  • -l、--logLevel :显示哪种日志级别,info/warn/error/silent,默认值为 'info'

  • --clearScreen:允许或禁止清除日志屏幕


特别提醒:修改上述配置文件后,无需重新执行 yarn dev,调试网页就立马生效,vite 非常强!


构建相关参数命令:

vite build [参数]
  • --target :编译目标,默认值为 "modules"

  • --outDir

    :输出目录,默认值为 "dist"

  • --base :公共基础路径,默认值为 '/'

  • --emptyOutDir:若输出目录在根目录外,则强行清空输出目录

    对于根目录内的输出目录,即使不设置该参数,也会每一次强行清空该目录

  • --assetsDir

    :输出目录中的资源目录,默认值为 "assets"

  • --sourcemap [output]:是否构建输出 source map 文件,默认值为 false

  • --minify [minifier]:允许或金庸最小化混淆,或指定使用哪种混淆器,默认为 "esbuild"

    可修改混淆器为 "terser",若设置为 false 则表示不使用混淆

  • --manifest [name]:是否构建后生成 manifest.json 文件

    [name] 可设置为 true 或 false,若想自定文件名则直接设定 name 的值

  • --ssrMainfest [name]:是否构后生成 SSR manifest.json 文件

    配置方式同 --manifest

  • --ssr [entry]:为服务端渲染配置指定入口文件

  • --assetsInlineLimit :静态资源内联为 base64 编码的阈值,以字节为单位,默认值 4096

  • -w、--watch:监控磁盘是否发生变更,若发生变更则重新(重头)构建

  • 其他参数(-c、--base、--clearScreen、-d、-f、-m、-h)和 开发过程中的相同


特别说明:

因为对于构建好的网页项目,若其将来并不在域名根目录下,那么就使用 --base 这个命令参数。

但是,更推荐另外一种做法:

去修改 vite.config.ts 的 base 字段,将其修改成其他值,例如相对路径 './' 或 具体路径 '/xx/'

import { defineConfig } from 'vite'

export default defineConfig({
  base:'./', //注意此处
  ...
})

其他(预构建依赖、本地预览构建产物)

vite preview [参数]

所谓 "预览构建产物" 你可以简单理解为 "实际构建中间的预览版"。

永远不要把 本地预览构建产物 当做构建产物来用!

可用适用的参数几乎和上面的差不多,具体可参考:https://cn.vitejs.dev/guide/cli.html


上面所有的命令参数实际上都可以通过修改配置 vite.config.ts 文件来实现,包括一些没有提及到的。

他们大致划分为:

此外还有上述命令参数中不存在的配置项:


具体用到哪些时直接看官方文档即可。


使用插件


vite插件与rollup插件的关系:

  • vite 最初是以 rollup 为基础(参考) 而来的,所以 rollup 的一些插件都可以直接应用在 vite 之上
  • vite 本身已经内置了很多 和 rollup 类似的插件
  • 但有些 rollup 插件会与 vite 内置插件冲突

所以,当我们说 "vite插件" 时实际上内含 2 种插件:

  1. 专门针对 vite 的插件
  2. 同样适用于 vite 的 rollup 的插件

虽然名字是 "插件",但其实也各类包含 "中间件"。

你也可以自定义插件或中间件,前提是需要你会一些 nodejs。

Vite 独有的钩子(hook):

https://www.vitejs.net/guide/api-plugin.html#vite-specific-hooks

你可以利用 vite 提供的钩子,编写自己的中间件。

例如可以针对资源请求针对 configureServer 钩子编写一些自己的逻辑。


例如我编写的这个:public404Middleware.ts

https://github.com/puxiao/notes/blob/master/fragment/public404Middleware.ts

用来检查 public 中图片资源若不存在则返回 404 而不是 vite 默认的 index.html 内容。

这个主要是用来避免开发阶段中,因为手抖而把图片资源写错却不容易被发现的问题。


请注意:vite 插件中的 中间件都只针对 dev 模式,而不是 build 模式。


从另外一个角度,以插件开发者身份的角度来看一共有 4 类:

  • vite 官方维护插件

    官方只维护针对不同框架的插件,例如 vue、react 等

  • vite 社区维护的插件

    涵盖了绝大多数日常项目开发所需的插件

  • 第三方个人开发的 vite 插件

    无法保证质量,慎用

  • rollup 插件

    要考虑有可能会与 vite 官方插件、社区插件有冲突风险


寻找插件:

  1. 首先:强烈推荐使用 vite 官方社区维护的插件:https://github.com/vitejs/awesome-vite#plugins
  2. 其次:NPM 平台 https://www.npmjs.com/ 中,搜索:vite-plugin 来搜索相关插件
  3. 备选:https://vite-rollup-plugins.patak.dev/

vite 官方社区维护的插件已经几乎涵盖日常开发中各个方面了,品质和兼容性有保障。


添加一个插件:

第1步:安装某插件

yarn add @vitejs/plugin-xx --dev

第2步:在 vite.config.ts 配置文件中的 plugins 数组中添加 xx 和 它的配置项


像我们前面创建的 react 项目,默认就是用的是 @vitejs/plugin-react 这个插件。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()], //若安装新插件,需要追加到此数组中
})

vite 内置的插件并未暴露在 plugins 数组中。


插件执行顺序:

默认情况下我们安装的插件都会在 vite 核心插件执行之后才调用。

若想修改我们安装的插件与 vite 核心插件 或 构建插件 的执行顺序,可通过给插件添加 enforce 字段来明确执行契机。

  • 默认值(不配置):在 vite 核心插件之后调用该插件

  • enforce: 'pre':在 vite 核心插件之前调用该插件

    注意此处说的是:vite 核心插件

  • enforce: 'post':在 vite 构建插件之后调用该插件

    注意此处说的是:vite 构建插件


按需使用插件:

除了上面提到的修改 插件 执行先后顺序外,我们还可以配置某插件仅在某模式下使用。

这里说的 某模式 是指:开发模式 和 生产模式

默认情况下插件会在上面 2 个模式中都调用,我们可通过 apply 字段来控制仅在某固定模式下才被调用。

  • apply: 'build':仅在构建模式下调用
  • apply: 'serve':仅在开发模式下调用

开发自己的插件:

首先需要阅读 rollup 插件文档:https://rollupjs.org/plugin-development/

然后再熟悉 vite 插件 API 和 约定:https://cn.vitejs.dev/guide/api-plugin.html


构建生产版本


修改公共目录:

默认使用的是 '/' 作为根目录,如何修改在前面讲 --base 命令参数时已经说过了,此处再复习一遍。

一共有 2 中修改方式:

  • 第1种:添加构建命令参数:

    vite build --base=./
    
  • 第2种:修改 vite.config.ts 配置项

    import { defineConfig } from 'vite'
    
    export default defineConfig({
      base:'./', //注意此处
      ...
    })
    

特别说明:base 与 root 的区别

  • base 是指编译后的文件的资源公共目录
  • root 是指我们存放的项目源码的基础公共目录

更为复杂的基础路径配置:

vite 还支持将不同文件存放在不同的路径中,这样做的目的是为了在部署时可以有更大的自由度,例如有些目录需要启用 CDN 加速,而有些不需要。

具体配置方式:https://cn.vitejs.dev/guide/build.html#advanced-base-options


构建多页面:

vite 支持多页面应用模式,也就是说不再是单页面,可以是多目录、多页面。

那么意味着:

  1. 你需要指定 N 个页面目录路径
  2. 指定每个目录页面的入口文件

构建多页面大体上可以分为 2 种实现方式:

  • 手工创建N个编译入口和模板文件

    这适用于页面数量不多的项目

  • 使用 vite 社区插件 vite-plugin-multi-pages

    这适用于页面数量非常多的项目


vite构建多页面 - 手工实现方式:

下面以 vite + vue 项目为例。

第1步:在 src 目录下创建 pages 目录,用于存放多个页面

这下和 nextjs 就很像了

  • 首页:src/pages/index/
    • App.vue
    • main.js
    • style.css
  • 子页面AA:src/pages/aa/
    • App.vue
    • main.js
    • style.css
  • 子页面BB:src/pages/bb/
    • ...

第2步:在项目根目录(root) ,也就是之前 index.html 页面同级目录 创建和修改子页面 .html 内容

我们将默认的 index.html 复制出来 2 份,并分别修改为 aa.html、bb.html

  • 首页:index.html

    我们需要修改 index.html 中对 JS 入口文件的引入地址

    - <script type="module" src="/src/main.ts"></script>
    + <script type="module" src="/src/pages/index/main.js"></script>

    同理,我们需要对其他页面分别进行设置

  • 子页面AA:aa.html

    <script type="module" src="/src/pages/aa/main.js"></script>
    
  • 子页面BB:bb.html

    <script type="module" src="/src/pages/bb/main.js"></script>
    

第3步:修改 vite.config.js 中 build.rollupOptions.input 的配置

import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'node:path'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [vue()],
    base: './',
    build: {
        rollupOptions: {
            input: {
                index: path.resolve(__dirname, 'index.html'),
                aa: path.resolve(__dirname, 'aa.html'),
                bb: path.resolve(__dirname, 'bb.html')
            }
        }
    },
    resolve: {
        alias: {
            '@/src': fileURLToPath(new URL('./src', import.meta.url)),
            '@/index': fileURLToPath(new URL('./src/pages/index', import.meta.url)),
            '@/aa': fileURLToPath(new URL('./src/pages/aa', import.meta.url)),
            '@/bb': fileURLToPath(new URL('./src/pages/bb', import.meta.url))
        }
    }
})

为了方便引入代码,我们还添加配套的 alias


这样基础源码结构就配置好了。

  • 如果是所有页面的公共组件,那么我们可以继续存放在 src/components/
  • 如果是某子页面单独使用的组件,那么可以存放在 src/pages/xx/components

最后,当我们执行编译:yarn build,就会在 dist 中分别看到构建好的 index.html、aa.html、bb.html。

默认这些页面引用的 js 会被分别存放在 assets 目录中,并且以他们的名字来作为 JS 文件前缀。

  • index_xxxxxx.js
  • aa_xxxxxxx.js
  • bb_xxxxxxx.js

vite 会针对每个需要构建的页面进行 摇树(tree shaking),即仅打包进去当前页面所需最小代码


关于 build.rollupOptions.input 等多配置介绍,可查阅:https://cn.rollupjs.org/configuration-options/#input


vite构建多页面 - 插件实现方式:

该插件的具体用法,可查阅插件官方文档:

https://github.com/Miofly/vite-plugin-multi-pages


项目常见配置


配置调试IP和端口

默认情况下当启动调试后,仅 'http://localhost' 可访问,局域网 IP 是无法访问的。


方法1:通过配置文件方式:

想修改启动 IP 和 端口,可如下配置:

vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
    base: './',
    server: {
        host: '0.0.0.0',
        port: 3000,
        strictPort: true,
        open: true
    },
    plugins: [react()],
})

上述配置中 host: '0.0.0.0' 等同于 host: true

上述其他建议配置:

  • 把 base 设置为 './'
  • strictPort(端口被占用则退出)
  • open(启动后自动打开浏览器调试页面) 也都设置为 true

方法2:通过命令方式来配置

package.json 中的 "scripts"

参数名与参数值中间使用 等号 连接

"scripts": {
    "dev": "vite --host=0.0.0.0 --port=3002",
}

参数名和参数值之间也可以使用 空格 连接:

"scripts": {
    "dev": "vite --host 0.0.0.0 --port 3002",
}

特别说明:

  • 若修改 vite.config.ts 则无需重新执行 yarn dev,自动立即生效
  • 若修改 package.json 则需要重新执行 yarn dev 后才会生效
  • 若 vite.config.ts 和 package.json 命令中同时配置了不同的 IP 和端口,命令方式的优先级更高

启用https

以下仅适用开发阶段的本地调试中启用 https。

第1种方式(不推荐):使用第三方插件生成 https 证书

  • 安装 @vitejs/plugin-basic-ssl,它会自动为我们生成调试阶段的 https 证书

  • 修改 vite.config.ts

    import { defineConfig } from 'vite'
    import react from '@vitejs/plugin-react'
    + import basicSsl from '@vitejs/plugin-basic-ssl'
    
    // https://vitejs.dev/config/
    export default defineConfig({
    -  plugins: [react()],
    +  plugins: [react(), basicSsl()],
    +  server: {
    +        host: true,
    +        port: 443,
    +    },
    })

    注意:并不是强制要求端口必须是 443,也可以是其他

这样就可以在 react + vite 项目调试中启用 https 了。

若等到正式发布,再配置正规的 https 证书。


第2种方式(推荐):使用自有的 https 证书

上面讲的第1种方式默认会被谷歌浏览器判定为 不安全 的证书并且阻止页面显示,我们推荐使用自有 https 证书 ,具体如下。

先使用mkcert生成https证书

第1歩:安装 mkcert

具体安装方法请查看:https://github.com/FiloSottile/mkcert?tab=readme-ov-file#installation

这里仅说一下 windows 系统安装步骤:

先安装 scoop:

使用 Powershell,并且需要有 梯子,依次执行下面命令

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression

再安装 mkcert:

scoop bucket add extras
scoop install mkcert

第2歩:初始化证书机构

mkcert -install

第3歩:生成 localhost 证书

mkcert localhost

会生成:localhost.pem、rootCA-key.pem 这 2 个证书文件


修改 vite.config.ts 中加载 https 证书

修改 vite.config.ts :

假定我们把 mkcert 生成的 2 个证书文件放在了项目 /pems/ 目录中

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { readFileSync } from 'node:fs'
import path from 'node:path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
+  server: {
+    https: {
+      key: readFileSync(path.join(__dirname, 'pems/localhost-key.pem')),
+      cert: readFileSync(path.join(__dirname, 'pems/localhost.pem'))
+    }
  }
})

经过如此配置后,就可以在开发阶段使用 https 了。


关于https的端口说明:

在 nginx 中要求 https 端口必须是 443,但是在 vite 中并没有此要求。

因此我们可以将端口设置为任何我们想设定的:

export default defineConfig({
  plugins: [react()],
  server: {
    https: {
      key: readFileSync(path.join(__dirname, 'pems/localhost-key.pem')),
      cert: readFileSync(path.join(__dirname, 'pems/localhost.pem'))
    },
+   host: '0.0.0.0',
+   port: 3000,
  }
})

使用husky

husky 是专门用来做代码 git 提交前的事件触发,可以在这个契机中进行代码相关检查或格式化,通过检查后才可以进行 git 代码提交,否则将拦截本次提交。

具体用法可参考另外一篇文章:Husky学习笔记.md


配置vscode

在项目根目录创建:.vscode/setting.json

{
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    "editor.detectIndentation": false,
    "editor.tabSize": 4,
    "javascript.format.insertSpaceBeforeFunctionParenthesis": true
}

上面是最基础的配置项:

  • 修改默认以 4 个空格对齐代码
  • 保存文件时自动格式化代码

使用prettier

上面是通过 vscode 配置方式来实现代码格式化,但是假设编辑器不是 VSCode,或者我们希望有更加丰富的代码格式化,那么可以安装使用 prettier 以及它的相关插件。

  • prettier:代码格式化、美化
  • prettier-plugin-packagejson:针对 package.json 的格式化插件
  • prettier-plugin-sort-imports:针对顶部中 import 引入代码部分的格式化插件

安装:

yarn add --dev [email protected] prettier-plugin-packagejson prettier-plugin-sort-imports

由于目前 prettier 3.0.0 版本在 windows 系统上会报错,所以我们此处暂时安装 2.8.8 版


修改插件配置文件:

打开 .prettierrc 文件,修改其中的 "plugins" 属性值:

"plugins": [
    "./node_modules/prettier-plugin-sort-imports",
    "./node_modules/prettier-plugin-packagejson"
]

新增命令:

package.json

"scripts": {
    ...
    "format": "prettier --write --ignore-unknown .",
    "format-check": "prettier --check --ignore-unknown .",
},

git提交前格式化代码:

package.json

"lint-staged": {
    "*.{js,jsx,ts,tsx}": [
        "yarn lint",
        "prettier --write --ignore-unknown"
    ]
},

特别说明:配置 "lint-staged" 的前提是你已安装使用 husky


关于报错:ESLint was configured to run on <tsconfigRootDir>/vite.config.ts using parserOptions.project ...

这是目前已知的一个 bug,第1种解决方法是:

打开 .eslintrc.cjs 文件,将 parserOptions.project 的值由默认的 true 修改为 ['./tsconfig.json', './tsconfig.node.json'] 即可。


第2种解决方案是: tsconfig.node.json

- "include": ["vite.config.ts"]
+ "include": ["vite.config.ts", ".eslintrc.cjs"]

使用sass

vite 内置 sass 的加载器,只需安装 sass 即可直接使用。

yarn add sass --dev

配置路径映射alias

无需安装任何插件,只需要直接在 vite.config.ts 中配置即可。

假定我们现在一共要添加 2 条路径映射:'@'、'utils'

resolve.alias 的值一共有 2 种写法。


方式1:对象

属性名就是映射后的路径缩写、属性值是原始路径

import path from 'path'

export default defineConfig({
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src'),
            'utils':  path.resolve(__dirname, './src/utils')
        }
    },
    ...
})

方式2:数组

数组中的每个元素结构为 { find: 'xx', replacement: 'xxxxx'}

import path from 'path'

export default defineConfig({
    resolve: {
        alias: [
            {
                find: '@',
                replacement: path.resolve(__dirname, './src')
            },
            {
                find: 'utils',
                replacement: path.resolve(__dirname, './src/utils')
            }
        ]
    },
    ...
})

修改配置tsconfig.json

增加 alias 相关配置:

"compilerOptions": {
    ...
    /* alias */
    "baseUrl": "./",
    "paths": {
        "@/*": ["src/*"]
    },
}

特别说明:静态资源对应的类型定义

如果使用 create-react-app,我们还需要去定义 global.d.ts,但是在 vite 中,它已经默认帮我们定义好了。

对应的就是 vite-env.d.ts 中的三斜杠注释代码。

/// <reference types="vite/client" />

"vite/client" 泛指各类客户端静态资源文件,例如 .svg、.jpg 等


依赖优化选项中添加esbuild配置选项

具体用法可查看:

https://cn.vitejs.dev/config/dep-optimization-options.html#optimizedeps-esbuild-options


这里重点说一下日常中可能会遇到的一个报错。

假设你使用了某些第三方库,可能因为里面使用了 "某些新的 JS 语法" (例如 await ),开发调试时收到这样的报错:

Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)

请注意上面说的 某些新的 JS 语法是加了引号的,也就是说这些 新的 JS 语法实际上并不是特别新,就好像上面那个因为第三方库使用了 await 这个语法。

我是在使用 threejs 中的 WebGPURenderer 时收到上面的报错信息的。


目前的解决方案是:在 vite.config.js 中增加 esbuildOptions 配置

export default defineConfig({
    ...
    optimizeDeps: {
        esbuildOptions: {
            target: 'esnext'
        }
    }
})

总体来说 vite 相对于 webpack 配置起来极其简单。


使用过程中的一些常见问题


清除 node_modules/.vite 缓存

假定你的项目执行过调试,那么 vite 会把当前项目所用到的 node_modules 中的各个包文件缓存下来,以便提高热更新性能。

代价是 vite 不会监控 node_modules 中文件的变动,例如你手工修改了 node_modules 下的某个包的代码,当你再次执行调试时 vite 继续使用之前的缓存,你刚手工修改的代码是不会生效的。

解决办法非常简单:手工删除 node_modules/.vite 目录,然后重新执行调试,此时就能看到变更后的代码了。


假定你每一次都不想使用 node_modules 中的 NPM 包缓存,可以调用执行 vite --force


执行 node.js 文件所需要的改动


Vite 环境下无法直接执行 node.js 文件?

Vite 创建的 package.json 中是这样配置的:

"type": "module"

由于 node.js 默认采用的是 CommonJS 模块,而 Vite 默认的是 ESM 模块,所以在 Vite 项目中默认是无法执行 node.js 编写的相关代码的。


在 Vite 项目中想执行 node.js 文件需要改动的地方:

  • 首先为了有 node.js 语法提示,我们先推荐安装 node.js 的类型提示

    yarn add @types/node --dev
    

    上面代码默认安装的是最新版 node.js 的类型包,你可根据自己的 node.js 版本有选择性的安装对应版本

  • 修改 node.js 编写的文件中的引入方式

    - const xx = require('xx')
    + import xx from 'xx'
  • 额外增加一些 "原本 node.js 中默认可用的环境变量",例如最常用的 __dirname

    对于 node.js 编写的代码,假定想获取当前文件目录的路径,那么是可以直接使用 __dirname 来得到的。可是这个变量在 ESM 中是默认不存在的,需要我们自己计算出来。

    具体改动参见下面的代码


node.js 文件代码改造示例:

以下这种方式仅适用于:高于 node v18、低于 nodejs v20 版本。

- const path = require("path")
+ import path from 'path'

+ import { fileURLToPath } from 'url'
+ const __filename = fileURLToPath(import.meta.url)
+ const __dirname = path.dirname(__filename)

const jsonPath = path.join(__dirname, './public/version.json')
console.log(jsonPath)

特别说明:上面这种方式已不适用最新版的 nodejs,因为最新版的 nodejs 中又恢复了 dirname,我们无需再自己定义 dirname。