vite8 与 Rolldown 新兴构建工具链详解,构建打包实践
vite8 与 Rolldown 学习
历史
- 发展阶段
-
- grunt、gulp只是工作流的开发,将繁琐的任务(task)自动化(石器时代)
-
- webpack, 模块化打包构建先驱, (rollup, parcel, esbuild同时期的替代工具)
-
- vite, bundless 方案, 借助于浏览器原生 esm支持,开发阶段无需打包,直接启动开发服务器,提升开发体验
- 开发环境:esbuild(快速冷启动),
- 生产环境:rollup(生态繁荣,配置话更高)
-
- 字节,
- rsbuild -> rspack -> rslib -> rspress等、
- 兼容webpack那一套
- oxc体系(尤雨溪团队基于 rust)
vite8 新特性
- rolldown 集成
- 性能监控和诊断(自动集成)
- 插件生态升级
初始化项目
- npm init -y
- 创建 pnpm-workspace.yaml
packages:
- "applications/*"
- "packages/*"
- "tools/*"
- 创建 applications 文件加 下面创建一个 demo 项目
- cd applications/demo
- 初始化 pnpm init -y
{
"name": "@vitebasic/demo",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview" // 把构建好的包(vite build)启动本地预览
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"vue": "3.5.22"
},
"devDependencies": {
"vite": "^7.1.10",
"@vitejs/plugin-vue": "^6.0.1"
}
}
- pnpm i
- 创建 src 文件夹,创建 index.ts
console.log("hello vite8");
- demo下创建 index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<!-- 必须是 type='module' -->
<script type="module" src="./src/index.ts"></script>
</body>
</html>
- 创建 src/App.vue
<template>
<div>hello word</div>
</template>
<script setup>
console.log("app demo");
</script>
<style lang="scss" scoped></style>
- 创建 src/index.ts
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
app.mount("#root");
- 运行 pnpm run dev
- 这个时候就会报错,因为 vite 默认是支持 .vue 文件,但是不支持 .ts 文件,所以我们需要安装 @vitejs/plugin-vue 插件
- 安装后,在 vite.config.ts 中配置插件
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import viteImagemin from "vite-plugin-imagemin";
export default defineConfig({
plugins: [
vue()
// 图片压缩插件配置
viteImagemin({
gifsicle: { optimizationLevel: 7, interlaced: false },// gif图片压缩
optipng: { optimizationLevel: 7 },// png图片压缩
mozjpeg: { quality: 80 },// jpeg图片压缩
pngquant: { quality: [0.8, 0.9], speed: 4 },// 图片压缩
svgo: {
plugins: [
{
name: 'removeViewBox',// 移除viewBox
},
{
name: 'removeEmptyAttrs',// 移除空属性
active: false,
},
],
},
})
],
build: {
outDir: "dist", // 打包输出目录
sourcemap: true, // 是否生成sourcemap
minify: "esbuild", // 现在通常使用 esbuild来打包, terser需要安装terser
cleanCss: true, // 清理css
cleanEmpty: true, // 清理空文件夹
cleanConsole: true, // 清理控制台输出
target: "es2015", // 设置构建目标,现代浏览器通常设为 'es2015' 或更高
// clean: true,// 清理所有
rollupOptions: {
output: {
// 这种方式是静态导入,会打包成一个单独的文件
// manualChunks: {
// lodash: ["lodash"], // 将lodash打包成一个单独的文件
// vue: ["vue"], // 将vue打包成一个单独的文件
// utils: ["./src/utils/index.ts"], // 将utils打包成一个单独的文件
// // 如果还有需要打成单独的文件的,可以继续添加
// },
// 代码分割策略
manualChunks: (id) => {
// 1. 将 node_modules 中的所有第三方库打包到 vendor.js
// 这样可以避免未在下面手动指定的库被打包进 index.js
if (id.includes('node_modules')) {
return 'vendor';
}
// 2. 静态指定的特定库打包到单独文件 (注意:这种方式需要确保你的项目里确实安装了这些包)
// 如果你使用了 lodash,它会匹配上面的 node_modules 规则,所以如果你想单独拆分 lodash,
// 需要把 node_modules 的判断放在下面,或者写更精确的正则。
// 示例:如果一定要单独拆分 vue
// if (id.includes('node_modules/vue')) {
// return 'vue-vendor';
// }
},
// 文件命名 hash
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js',
assetFileNames: '[ext]/[name]-[hash].[ext]',
},
chunkSizeWarningLimit: 1000,// chunk 大小警告的限制 (kb)
},
},
});
- 重新运行 pnpm run dev,就可以看到页面了
安装 vite8
- npmjs.org 搜
rolldown-vite仓库
"vite": "npm:rolldown-vite@latest"
// 相关插件
- vite.config.ts
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [vue()], // 插件
server: {
port: 3000, // 端口
},
build: {
// rollupOptions vite 8之前的,线上(生产环境)打包用的
rolldownOptions: {
treeshake: true, // 摇树优化
}, // rollupOptions vite8用的
},
});
插件整合
- 插件的本质是由插件系统决定的, 由vite开发、vue开发者确定插件协议
- vite插件的本质是一个函数
- vue插件的本质是一个对象,对象中有一个
install方法 - vite.config.ts
import vue from "@vitejs/plugin-vue";
import type { PluginOption } from "vite";
import { defineConfig } from "vite";
// 自定义插件(vite插件的内部结构如下)
const pluginHtml = () => {
const options = {
name: "html", // 插件名称
transform(code: string, id: string) {
consol.log(code, id);
}
transformIndexHtml(html: string) {
return html.replace("<!--title-->", "自定义标题"); // 替换html中的内容
},
}; // 这里可以定义插件的配置项
return options satisfies PluginOption; // 高级用法
};
export default defineConfig({
plugins: [vue(), pluginHtml()], // 插件
server: {
port: 3000, // 端口
},
build: {
// rollupOptions vite 8之前的,线上(生产环境)打包用的
rolldownOptions: {
treeshake: true, // 摇树优化
}, // rollupOptions vite8用的
},
});
eslint配置 eslint: "^9.37.0"
- pnpm i eslint@9.37.0 eslint-plugin-oxlint@1.23.0 --save-dev
- eslint-plugin-oxlint@1.23.0就是老的eslint兼容 oxlint的插件
- pnpm i oxlint@1.23.0 -D 用来替换掉上面的 eslint
{
"name": "@vitebasic/demo",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"lint:es": "eslint . --ext .ts,.vue",
// "lint:oxc": "oxlint ." 扫描全部的
"lint:oxc": "oxlint src/**/*.{ts,vue}" //扫描src下的
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"vue": "3.5.22"
},
"devDependencies": {
"vite": "npm:rolldown-vite@latest",
"@vitejs/plugin-vue": "^6.0.1",
"eslint": "^9.37.0",
"oxlint": "^1.23.0"
}
}
- 创建 eslint.config.js 文件
// 暂时没有配置
export default [{}];
- 这个看文档了,东西有点小多