news 2026/8/31 10:35:05

从Webpack到Vite+tsup+Rolldown:构建工具组合拳的实践与思考

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从Webpack到Vite+tsup+Rolldown:构建工具组合拳的实践与思考

我前阵子帮一个团队评估新项目的构建方案。需求并不复杂:TypeScript 写的后台管理系统,有组件库、工具函数,还要把几个模块抽出来单独发布。问到 Webpack 几乎是本能的,毕竟团队所有存量项目都基于它,文档熟练,踩坑经验也足够。但聊得越深,我越清楚一件事:真正让人想换掉 Webpack 的,往往不是它“不能用”,而是它的配置成本、启动成本和心智负担。这个议题不算新鲜,但今年情况确实不太一样——TypeScript 已经接近默认基础设施,Vite 覆盖了大量应用开发场景,tsup 把库构建简化到近乎普通脚本,Rolldown 又把“Vite 底层换核”从话题变成了可尝试的路径。

所以我更愿意把这次思考描述成一个判断:这一轮工具更替,重点不是“打包更快”,而是把之前被 Webpack 硬塞进一个配置文件里的多件事拆开了。Webpack 像一个什么都管的大管家,能力边界宽,但任何一件事想改顺手,都要先理解那套相当庞杂的规则。而 tsup、Vite、Rolldown 的思路更接近分工协作:开发时用 Vite 的即时反馈,发布库时用 tsup 的干净产物,底层打包交给 Rolldown 或 esbuild 这类更高效的引擎。“告别 Webpack”不一定意味着否定它,而是意味着你的构建流程,不再由一个庞大的配置系统统一接管。

1. 先别急着告别:Webpack 教会了我们什么,又在哪里透支了体验

1.1 Webpack 当年解决的核心问题

回到 Webpack 盛行的时代,前端工程化面临的问题和今天完全不同。那时模块规范还在过渡,浏览器对 ES Module 的支持能力有限,开发者需要一套机制把散落各处的 JS、CSS、图片、字体统一处理。Webpack 的价值不只是“打包”,而是提供了一个统一资源处理模型:loader 负责把各种资源转成可打包的模块,plugin 负责在打包生命周期里做优化、注入、拆分。这个模型最厉害的地方在于,它把不确定的外部资源世界,收敛成一个可编程的构建流程。

直到今天,很多团队仍然依赖 Webpack 的 loader 体系和插件生态来解决特殊需求。比如样式预处理、图片压缩、代码混淆、产物注释清理、按需加载、多页面打包、复杂的环境变量注入。这些能力是真实的,也是很多项目正常运行的基础。任何一种替代方案在宣传自己“更快”之前,都得先回答一个问题:你的生态能不能覆盖这些实际场景?

从历史作用来说,Webpack 完成了前端工程化的一次大统一。正因为它太成功,后来才有大量项目建立在对它的路径配置、loader 顺序、plugin 实现细节的依赖之上。理解了这一层,你才能理解“告别 Webpack”为什么不能只是一次简单的工具替换。

1.2 想更换工具的三种真实信号

不是所有项目都需要换工具。我见过不少团队,把 Webpack 配置优化得很好,构建速度也在可接受范围,那确实没必要为了追新而追新。但如果你遇到下面三种信号,就该认真考虑新的组合方案了。

第一种信号:配置增量已经超过业务增量。一个新页面不需要写几行业务代码,反而要先搞清楚“为什么这个 svg 走不了”、“为什么新增的目录没被打进产物”、“为什么 node_modules 里的某个包又被编译了一遍”。这种时候,工具已经从基础设施变成了日常阻力。

第二种信号:dev server 的启动和热更新时间开始影响开发节奏。Webpack 的缓存策略和持久化缓存配置可以解决一部分问题,但它的架构决定了,全量编译和复杂依赖图的处理开销很难被彻底消掉。当改动一个文件要等 5 到 10 秒甚至更久,开发状态就会被打断。很多人对 Webpack 的抱怨不是“打包慢”,而是“等待感太强”。

