Vite的优势
1.上手非常简单, 没有很多复杂晦涩的配置
2.传统的打包文件: 从入口文件把所有的文件打包成一个bundle, 构建应用, 提供服务 (如图一)
3.Vite的打包: 在浏览器请求源码时进行转换并按需提供源码,根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理 (如图二)
图一
图二
Vite 对比其他构建工具
1.High Level Api (其他都是low Level Api, 关注太细节了, 更关注比较细节的实现, 比如文件如何加载, 代码如何去编译, 模块和模块如何依赖的关系, 怎么去加载, 怎么去load)
2.不包含自己的编译能力,不参与编译,底层是Rollup和ESbuild (只是集成了rollup的功能, 启动了devserver, 帮我们在中间进行串联, 管理模块之间的图谱, 监听模块之间的更新来进行HMR的推送)
3.完全基于ESM加载方式进行开发
Vite VS Webpack Rollup
1. webpack功能更强大,rollup是一个更加专一的工具(Rollup诞生的目的就是为了build esm的module, 只关注于build javascript而不考虑平台的工具)
2.webpack构建产物有许多自身特性,辅助函数;rollup不会,它产出的是符合规范的代码,初衷是为工具类库服务,而不是前端项目
3.vite的目标是工程,Vite更加上层,更方便开发项目 ( webpack, rollup 注重的是如何构建)
4.vite在DEV环境使用了EsBuild,启动的时候只做了一些预编译,初次访问只需要编译首页需要加载的内容,相当于只有一条路径,而webpack需要递归遍历所有路径输出bundle
使用Vite学习成本没有webpack那么高,它从一开始设计就是为了面向项目开发。vite为项目而生,不为构建而生
5.vite减少了很多配置量
主要减少的工作: dev server、 不需要配置各类loader(less, scss,babel)、 内置build命令(vite build, vite dev, vite serve)
vs 脚手架 vue-cli,create-react-app
你要修改后两者,你还是要修改webpack配置
cra需要eject弹射
vue-cli需要configWebpack和chainWebpack
Vite有自身的插件系统,尽量做到了简单
webpack更全面,rollup更专一,vite更High-level更好用
生态兼容了rollup的插件, 快
Vite 的命令以及创建各种不同框架
yarn create vite
➜ yarn create vite
yarn create v1.22.10
warning package.json: No license field
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
warning Your current version of Yarn is out of date. The latest version is "1.22.19", while you're on "1.22.10".
info To upgrade, run the following command:
$ curl --compressed -o- -L https://yarnpkg.com/install.sh | bash
success Installed "create-vite@4.0.0" with binaries:
- create-vite
- cva
? Project name: › vite-project
Vite 中处理静态资源(CSS/TS/JSON/WebAssembly)
显示URL引入
import imgUrl from './img.png?url'
将资源引入为字符串
import shaderString from './shader.glsl?raw'
导入脚本作为worker
// index.js
import Worker from './worker.js?worker'
const worker = new Worker();
worker.onmessage = function (e){
console.log(e)
}
// worker.js
var i = 0;
function timedCount() {
i += 1;
postMessage(i);
setTimeout(timedCount, 500);
}
timedCount();
CSS/Less/Scss
Vite 官方已经集成了postcss 的插件, 可以直接加一个postcss.config.js的文件, 然后在项目中添加想要使用的库(less/sass/scss)
// postcss.config.js
module.exports = {
plugins: [require('@postcss-plugins/console')]
}
同样地也支持css.module 的写法
/* example.module.css */
.red{
color:red;
}
// other file
import $classes from './example.module.css'
<div class={$classes.red}>我是红色</div>
Vite中使用Typescript
Vite 官方天然支持.ts文件;但仅执行.ts文件的转译工作, 并不执行任何类型检查,如果需要做校验, 可以手动执行tsc --noEmit 使用Typescript只需要在项目中添加typescript包, 并添加tsconfig.json文件
{
"compilerOptions": {
"target": "ESNext",
"isolatedModules": true, // `esbuild` 只执行没有类型信息的转译,它并不支持某些特性, 建议设置为true
"skipLibCheck": true, // 一些库不能很好的与"isolatedModules": true共同工作, 可以在上游仓库修复好之前暂时使用这个属性来缓解错误
}
}
客户端类型 可以添加一个d.ts文件提供类型定义补充
// vite-env.d.ts
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
interface ImportMetaEnv {
VITE_TITLE: string;
}
同时也可以将vite/client 添加到tsconfig中compilerOptions.types下
"compilerOptions":{
"types": ["vite/client"]
}
JSON
JSON可以直接被导入----同样支持具名导入
// 导入整个对象
import json from './example.json'
// 对一个根字段使用具名导入 —— 有效帮助 treeshaking!
import { field } from './example.json'
Glob导入
Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块:
// 动态导入实现
const modules = import.meta.glob("./ts/*.ts");
// 直接引入所有的模块
const modules1 = import.meta.glob("./ts/*.ts", { eager: true });
// 支持以字符串形式导入文件
const modules2 = import.meta.glob("./ts/*.ts", { as: "raw" });
// 将资源作为 URL 加载
const modules3 = import.meta.glob("./ts/*.ts", { as: "url" });
// 多个匹配模式
const modules4 = import.meta.glob(["./ts/*.ts", "./another/*.ts"]);
// 反面匹配模式
const modules5 = import.meta.glob(["./ts/*.ts", "!**/bar.ts"]);
// 具名导入 只想要导入模块中的部分内容
const modules6 = import.meta.glob("./ts/*.ts", { import: "setup" });
// 对这些模块进行 tree-shaking
const modules7 = import.meta.glob("./ts/*.ts", { import: "setup", eager: true });
// 加载默认导出
const modules8 = import.meta.glob("./ts/*.ts", { import: "default", eager: true });
// 自定义查询
const modules9 = import.meta.glob('./ts/*.ts', {
query: { foo: 'bar', bar: true },
});
动态导入
和glob导入类似,Vite 也支持带变量的动态导入。
const module = await import(`./dir/${file}.js`)
[[info]]注意⚠️:变量仅代表一层深的文件名。如果 file 是 foo/bar,导入将会失败
WebAssembly
预编译的 .wasm 文件可以通过 ?init 来导入; 默认导出一个初始化函数,返回值为所导出 wasm 实例对象的 Promise
// assemb.ts 求第n个斐波拉契数字
export function fib(n: any) {
var a = 0,
b = 1;
if (n > 0) {
while (--n) {
let t = a + b;
a = b;
b = t;
}
return b;
}
return a;
}
可以用asc来将ts文件转化为.wasm文件
npm i -g assemblyscript
asc assemb.ts --outFile assemb.wasm --optimize
转化完成之后在文件中使用
import init from './fib.wasm?init';
init({}).then((m: WebAssembly.Instance) => {
console.log(m.exports?.fib?.(10)); // 55
});
Vite中集成eslint、prettier和husky
- 添加.eslint.js 文件
module.exports = { extends: "standard", // 标准 globals: {}, // 全局 rules: {} // 规则 } - 添加.prettierrc 文件
{
"semi": true,
"singleQuote": true
}
- 添加husky
npx i husky
npx husky add .husky/pre-commit "npm run lint"
Vite env 环境变量
Vite 在一个特殊的 import.meta.env 对象上暴露环境变量
- 通过import.meta.env 可以导入
- MODE/BASE_URL/PROD/DEV/SSR
- 直接把import.meta.env的对象值放入编译里面, 不会存成一个对象
- 增加env文件, 变量需要加上VITE前缀
.env # 所有情况下都会加载
.env.local # 所有情况下都会加载,但会被 git 忽略
.env.[mode] # 只在指定模式下加载
.env.[mode].local # 只在指定模式下加载,但会被 git 忽略