← 所有文章

无构建宣言:不用打包工具直接发布

以下内容并非要说服您放弃构建工具,而是记录放弃之后会发生什么。

blakecrosley.com 运行 FastAPI + Jinja2 + HTMX + Alpine.js + 纯CSS。没有webpack,没有Vite,没有Rollup,没有TypeScript编译器,没有Babel,没有PostCSS,没有Tailwind,没有package.json,没有node_modules/。该站点提供33篇博客文章、14个交互式JavaScript组件、20份指南、九种语言翻译,并在Lighthouse上获得100/100/100/100的满分

摘要

HTMX社区不缺倡导者,缺的是证据。这里的数据来自一个真实的生产站点——拥有大量内容、交互功能和国际化支持,且完全没有使用任何构建工具。取舍是诚实的,结论也是有限定的:对于内容驱动型站点,由独立开发者或小团队维护时,构建工具解决的是您并不存在的问题,同时制造您确实会遇到的问题。对于拥有共享组件库和设计系统包的大型团队,构建工具的复杂性是值得的。这条边界比社区讨论所暗示的要清晰得多。


技术栈

Backend:    FastAPI + Jinja2 (server-rendered HTML)
Frontend:   HTMX + Alpine.js + Bootstrap 5 (CDN)
Styles:     Plain CSS with custom properties
JavaScript: Vanilla JS, IIFE-scoped per component
Deployment: Railway (git push → live)
CDN:        Cloudflare (caching, Workers, D1)

无需转译,无需摇树优化,无需热模块替换,无需Source Map。您写的JavaScript就是最终发布的JavaScript。


数据

以下是真实指标,不是估算值:

指标 blakecrosley.com 典型Next.js项目(作者估算)1
依赖项 18个Python包 300+个npm包
构建配置文件 0 5-8个(next.config、tsconfig、postcss、tailwind、eslint、babel等)
node_modules/大小 不存在 150-400 MB
安装时间 pip install -r requirements.txt:8秒 npm install:30-90秒
构建步骤 next build:15-60秒
部署流水线 git push → 约40秒上线 git push → 安装 → 构建 → 部署:2-5分钟
CSS文件 14个文件,10,300行(纯CSS) 由Tailwind/Sass生成,输出大小不定
JS文件 33个文件,10,061行(人类可读) 打包、压缩、分块:生产环境中不可读
Lighthouse性能分 100 不定(未经优化通常在70-90之间)

这18个Python包包括FastAPI、Jinja2、Pydantic、SQLAlchemy和其他14个。没有一个是构建工具,没有一个是编译器,没有一个是打包器。2


您会失去什么

诚实要求我们列出真实的代价。这些代价确实存在。

没有TypeScript。 本项目中每个.js文件都是原生JavaScript。测试和Claude Code的分析来捕获类型错误,而非编译器。这种方式对独立开发者有效,但对一个10人团队跨模块共享组件接口的场景则行不通。

没有热模块替换。 当我修改一个CSS文件时,需要手动刷新浏览器。HTMX的hx-boost使导航足够快,完全刷新尚可接受。但在一个每30秒就要迭代视觉细节的项目中,HMR确实能节省可观的时间。

没有摇树优化。 我写的每一个字节的JavaScript都会发送到浏览器。我无法只从工具库中引入单个函数而不附带整个文件。这种约束迫使代码保持纪律性:小而专注的文件,而非庞大的工具模块。14个交互组件平均每个300-700行,因为它们必须自包含。3

没有来自npm的组件库。 没有Radix,没有shadcn/ui,没有Headless UI。每个交互元素(Boids模拟汉明码可视化器共识模拟器)都是手工构建的。这种方式之所以可行,是因为交互组件服务于特定的教学目的,而非通用UI模式。

没有来自npm的设计系统令牌。 我的设计系统完全依赖CSS自定义属性。我无法将其作为包导入到其他项目中。对于单站点系统,这种约束是可接受的;对于多产品组织,则不可接受。

以上五项取舍对于一个由单人开发者维护的内容驱动型站点来说是可接受的。但对于一个拥有15人工程团队的SaaS产品来说则不可接受。


您会获得什么