第三种信号:你希望同一份代码既能作为应用的一部分运行,又能被独立发布成库或组件给其他项目使用。Webpack 虽然也支持 library 模式,但配置起来并不轻松,还要处理 externals、UMD、ESM 产物兼容等问题。相比之下,用 tsup 这类面向库构建的工具,几乎可以在一份不到十行的配置里完成同样的事情。

1.3 一个容易被忽略的干扰项:有些“ts”和 TypeScript 无关

搜索“TS”这个关键词时,经常看到两类完全不同的内容:一类是 TypeScript,另一类是视频传输流中的分片文件。比如“下载视频变成了很多 ts 文件”、“ffmpeg ts 伪装 jpg”、“带 subtitle 的 ts 流”这些,和前端工程化没有任何关系。它们只是恰好用了同一个缩写。

我提这件事,是因为工具选型时最怕被错误信息干扰。如果你发现自己绕进“TS 不是 TypeScript”的检索迷宫里,先退出来,把自己要找的东西定义清楚。这篇文章里的 TS,全部指 TypeScript。

想替换 Webpack 不是情绪问题,而是判断问题。你要先看清当前项目到底被什么困住,再决定新方案承担什么角色。

2. 组合拳不是堆工具:tsup、Vite、Rolldown 如何分工

2.1 三层分工模型:应用构建、库构建、打包内核

很多人一开始容易做错一件事:把 tsup、Vite、Rolldown 当成“三个 Webpack 替代品”来回对比,然后试图选一个赢家。实际上,这三者在当前生态里不是同一个层级的东西,它们解决的问题也不一样。

一个相对清晰的分层方式是:

  • 应用层:你用 Vite 启动开发服务器、代理接口、编译应用代码、产出 web 应用所需的静态资源。
  • 库层:你用 tsup 打包可复用代码,比如组件库、工具函数、请求封装、类型定义,输出 ESM 和 CJS 双格式,同时生成声明文件。
  • 底层内核:Rolldown 或 esbuild 负责真正执行打包、转译和代码转换的算法。

Vite 是一个完整的应用开发与构建工具,它在开发阶段用 esbuild 做依赖预构建,在生产构建阶段用了 Rollup。tsup 则是一个更聚焦的“库打包器”,它的底层早期依赖 esbuild,后来也能接入别的底层能力。Rolldown 更偏向底层,它想用 Rust 重新实现一个和 Rollup API 兼容的打包内核,未来可能替代 Vite 底层依赖的 Rollup。

用生活里的例子类比:Vite 像一套精装房的施工流程,从进场到交付都管;tsup 像一个家具工厂,负责把某些标准模块做成可搬走的成品;Rolldown 更像生产流水线上的核心机床,效率更高,但它本身不直接面向最终用户。

这套分工模型想传递的核心观点是:工具组合的价值不在工具数量多,而在于每个工具只承担自己最擅长的一层。你不需要把库构建和应用构建的所有配置都堆在同一个工具里。

2.2 为什么会出现 Rolldown 这种“底层换核”方案

要理解 Rolldown,得先理解 Vite 现在的一个隐性摩擦。Vite 在开发阶段使用 esbuild 做依赖预构建和 TS 转译,速度非常快;但在生产构建阶段使用 Rollup,因为 esbuild 的产物控制和代码分割能力还达不到完整替代 Rollup 的程度。这带来一个客观问题:开发环境和生产环境的模块处理逻辑并不完全一致。很多“开发环境正常,打包后报错”的诡异问题,根源就在双引擎差异。

Rolldown 的思路是用 Rust 重写一个 Rollup 兼容的打包内核,它既保留 Rollup 的插件生态和产物模型,又能获得接近 esbuild 的性能。如果这个方向成熟,Vite 的开发和生产构建可以共用同一套内核,从而消除偏差。这也就是“只要换一个底层,整个上层体验都会变化”的逻辑。

