Vite 官方文档速通(上)

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: Vite 官方文档速通(上)

前言:参考 Vite 官网

一. 指引

1. 为什么选择 Vite

1.1 现实问题

问题:当项目中 JS 代码量变多,就会导致:1. 启动开发服务慢(几分钟)。2,模块热替换(HMR)慢(几秒钟)。极大影响开发效率和体验。

解决:1. Vite 将应用模块分为依赖和源码,加快了开发服务器启动时间。Vite 使用 esbuild 预构建依赖,esbuild 使用 go 编写,比 JS 编写的打包器预构建依赖块 10-100 倍。Vite 以原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。2. Vite 使已编辑的模块与其最近的 HMR 边界之间的链失活,始终保持快速更新。

1.2 为什么生产环境仍需打包

为了最佳的加载性能,最好将代码进行 tree-shaking、懒加载和 chunk 分割(以获得更好的缓存)。为什么不用 ESBuild 打包,因为 Vite 的插件 API 与 esbuild 打包器并不兼容。尽管 esbuild 速度更快,但 Vite 采用了 Rollup 打包。

2. 开始

2.1 总览

Vite 是一款前端构建工具,由两部分组成:1. 一个开发服务器。2. 一套构建指令。在线试用 vite

2.2 搭建 Vite 项目

兼容性注意:Vite 需要 Node.js 版本 18+,20+。

npm create vite@latest
# or
yarn create vite
# or
pnpm create vite

2.3 index.html 与项目根目录

在 Vite 项目中,index.html 在项目最外层。在开发期间 Vite 是一个服务器,而 index.html 是该 Vite 项目的入口文件。Vite 解析  指向 JavaScript 源码。index.html 中 URL 将被自动转换,不再需要 %PUBLIC_URL% 占位符了。

2.4 命令行界面

在通过脚手架创建的 Vite 项目中默认的 npm scripts:

{
  "scripts": {
    "dev": "vite", // 启动开发服务器,别名:`vite dev`,`vite serve`
    "build": "vite build", // 为生产环境构建产物
    "preview": "vite preview" // 本地预览生产构建产物
  }
}

3. 功能

Vite 通过原生 ESM 导入提供了许多主要用于打包场景的增强功能。

3.1 NPM 依赖解析和预构建

原生 ES 导入不支持下面这样的裸模块导入,Vite 将会检测到所有裸模块导入,并进行: 1. 预构建。2. 重写导入为合法的 URL

import { someMethod } from "my-dep";

3.2 TS

Vite 天然支持引入 .ts 文件。Vite 使用 esbuild 将 TS 转译为 JS,Vite 为了将类型定义用在客户端需要设置 d.ts 文件,或者添加到 tsconfig.ts 中的 compilerOptions.types 中。设置后会提供:资源导入、import.meta.env、import.meta.hot 的类型定义补充:

// d.ts
/// <reference types="vite/client" />
// tsconfig.ts
{
  "compilerOptions": {
    "types": ["vite/client"]
  }
}

要覆盖默认类型定义,新建一个包含你所定义类型的文件,然后在 d.ts 注释前引入:

// vite-env-override.d.ts (the file that contains your typings):
declare module "*.svg" {
  const content: React.FC<React.SVGProps<SVGElement>>;
  export default content;
}
// The file containing the reference to vite/client
/// <reference types="./vite-env-override.d.ts" />
/// <reference types="vite/client" />

3.3 CSS

以 .module.css 为后缀的 CSS 被认为是 CSS modules 文件。导入这样的文件会返回一个相应的模块对象:

/* example.module.css */
.red {
  color: red;
}
import classes from "./example.module.css";
document.getElementById("foo").className = classes.red;

通过 ?inline 关闭 css 注入页面,使 css 样式失效。

import "../src/assets/css/index.scss?inline";

3.4 JSON

JSON 可以被直接导入 —— 同样支持具名导入:

// 导入整个对象
import json from "./example.json";
// 根字段具名导入 —— 有效帮助 treeshaking!(只打包用到的依赖)
import { field } from "./example.json";

3.5 Glob 导入

import.meta.glob 函数从文件系统导入多个模块,默认是懒加载的,过动态导入实现,传入 { eager: true } 转化为直接引入。传入{ as: "raw", eager: true }转化为字符串形式:

const modules = import.meta.glob("./dir/*.js");
// 转译为
const modules = {
  "./dir/foo.js": () => import("./dir/foo.js"),
  "./dir/bar.js": () => import("./dir/bar.js"),
};
 
const modules = import.meta.glob("./dir/*.js", { eager: true });
// 转译为
import * as __glob__0_0 from "./dir/foo.js";
import * as __glob__0_1 from "./dir/bar.js";
const modules = {
  "./dir/foo.js": __glob__0_0,
  "./dir/bar.js": __glob__0_1,
};
 
const modules = import.meta.glob("./dir/*.js", { as: "raw", eager: true });
// 转译为
const modules = {
  "./dir/foo.js": 'export default "foo"\n',
  "./dir/bar.js": 'export default "bar"\n',
};

使用数组多个匹配文件:

const modules = import.meta.glob(["./dir/*.js", "./another/*.js"]);

使用 !排除匹配中的一些文件:

const modules = import.meta.glob(["./dir/*.js", "!**/bar.js"]);
// 转译为
const modules = {
  "./dir/foo.js": () => import("./dir/foo.js"),
};

3.6 构建优化

CSS 代码分割

Vite 会根据异步 chunk 模块生成单独的 CSS 文件。在异步 chunk 加载完成时通过  标签载入,该异步 chunk 只在 CSS 加载完毕后执行,避免发生 FOUC (无样式内容闪烁)。通过设置 build.cssCodeSplit 为 false 来禁用 CSS 代码分割。将所有 CSS 抽取到一个文件。

异步 Chunk 加载优化

问题:在无优化的情境下,当异步 chunk A 被导入时,浏览器将必须请求和解析 A,弄清楚它也需要共用 chunk C。这会导致额外的网络往返:Entry ---> A ---> C

解决:Vite 使用预加载步骤自动重写代码,来分割动态导入调用,以实现当 A 被请求时,C 也将 同时 被请求:Entry ---> (A + C)

4. 命令行界面

# 启动 Vite 开发服务器
vite [root]
 
# 构建生产版本
vite build [root]
 
# 预构建依赖
vite optimize [root]
 
# 本地预览构建产物
vite preview [root]

5. 使用插件

5.1 添加插件

添加后,在 vite.config.js 配置文件中的 plugins 数组中引入它。例如,要想为传统浏览器提供支持:

$ npm add -D @vitejs/plugin-legacy
// vite.config.js
import legacy from "@vitejs/plugin-legacy";
import { defineConfig } from "vite";
 
export default defineConfig({
  plugins: [
    legacy({
      targets: ["defaults", "not IE 11"],
    }),
  ],
});

5.2 按需应用

使用 apply 属性指明插件在 'build' 或 'serve' 哪种模式时调用:

// vite.config.js
import typescript2 from "rollup-plugin-typescript2";
import { defineConfig } from "vite";
 
export default defineConfig({
  plugins: [
    {
      ...typescript2(),
      apply: "build",
    },
  ],
});

6. 依赖预构建

首次启动 vite 时,Vite 会预构建项目依赖。目的在于:1. 将 CommonJS 或 UMD 转化为 ES 模块。2. 将许多内部模块的 ESM 依赖项转换为单个模块。

7. 构建生产版本

打包运行 vite build 命令。将 /index.html 作为构建入口点,生成静态部署的应用包。

8. 部署静态站点

默认打包文件 dist,可通过 build.outDir 修改。vite preview 只作预览本地构建,不应作为生产服务器。Vite 构建的项目已经配置好了 npm scripts:

{
  "scripts": {
    "build": "vite build",
    "preview": "vite preview"
  }
}

8.1 构建应用

运行 npm run build 打包,默认打包到 dist 文件夹,可以将 dist 文件夹部署到你喜欢的平台。构建完成后通过 npm run preview 在本地启动一个静态 wbe 服务器,将 dist 文件夹运行在 http://localhost:4173,这样可以在本地查看构建产物是否正常运行。可以通过 --port 配置端口:

# 打包
npm run build
 
# 预览
npm run preview
# or
npm run preview --port 8080

8.2 GitHub Pages

在 vite.config.js 中配置 base,设置部署根目录。比如部署到 https://.github.io/,base 设置为'/',如果部署到 https://.github.io//,base 设置为'//'。

<!-- base: 'admin' -->
<script
  type="module"
  crossorigin
  src="/admin/assets/index-qcvr7oK4.js"
></script>
<link rel="stylesheet" crossorigin href="/admin/assets/index-ICKpZ_al.css" />
 