零构建失败。 部署流水线就是git push。不会因为对等依赖冲突导致npm install失败,不会因为我没碰过的文件中的TypeScript错误导致next build失败,不会因为Dependabot的PR升级了某个传递依赖而破坏构建。4

用”查看源代码”来调试。 浏览器中运行的JavaScript就是我写的JavaScript。不需要Source Map,不需要从编译输出映射回源代码。当生产环境出现Bug时,我直接阅读部署的文件。

本地即时启动。 uvicorn app.main:app --reload在2秒内启动。不需要npm run dev先安装、编译、打包,然后才能看到页面。

零Dependabot噪音。 没有package-lock.json意味着没有每周更新semveransi-regexglob-parent的PR——这些我从未直接引入、却在依赖树中三层深处的包。

面向未来。 这个站点10年后依然能正常运行。HTML就是HTML,CSS就是CSS,JavaScript就是JavaScript。没有Webpack 4 → 5迁移,没有Create React App弃用,没有Next.js App Router迁移。平台本身就是标准。5


HTMX作为架构

HTMX的讨论焦点通常集中在语法上:hx-gethx-swaphx-target。这个视角是错误的。其架构层面的洞见在于服务器渲染的HTML就是API

在传统SPA中:

Browser → fetch('/api/users') → JSON → React renders HTML → DOM update

使用HTMX:

Browser → GET /users (hx-get) → Server renders HTML fragment → DOM swap

服务器返回最终表示。没有客户端状态管理,没有序列化/反序列化,没有hydration。Jinja2模板就是组件。FastAPI端点就是API。只有一层,而非三层。6

这个模式直接映射到复利工程原则:每个基础设施部件只做一件事,各部件之间组合而不干扰。模板渲染HTML,路由返回它,HTMX将其替换到页面中。没有构建步骤来协调这些部件,因为根本不需要协调。


纯CSS就够了

我的设计系统使用10个颜色令牌、13个字体比例阶梯和8个间距值——全部是CSS自定义属性:

:root {
  --color-bg-dark:        #000000;
  --color-text-primary:   #ffffff;
  --color-text-secondary: rgba(255,255,255,0.65);
  --spacing-sm:           1rem;
  --spacing-md:           1.5rem;
  --font-size-lg:         1.25rem;
}

没有Sass编译步骤,没有Tailwind配置生成工具类,没有PostCSS插件转换自定义语法。浏览器直接读取这些值。7

本站美学与粗野主义的视觉风格(纯黑底上的白色文字配合四级透明度)正是源于这种约束。当您无法使用丰富的色彩时,排版承载层次。当您无法使用组件阴影时,留白创造结构。约束本身就是设计。8


CLS之旅

Lighthouse之旅暴露了无构建方案的一个真实成本:关键CSS提取需要自定义Python脚本。在Next.js项目中,框架会自动处理这一点。

具体的Bug:一个移动端媒体查询覆盖了一个CSS自定义属性(--gutter: 48px--gutter: 24px)。关键CSS包含了桌面端的值,但没有包含移动端的覆盖。在移动设备上,Hero区域先以48px内边距渲染,然后在完整样式表加载后变为24px,产生了0.493的CLS。

修复只用了12行Python代码。排查花了三个小时。构建工具会自动处理这个问题。

诚实的核算:构建工具将您可以手动完成的事情自动化了,但手动方案在出问题时需要付出调试时间。问题在于自动化的成本(复杂性、依赖项、构建失败、迁移折腾)是否超过了手动成本(偶尔的调试会话)。

对于本站来说,手动成本更低。三年,一个CLS Bug,三个小时的调试。替代方案(维护构建流水线)在依赖更新、破坏性变更和配置维护上消耗的累计时间会更多。


何时不应使用此方案

无构建方案不适用于以下场景:

大型团队。 TypeScript的价值随团队规模增长。9当10个开发者共享组件接口时,编译时类型检查能防止那些运行时测试发现得太晚的集成Bug。独立开发者可以将整个系统装在脑中,团队则做不到。

设计系统包。 如果多个产品消费您的设计系统,它需要成为一个带有适当版本管理、摇树优化和构建流水线的npm包。单个样式表中的CSS自定义属性无法跨仓库组合。