需要强调,Rolldown 不是基于 esbuild 的简单替代,也不是 Vite 的替代方案。它是给 Vite 这类构建工具提供更优底层的实验性项目。从公开进展看,它已经有部分里程碑版本发布,但距离“所有生产项目无感切换”仍有距离。落地前务必以官方文档和最新 changelog 为准。

2.3 这套组合适合谁,不适合谁

先说适合的场景。

如果你是新手项目、中小型 Web 应用,或者团队正在做技术栈统一、需要同时维护应用和多个库,那么 tsup + Vite 的组合非常值得尝试。它配置量小、反馈快、默认行为清晰,很容易把一个项目的构建流程控制在可理解的范围内。对于组件库、工具包、接口层封装这类产物,tsup 几乎是当前最省心的选择之一。

再说不适合的场景。

如果你有一个大型存量 Webpack 工程,里面用了大量自定义 loader、复杂 plugin、动态 require、依赖内部模块路径等写法,那么“告别 Webpack”的成本会非常高。这种情况下,更合理的策略不是推翻重来,而是渐进拆分:先把可以被标准工具处理的模块抽离出去,再逐步把剩余部分迁移到新工具上。

如果你只是被之前某个项目里的 Webpack 配置搞烦了,但新项目并不需要多库发布、组件复用和快速迭代,那组合拳的优势就不明显。工具是为你服务的,不是用来证明你技术很新的装饰品。

3. 落地基线:TS + Vite + tsup 的最小工程怎么搭

3.1 项目结构和依赖准备

我先给一个常见的最小结构。这里以“应用 + 独立库”并存的单仓库简化版为例展开,避免一上来引入复杂 monorepo 概念。

your-project/ ├─ src/ │ ├─ components/ │ ├─ pages/ │ ├─ utils/ │ ├─ api/ │ └─ index.ts ├─ package.json ├─ tsconfig.json ├─ tsup.config.ts └─ vite.config.ts

依赖准备上,核心的大类如下:

  • TypeScript:提供类型系统和 tsc 命令。
  • Vite 以及对应框架插件,比如 Vue 项目用@vitejs/plugin-vue,React 项目用@vitejs/plugin-react
  • tsup:负责库构建。
  • 项目自己的业务依赖和开发依赖,建议放在 package.json 中明确区分。

安装方式很常规,直接使用 npm、pnpm 或 yarn 按项目规范安装即可。需要注意 Node 版本和包管理器版本,不同工具对运行环境的支持范围不同。如果原始材料没有给出明确版本,落地前要先确认依赖版本,不要拿旧版本硬套新配置。

3.2 tsconfig:先做类型检查,再做打包

类型检查是 TypeScript 项目的地基。很多人在 Vite 项目中把类型检查完全交给 Vite,这是不对的。Vite 用 esbuild 转译 TS 时只做语法转译,不会做完整的类型检查。也就是说,只要语法合法,即使类型有问题也能跑起来。

所以 tsconfig 至少要包含以下关键点:

{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "isolatedModules": true, "declaration": true, "baseUrl": ".", "paths": { "@/*": ["src/*"] }, "outDir": "dist" }, "include": ["src"] }

几个容易踩坑的点:

moduleResolution设为Bundler是因为 Vite、tsup 这类打包器使用 ESM 解析逻辑,它比Node更贴近实际运行环境。isolatedModules启用后,要求每个文件都能被单独转译,这比较符合 esbuild 的单文件转译模式。strict建议一直开着,它会在编译阶段拦截大量低级错误。

至于热词里经常出现的TS interfaceTS partialTS 封装 axios 设置响应返回类型,其实都指向同一个观点:类型定义是团队的约定文档,而不是装饰。一个项目想要长期维护,首先要让npm run typecheck成为提交代码之前必跑的检查项。

3.3 tsup 配置:库构建优先

tsup 的魅力在于默认配置足够聪明,你需要关心的字段不多。下面是一个常见的库构建配置:

import { defineConfig } from 'tsup' export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], dts: true, sourcemap: true, clean: true, splitting: false, treeshake: true, external: ['vue', 'react'], })