<!-- base: '/' -->
<script type="module" crossorigin src="/assets/index-qcvr7oK4.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-ICKpZ_al.css" />

9. 环境变量与模式

9.1 内置环境变量

import = {
  meta: {
    env: {
      // 运行模式
      MODE: 'development',
      // 部署的基本 URL
      BASE_URL: '/',
      // 是否运行在生产环境
      PROD: false,
      // 是否运行在开发环境
      DEV: true,
      // 是否运行在 server 上
      SSR: false
    }
  }
}

9.2 .env 文件

Vite 使用 dotenv 加载额外的环境变量,指定模式的优先级(.env.development)高于通用模式(.env),并通过 import.meta.env 暴露给客户端,变量命名必须以 VITE\_为前缀才会被暴露出去:

.env                # 所有情况下都会加载
.env.local          # 所有情况下都会加载,但会被 git 忽略
.env.[mode]         # 只在指定模式下加载
.env.[mode].local   # 只在指定模式下加载,但会被 git 忽略

随着环境变量越来越多,我们希望 TS 可以给出智能提示,可以通过在 src 下创建 env.d.ts,然后定义如下代码实现:

/// <reference types="vite/client" />
interface ImportMetaEnv {
  readonly VITE_APP_TITLE: string;
  // 更多环境变量...
}
 
interface ImportMeta {
  readonly env: ImportMetaEnv;
}

9.3 在 HTML 中使用

任何命名的环境变量可以在 HTML 中使用,用法 %ENV_NAME%:

<h1>Vite is running in %MODE%</h1>
<p>Using data from %VITE_API_URL%</p>

9.4 模式

vite 加载 .env.development 的环境变量,vite build 加载的 .env.prodution 的环境变量,可以通过 --mode 替换加载的环境变量,比如在 staging(预发布)模式下构建应用加载 .env.staing 的环境变量:

vite build --mode staging

10. 性能优化

10.1 减少解析操作

Vite 支持通过 resolve.extensions 选项“猜测”导入路径,该选项默认为 ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']。当使用 import './Component' 导入 ./Component.jsx 时,Vite 将运行以下步骤来解析它:

| 检查 ./Component 是否存在,不存在。

| 检查 ./Component.mjs 是否存在,不存在。

| 检查 ./Component.js 是否存在,不存在。

| 检查 ./Component.mts 是否存在,不存在。

| 检查 ./Component.ts 是否存在,不存在。

| 检查 ./Component.jsx 是否存在,存在!

如上,导入一个文件需要进行 6 次文件系统检查。隐式导入越多,解析所需的时间就越多。所以明确导入路径,例如:import './Component.jsx' 可以减速解析时间。

10.2 避免使用桶文件

桶文件(barrel files)是重新导出同一目录下其他文件 API 的文件。例如:

// src/utils/index.js
export * from "./color.js";
export * from "./dom.js";
export * from "./slash.js";

导入一个单独的 API,import { slash } from './utils',需要获取和转换桶文件中的所有文件。这意味着在初始页面加载时,加载的文件比所需的要更多,导致页面加载速度变慢。所以应避免使用桶文件(barrel files),直接导入单独 API:import { slash } from './utils/slash.js'

Vite 官方文档速通(下)https://developer.aliyun.com/article/1512023?spm=a2c6h.13148508.setting.29.f8774f0euyBLtl

目录
打赏
0
0
0
0
15
分享
相关文章
|
5月前
|
【有手就行系列】Vue快速入门案例
【有手就行系列】Vue快速入门案例
47 0
|
10月前
|
SASS 官方文档速通
SASS 官方文档速通
54 1
Vue-Router 官网速通(上)
Vue-Router 官网速通(上)
40 1
|
10月前
|
Vite 官方文档速通(下)
Vite 官方文档速通(下)
150 0
Vue3 官方文档速通(上)
Vue3 官方文档速通(上)
485 0
Vue3官方文档速通(下)
Vue3官方文档速通(下)
147 0
|
10月前
|
Vue3 官方文档速通(中)
Vue3 官方文档速通(中)
666 0
《VitePress 简易速速上手小册》第1章:VitePress 入门(2024 最新版)
《VitePress 简易速速上手小册》第1章:VitePress 入门(2024 最新版)
505 1
Vue-Router 官网速通(下)
Vue-Router 官网速通(下)
41 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等