复杂客户端状态。 如果您的应用有丰富的客户端状态(拖拽界面、实时协作、离线优先数据),那么像React或Svelte这样的框架的复杂性是值得的。HTMX用服务器往返替代客户端状态,在延迟敏感的场景下就会力不从心。

npm生态系统库。 如果您需要Radix基元、Framer Motion或TanStack Query,您就需要构建流水线。这三者都假定存在打包器。不用打包器来使用它们,从痛苦到不可能不等。

边界比社区讨论所暗示的要简单得多:如果您的应用主要是由服务器渲染的内容,构建工具就是开销;如果您的应用主要是由客户端管理的状态,构建工具就是基础设施。


关键要点

对于独立开发者和小团队:

  • 证据是这个站点本身,而非论点。 blakecrosley.com以零构建工具和Lighthouse满分提供33篇文章、14个交互组件、20份指南和九种语言支持。这些数据是可验证的。

  • 无构建方案的真实成本是偶尔的调试。 CLS Bug花了三个小时修复。构建工具会自动处理它。但三年来,累计调试时间远少于构建流水线所需的累计维护时间。

  • 约束产生设计。 没有色彩迫使排版承载层次。没有构建工具迫使JavaScript保持简单和自包含。最好的约束是在需要之前就主动选择的约束。

对于评估技术栈的团队负责人:

  • 构建工具解决的是团队规模的问题。 TypeScript、摇树优化和组件库在多个开发者共享接口时,其复杂性才值得。一个构建内容驱动型站点的独立开发者并没有这些问题。

  • HTMX真正的贡献在于架构层面。 服务器渲染的HTML作为API,消除了客户端状态管理、序列化和hydration。语法是次要的,洞见才是核心。


本文横跨博客的设计工程板块。设计决策详见美学与粗野主义创业公司的设计系统字体比例。工程数据详见Lighthouse满分复利工程氛围编程一文探讨了这种理念在AI辅助开发中的适用场景。



  1. “典型Next.js项目”一列反映了作者在5个以上Next.js项目(2021-2024年)中的经验和社区报告的常见数据。具体数字(300+个包、150-400 MB的node_modules)与Node.js社区中常见的报告一致。各项目差异较大。这些数字是作者的估算,非独立验证的基准测试。 

  2. 截至2026年2月的完整依赖列表:fastapi、uvicorn、starlette、pydantic、pydantic-settings、jinja2、markdown、pygments、beautifulsoup4、lxml、nh3、resend、python-dotenv、python-multipart、slowapi、httpx、sqlalchemy、analytics-941。零个是构建工具,零个是编译器,零个是打包器。 

  3. 组件平均大小(300-700行)测量自截至2026年2月/static/js/中的14个交互式JS文件。大小范围从240行(signal-calculator.js)到690行(boids-simulation.js)。 

  4. 根据作者维护Next.js项目的经验,JavaScript生态系统每月为一个活跃项目生成15-25个Dependabot PR,其中大多数更新的是开发者从未直接引入的传递依赖。该数据是直接观察的估算值,非独立验证的基准测试。 

  5. Web平台(HTML、CSS、JavaScript)已保持30年的向后兼容性。1996年的页面在Chrome 2026中仍可渲染。Tim Berners-Lee将此表述为一项设计原则:”浏览器应该向后兼容,即能够读取早期版本的语言。”参见w3.org/DesignIssues/Principles。 

  6. HTMX的创建者Carson Gross将此表述为”超媒体作为应用状态的引擎”(HATEOAS)。参见htmx.org essays以及Gross、Stepinski和Cotter合著的《Hypermedia Systems》(2023年):hypermedia.systems。 

  7. CSS自定义属性(CSS变量)在全球97%以上的浏览器中得到支持。来源:caniuse.com/css-variables。使用它们不需要任何编译步骤。 

  8. “约束作为设计工具”这一原则由来已久。Charles Eames说过:”设计在很大程度上取决于约束。”电影界的Dogme 95运动证明,移除工具(不用人工照明、不做后期制作)产生的是更诚实的叙事,而非更贫乏的叙事。参见en.wikipedia.org/wiki/Dogme_95。 

  9. 2024年Stack Overflow开发者调查发现,TypeScript是第四大最受欢迎的语言,也是最受欢迎的JavaScript超集,其采用率与团队规模成正比。参见survey.stackoverflow.co/2024/。