逐项解释一下:

  • entry:库入口文件,通常是你希望对外暴露的公共 API。
  • format:输出 ESM 和 CJS 两种格式。这样既支持现代构建工具,也能兼容老式 Node 项目。
  • dts:生成.d.ts类型声明文件。这一步对库发布来说很重要,没有类型声明,使用方在 TS 项目里会非常痛苦。
  • sourcemap:生成 sourcemap,方便使用方调试库代码。
  • clean:每次构建前清空输出目录,避免旧文件残留。
  • splitting:库构建时一般关闭代码分割,避免产物碎片化。
  • external:把 vue、react 这类框架依赖标记为外部依赖,不打包进产物,由使用方项目自己提供。

注意:external不是在配置里随便列两个包名就完事。你要先想清楚,哪些依赖应该打进产物,哪些应该交给使用方。打包进产物会让库体积变大,也容易造成多实例问题;不打包则会要求使用方必须安装对应依赖。

在具体项目里,如果你还负责工具函数或接口封装,可以给每个包单独维护一个 tsup 配置,甚至用多入口一次构建多个产物。但不要一上来就把所有模块塞进同一个入口,先保持入口稳定,再逐步扩展。

3.4 Vite 配置:应用构建的核心

Vite 配置更偏应用侧。以一个 Vue 项目为例,常见配置可以长这样:

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { fileURLToPath, URL } from 'node:url' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, server: { port: 5173, proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true } } }, build: { outDir: 'dist', sourcemap: true } })

这里要重点理解两个部分。

