本节摘要:Solid 的工具链是"Vite 加一个插件"的单层结构:编译转换交给 Babel 系插件,打包交给 Vite;React 的工具链则是"转换器加打包器"的双层组合,且转换器选择多。本节给出两份可抄的配置,对照热更新行为与产物体积,帮你在迁移第一天就把地基铺对。
从 React 项目迁过来的第一疑问通常是:要不要换打包器?答案是好消息——不用。Solid 的开发体验建在 Vite 上,官方插件一条命令接入;React 社区如今也在向 Vite 靠拢,两边共用同一代构建底座,迁移的工程中断面比看起来小得多。
Solid 侧,Vite 配置:
// Vite 配置:一个插件搞定转换 import { defineConfig } from "vite"; import solid from "vite-plugin-solid"; export default defineConfig({ plugins: [solid()], build: { target: "esnext" }, });
配套的 TypeScript 配置要点:
{ "compilerOptions": { "jsx": "preserve", "jsxImportSource": "solid-js", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "types": ["vite/client"] } }
React 侧的等价物是"转换器加插件"两层:Vite 下用官方 React 插件(内部接 Babel 或 SWC 做快速刷新),TypeScript 指向 react 的 jsx 工厂。配置行数差不多,结构差异在语义:Solid 的插件不是语法糖转换器,而是第 3 章那套模板克隆产物的生成器——它决定编译目标,因此不可绕过、不可混用;React 的转换器只负责把 JSX 翻成工厂调用,运行时模型与它无关。这也是为什么两个框架的文件不能共享一个转换配置,混仓项目要按目录分开插件作用域。

开发期的体感差异集中在热更新。React 的快速刷新以组件为粒度:改组件代码,组件重新挂载,局部状态是否保留有精细规则。Solid 的热更新目前以模块为粒度:改动通常触发相关模块整体重载,组件内状态会重置——它保存的是"页面没整刷、滚动位置还在"的体验,但不是"表单填到一半代码改了状态还在"的体验。务实建议:表单类开发把草稿进 store 或本地存储(3.3 的原语正好复用),别依赖热更新保状态。这不是功能缺失,是细粒度模型的取舍——组件实例与状态在图上纠缠,安全热替换的边界比虚拟 DOM 模型更窄。
体积是 Solid 最直观的卖点:框架运行时内核在个位数 KB 量级(压缩后),一个路由级页面附带业务代码后的首屏脚本,通常比同复杂度 React 应用小一截。来源有两个:运行时本身小(没有协调器与调度器这两大件),以及编译产物里静态部分是模板字符串而非对象构造代码。要把话讲满:应用业务代码才是包体积大头,框架差异在中小型应用里可能是总量的两成,在巨型应用里摊薄——但它同时压低的是解析与执行时间,弱设备上的收益比数字更大。
⚠️ 两个常见配置坑:一是忘了把 TS 的 jsx 工厂指向 solid,类型检查走 React 语义,props 的只读约束与事件类型全部对不上;二是把 React 的 babel 插件配置带进混仓,两套转换互相覆盖。混仓迁移期,按目录拆 Vite 插件作用域是唯一稳妥解。
存量 React 仓库逐步引入 Solid 的团队,工具链上的第一个实战问题是两套转换共存。原则:按目录切作用域,绝不按文件类型切。Vite 插件支持传入过滤规则,把 Solid 插件限制在指定目录前缀内:
import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import solid from "vite-plugin-solid"; export default defineConfig({ plugins: [ react({ include: [/src\/legacy\/.*/] }), solid({ include: [/src\/solid\/.*/] }), ], });
两条配套纪律:目录边界即心智边界——solid 目录里的文件不引 React 组件、不引 hooks,代码评审照着目录红线查;共享层(工具函数、类型、样式)放两套目录都引得到的公共位置,样式与算法类依赖本就框架无关。这条切法比"文件级混用"安全一个数量级,因为转换器错了不是报错而是运行时行为诡异,文件级混用几乎必然踩中。
体积问题上 Solid 占优,但诊断习惯不能省。发版前看三样:入口块里有没有被意外打进的重依赖(图标库全量、日期库全 locale 是惯犯);路由级代码分割是否真的把工作台与营销页分开了(SolidStart 与路由器的懒加载原语负责切,构建报告负责验证);产物里有没有两份框架运行时(混仓期最容易发生,构建报告里运行时相关包出现两次就是信号)。三样都过,部署产物才算体检合格——这些检查与第 9 章的生产化清单首尾相接。
方向一致、深度不同。开发态产物保留更多可读信息,便于调试与热更新衔接;生产态产物会做模板预编译的极限压缩、静态属性的进一步内联、事件委托的集中化。对开发者的含义是:调试时看到的绑定结构与 3.1 教学示意一致即可,不必逐字符对齐生产产物;真正要"读产物"的场合(排查静默失效)在开发态做,结论对生产态同样成立。
工具链铺好了,下一节铺库——生态对照矩阵逐条赛道过一遍。