Vite初始化前端项目
-
初始化 $
pnpm create vite
conffLibrary/pnpm/store/v3/tmp/dlx-42133 | Progress: resolved 1, reused 0, downlLibrary/pnpm/store/v3/tmp/dlx-42133 | +1 + Library/pnpm/store/v3/tmp/dlx-42133 | Progress: resolved 1, reused 0, downlLibrary/pnpm/store/v3/tmp/dlx-42133 | Progress: resolved 1, reused 0, downlLibrary/pnpm/store/v3/tmp/dlx-42133 | Progress: resolved 1, reused 0, downloaded 1, added 1, done ? Project name: › vite-project ? Select a framework: › - Use arrow-keys. Return to submit. Vanilla Vue ❯ React Preact Lit Svelte Solid Qwik Others ? Select a variant: › - Use arrow-keys. Return to submit. ❯ TypeScript TypeScript + SWC JavaScript JavaScript + SWC Remix ↗ Scaffolding project in /Users/Wang/Desktop/x/vite-project... Done. Now run: cd vite-project pnpm install pnpm run dev
-
输入自己的项目名称,一路选择 React + TS, 之后执行
confcd vite-project pnpm install pnpm run dev
-
之后,运行成功
confVITE v5.3.1 ready in 200 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help
Vite 与 CRA 之间的性能对比
- CRA (create-react-app) 是 React 官方推荐的脚手架
- 自行做不太精准的一些测试
Vite | CRA | |
---|---|---|
初始化 & 启动时间 | 44s | 3min23s |
打包时间 | 2s | 6s |
打包产物大小 | 152kb | 565kb |
- 由上面数据可见,vite 完胜,从网上的统计数据中:Vite 已经比 cra 快了接近 6 倍
- 并且一开始就甩了 cra 一大截,显而易见地提升了初始化速度和开发体验
项目目录
conf
├── index.html
├── package.json
├── pnpm-lock.yaml
├── public/
├── src/
│ ├── assets/
│ ├── App.css
│ ├── App.tsx
│ ├── index.css
│ ├── main.tsx
│ └── vite-env.d.ts
├── .eslintrc.cjs
├── .gitignore
├── package.json
├── pnpm-lock.yaml
├── tsconfig.app.json
├── tsconfig.node.json
├── pnpm-lock.yaml
├── tsconfig.json
└── vite.config.ts
探究 dev 环境
-
当你访问 http://localhost:5173 的时候,Vite 的 Dev Server 会自动返回这个 HTML 文件的内容
html<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vite + React + TS</title> </head> <body> <div id="root"></div> <script type="module" src="/src/main.tsx"></script> </body> </html>
-
在这个 HTML 文件中,在 body 标签中除了 id 为 root 的根节点之
外,还包含了一个声明了 type="module" 的 script 标签:
<script type="module" src="/src/main.tsx"></script>
-
由于现代浏览器原生支持了 ES 模块规范,因此原生的 ES 语法也可以直接放到浏览器中执行,只需要在 script 标签中声明 type="module" 即可。
-
比如上面的 script 标签就声明了 type="module",同时 src 指向了 /src/main.tsx 文件,此时相当于请求了 http://localhost:5173/src/main.tsx 这个资源,Vite 的 Dev Server 此时会接受到这个请求,然后读取对应的文件内容,进行一定的中间处理,最后将处理的结果返回给浏览器
-
这里的中间处理是:编译文件内容返回给浏览器
-
好,现在看下 main.tsx 的内容
tsimport React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <App /> </React.StrictMode>, )
-
这里,浏览器并不识别 tsx 语法,也无法直接 import css 文件,上面这段
代码究竟是如何被浏览器正常执行的,看下浏览器的网络面板,里面返回的是编译后的内容
-
这涉及 Vite 内部的编译流程,Vite 会将项目的源代码编译成浏览器可以识别的代码,与此同时,一个 import 语句即代表了一个 HTTP 请求,Vite Dev Server 会读取本地文件,返回浏览器可以解析的代码
-
当浏览器解析到新的 import 语句,又会发出新的请求,以此类推,直到所有的资源都加载完成
-
可见,Vite 所倡导的 no-bundle 理念: 利用浏览器原生 ES 模块
的支持,实现开发阶段的 Dev Server,进行模块的按需加载,而不是先整体打包再进行加载 -
相比 Webpack 这种必须打包再加载的传统构建模式,Vite 在开发阶段省略了繁琐且耗时的打包过程,这也是它为什么快的一个重要原因
-
默认情况下,index.html 在 src 之外,按照习惯,我们希望将它移动到src目录中,那就需要同步修改 vite.config.ts, 添加
root: path.join(__dirname, 'src')
tsimport { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // 引入 path 包注意两点: // 1. 为避免类型报错,你需要通过 `pnpm i @types/node -D` 安装类型 // 2. tsconfig.node.json 中设置 `allowSyntheticDefaultImports: true`,以允许下面的 default 导入 import path from 'path' // https://vitejs.dev/config/ export default defineConfig({ root: path.join(__dirname, 'src'), // 主要注意这里 plugins: [react()], })
-
之后,在 index.html 和 App.tsx 中修改相对路径
探究生产环境
-
在生产环境中,Vite 依然会基于Rollup 进行打包,并采取一系列的打包优化手段。
-
从脚手架项目的 package.json 中就可见一斑:
ts"scripts": { "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" }
-
关注 build 和 preview, 在 build 之后,可以执行 preview 验证打包后的状态
-
为什么在 vite build 命令执行之前要先执行 tsc 呢?tsc 作为 TypeScript 的官方编译命令,可以用来编译 TypeScript 代码并进行类型检查
-
而这里的作用主要是用来做类型检查,我们可以从项目的 tsconfig.app.json 中注意到这样一个配置
ts{ "compilerOptions": { // 省略其他配置 // 1. noEmit 表示只做类型检查,而不会输出产物文件 // 2. 这行配置与 tsc --noEmit 命令等效 "noEmit": true, }, }
-
虽然 Vite 提供了开箱即用的 TypeScript 以及 JSX 的编译能力,但实际上底层并没有实现 TypeScript 的类型校验系统
-
因此需要借助 tsc 来完成类型校验(在 Vue 项目中使用 vue-tsc 这个工具来完成),在打包前提早暴露出类型相关的问题,保证代码的健壮性