resolve.alias决定了代码里的@/components/xxx指向哪里。它必须和 tsconfig 里的paths保持一致。如果 tsconfig 里配了@/*,但 Vite 里没配,开发时也许能通过,但类型检查和构建时可能就找不到模块。保持两边一致,是减少配置冲突的关键。

server.proxy解决了开发阶段的接口跨域和代理问题。它把前端请求转发到后端服务,从而让浏览器认为所有请求都来自同一个源。具体到某个/api/form/list请求失败时,往往不是 Vite 配置本身的问题,而是 target 指向的服务不可用、路径没有正确 rewrite、或者后端 CORS 策略太严格。

3.5 从单命令到开发、构建、类型检查、产出的闭环

配置好之后,你需要的不是一个命令,而是一组命令,形成闭环:

# 类型检查 npm run typecheck # 开发环境 npm run dev # 应用构建 npm run build # 库构建 npm run build:lib

如果项目把类型检查放在npm run build之前,那 Vite 的打包就不会被类型错误悄悄带过。一个更稳的流程是:

  1. 先跑 typecheck,捕获类型问题。
  2. 再跑单元测试或 lint,保证逻辑和规范。
  3. 然后分别跑 build 和 build:lib,验证应用产物和库产物都正常。
  4. 最后检查 dist 目录里的文件名、sourcemap、声明文件是否齐全。

这一步看起来简单,但它决定了你的构建体系是“能跑”还是“可维护”。

4. Rolldown 的正确打开方式:实验性内核怎么理解、怎么试

4.1 为什么需要 Rust 重写打包内核

Rolldown 出现之前,前端社区对构建性能的追求已经分成了两条路线:一条是 esbuild 的“尽可能快”,另一条是 Rollup 的“尽可能符合生态”。esbuild 很快,但插件模型和产物控制比 Rollup 弱;Rollup 生态成熟,但 JavaScript 实现的性能在大型项目上有瓶颈。

Rolldown 想同时拿到两者的优点:用 Rust 提供高性能,同时保持 Rollup 兼容的 API,让大量现有插件不需要重写就能继续使用。这个方向一旦成立,Vite 的双引擎问题就会从根上解决。更重要的是,它把“构建工具”这件事从配置竞争提高到了“内核性能”竞争的层面。

4.2 在 Vite 中切换 Rolldown 的试验路径

因为 Rolldown 仍处于快速迭代阶段,不同版本入口和启用方式可能都不一样,所以我不在这里写死命令。更稳妥的做法是,把它当作一个实验分支来评估。

一个通用试验路径:

  1. 复制一份当前项目,或者新建一个空项目,不要直接改生产分支。
  2. 查看 Vite 和 Rolldown 官方文档、发布说明,确认当前版本推荐的启用方式。
  3. 在最小范围内验证插件兼容性。先跑通最简单的页面,再逐步加组件库、路由、状态管理、接口代理。
  4. 对比开发启动时间、热更新时间、生产构建时间和产物大小,记录数据。

在真实评估过程中,你会很快发现哪些插件和 Rolldown 有兼容问题,哪些构建行为发生了变化。这类信息比看任何评测文章都有价值。

注意:不要因为 Rolldown 性能数据亮眼,就直接把它引入重要生产环境。它更像是一辆性能很强的工程样车,适合在测试赛道里充分验证,不适合第一天就开着它上高速。

4.3 用 Rolldown 之前的边界检查

如果你想在项目里引入 Rolldown,建议先回答这几个问题:

  • 你的项目版本和依赖版本是否支持当前 Rolldown 的启用方式?
  • 你依赖的 Vite 插件是否都兼容 Rolldown 的插件模型?
  • 项目的开发构建和生产构建是否都跑过一遍完整验证?
  • 有没有做性能对比和产物差异对比?
  • 万一出现严重问题,回退到 Rollup 或 esbuild 的路径是否顺畅?

如果有一个问题回答不了,就不要把它推向生产。用工具不是为了追踪最新版本,而是为了获得稳定可控的交付流程。

4.4 现在不建议做的几件事

以目前的成熟度,我不建议做下面几件事:

不建议把 Rolldown 直接作为默认工具写进新项目模板,除非你的团队愿意持续处理版本变化。不建议为了兼容 Rolldown 去改造现有插件链,这等于把迁移成本提前支付给了还不稳定的底层。不建议只因为 Rolldown 性能高就忽略构建结果差异,性能不是衡量构建工具的唯一指标。

这一章并不是否定 Rolldown,而是强调边界。工具越靠近底层,越需要谨慎评估。

5. 从 Webpack 迁移的实操路线:先抽层,再接管,最后换核

5.1 第一步:把可复用代码用 tsup 抽成独立包

从 Webpack 项目迁到新组合,最大的风险是“一刀切”。正确做法是先抽层。

先找出项目里可以被独立复用的部分:工具函数、通用组件、类型定义、请求封装。把它们放到独立目录或独立包中,用 tsup 打包。这样带来的第一个好处是,这些代码不再被应用构建捆绑,可以单独测试、单独发布。第二个好处是,后续应用迁移 Vite 时,不需要处理这部分复杂依赖。

这个阶段最容易遇到的问题是多包之间的依赖关系。如果 A 包依赖 B 包,并且通过相对路径直接引用 B 包源码,那再好的工具方案都会变得很脆弱。建议先明确包的对外入口,让包之间只通过入口文件依赖。

5.2 第二步:用 Vite 接管应用开发服务器和构建

抽离出可复用代码后,下一步是让应用开发从 Webpack 切到 Vite。

这一步不用追求一步到位。可以先把开发服务器切到 Vite,保留旧的 Webpack 构建作为发布构建,用一段时间对比差异。开发阶段主要关注:热更新是否正常、接口代理是否一致、环境变量是否完整、静态资源是否符合预期。如果开发体验稳定,再逐步把生产构建也切换过去。

这里要特别注意环境变量的替换规则。Webpack 里可能用process.env.NODE_ENV或自定义插件注入变量,Vite 则默认通过import.meta.env暴露变量,并用loadEnv读取.env文件。迁移时需要把老的环境变量格式梳理一遍,避免构建后出现 undefined。

5.3 第三步:评估 Rolldown 替换时机

当前两步都稳定之后,再考虑 Rolldown。

评估的关键时刻是:你的 Vite 插件生态已经稳定,构建产物确认没有异常,团队对 Vite 的配置和维护已经有足够经验。此时引入 Rolldown,主要目的是解决你确实遇到的构建瓶颈,而不是为了追新。没有明确瓶颈,就保持现状。

Rolldown 的替换时机不是由技术热度决定的,而是由稳定性和收益共同决定的。如果现有方案已经能让你把时间和精力放在业务上,那它就是一个好方案。

5.4 一份迁移检查清单

迁移到新构建体系之前,建议把这张检查清单过一遍。下面这些项是我在多个项目里都会确认的内容:

检查项需要确认的问题
依赖版本Node 版本、包管理器版本、Vite/tsup/Rolldown 版本是否兼容
入口与出口应用入口、库入口、输出目录和文件名是否清晰
环境变量所有process.env.env变量是否迁移到import.meta.env或统一配置
静态资源public 目录内容是否完整,资源路径是否发生变化
代理规则开发代理是否与后端接口地址匹配,是否启用了 rewrite
插件替代Webpack loader 和 plugin 是否找到 Vite/Rolldown 对应方案
产物清理是否清空旧 dist,避免旧文件与新文件混在一起
类型声明库产物是否生成 d.ts,应用类型检查是否独立执行
构建缓存CI 和本地构建缓存是否清掉,避免旧缓存干扰
回归验证关键页面、接口、鉴权、路由是否全部走一遍

还有一个容易忽略的细节:Webpack 时代很多团队会配置注释清除或代码压缩相关的优化项,比如terserformat.commentsoptimization.minimizer。切到 Vite 后,注释清理和压缩策略是由 Vite 自身或其生成的底层配置决定的,方法和 Webpack 完全不同。迁移时要主动检查产物里是否保留了不该保留的注释、签名或调试信息,不能默认“新工具一定会做”。

注意:迁移过程中,尽量把“工具替换”和“业务重构”分开。不要一边换构建工具,一边改业务模块结构。两件事同时发生时,你很难判断问题来自工具还是来自业务改造。

6. 高频故障排查链路:三个真实报错,一层一层查

6.1 问题一:Cannot find package 'vite'

我看到这个报错出现在很多新手项目里。现象是运行npm run dev时,Node 提示找不到 vite 包,有时还带着imported from的路径。

先别急着重装依赖。排查顺序应该是:

  1. 打开 package.json,确认 vite 是否真的出现在 devDependencies 或 dependencies 里。
  2. 检查当前目录位置,确认你是在项目根目录运行的命令,而不是子目录。
  3. 检查 node_modules 里是否存在 vite 目录。如果存在,检查版本是否与 package.json 声明一致。
  4. 如果使用 pnpm,还要确认是否因为工作区 hoisting 导致依赖被安装到了根目录,而子项目访问不到。
  5. 确认没有 lockfile 错乱后,再决定是否删除 node_modules 和 lockfile 重新安装。

最忌讳的是直接运行npm install vite,它可能把 vite 装到不正确的层级,或者安装了错误版本,反而把问题弄复杂。依赖问题要先看“依赖应该在哪里”,再看“实际在哪里”,最后才动手调整。

6.2 问题二:[vite] http proxy error

这个报错在开发环境里很常见。比如/api/form/list?page=1&pagesize=10请求代理失败。看到http proxy error时,首先要意识到,它通常不是 Vite 配置写错,而是代理链路里某个环节没通。

按下面几步排查:

  1. 先确认代理目标服务是否在运行。可以直接用 curl 请求http://localhost:3000/api/form/list,看后端有没有响应。
  2. 检查 vite.config.ts 里的proxy.target是否正确,端口是否写错。
  3. 检查是否需要 rewrite 路径。如果后端接口不带/api前缀,就需要把前缀去掉。
  4. 检查changeOrigin是否开启,尤其是后端服务对 Host 头有校验时。
  5. 检查本地是否使用了localhost,而代理目标是 IPv6 地址或特定域名,解析可能存在差异。
  6. 可以开启构建工具的调试日志,观察代理请求实际发到了哪里。

这类问题影响面很大,但定位路径其实很固定:先确认目标服务,再确认代理规则,最后才怀疑工具本身。

6.3 问题三:public 目录与旧构建配置冲突

有一个常见提示是content not from webpack is served from public,这是 Webpack dev server 对 public 目录内容的说明。如果你在新项目里仍然看到类似信息,说明你可能还跑在旧构建体系下,或者旧构建脚本没有真正被替换。

另一个常被忽略的问题是,一个 dist 目录同时被 Webpack 和 Vite 写入。旧脚本还在跑构建,新脚本也在写产物,最后目录里的文件新旧混杂,很容易出现“新代码没生效”的错觉。

遇到这种情况,先关闭所有构建进程,清空 dist 目录,再确认当前 dev 和 build 命令实际执行的是哪个配置文件。检查 package.json 里的 scripts,检查有没有残余的 webpack.config.js 或老启动脚本。public 目录本身的处理逻辑在 Vite 里比较清晰:所有放在 public 下的文件都会原样复制到构建输出根目录,并且放在 public 之外的静态资源通过 import 或 URL 引用。迁移时要注意路径变化,尤其是 favicon、page 模板这类非 JS 资源。

6.4 通用排查顺序表

把上面的经验收拢成一张通用排查顺序表,以后遇到“构建工具行为异常”时,可以按这个顺序走:

阶段要做的检查典型问题
现象到底报什么错、卡在哪里、输出什么报错信息被忽略,直接猜配置
输入入口文件、路径、编码、格式是否正常文件路径大小写、文件损坏、编码不一致
环境Node、包管理器、依赖位置、版本依赖安装层级错误、锁文件错乱
配置入口、出口、别名、代理、环境变量别名不一致、代理 target 错、环境变量缺失
资源public、静态文件、构建缓存旧资源残留、缓存干扰
工具边界插件兼容、已知缺陷、版本限制插件不支持新版本、实验性功能不稳定

多数“诡异”问题,都能在输入或环境环节找到原因。别一上来就怀疑工具能力不够。

回到最初那个团队的问题,我的建议其实很简单:先在一个独立分支或新项目里把 tsup + Vite 的组合跑通,再思考是不是真要引入 Rolldown。如果你发现开发链路变短了、构建行为变清晰了、产物结构变稳定了,那这次工具更新就算成功。真正值得长期关注的不是“用上了某个新打包器”,而是你是否有能力控制构建流程的每一步。工具总在迭代,但“先跑通、再分流、再优化”的处理方法,才是这一类方案留给你最持久的东西。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 10:34:19

安检X光目标检测数据集:10类物品YOLOV5训练实践

简介:本资源是面向计算机视觉初学者与安防智能检测开发者的目标检测专用数据集,聚焦X光安检场景下的包内违禁/常见物品识别任务,直接支持YOLOv5等主流模型训练与验证。数据集严格按YOLOv5目录结构组织,含训练集2880张RGB图像&…

作者头像 李华
网站建设 2026/8/31 10:32:36

GPU Driven Rendering:Compute Shader实现细节全解析

上一篇讲了原理和架构,这一篇我们撸起袖子,把每个环节的Compute Shader代码拆开来看,包括数据布局、裁剪算法、Hi-Z生成、Indirect参数写入、Meshlet裁剪等核心实现。 一、整体Pipeline编排 先看整体的Dispatch顺序,这是理解后面所有代码的地图: Frame流程: ┌────…

作者头像 李华
网站建设 2026/8/31 10:32:24

TVA具身智能架构:面向开放场景的开放词汇目标检测

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”或“TVA视觉智能体”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积…

作者头像 李华
网站建设 2026/8/31 10:32:04

Claude API生产环境接入指南:模型选型、连接异常与工程实践

最近不少同学在技术群里讨论 Anthropic,但问题已经从“Claude 又发布了什么新模型”,慢慢变成了“Claude API 到底能不能进生产环境”“接入成本高不高”“报错 failed to connect to api.anthropic.com 应该怎么查”。问题方向的变化,说明…

作者头像 李华