STEP 1 · 08-13先有清单,没有打包
产品必须同时支持「单文件便携 HTML」和「localhost 服务」,且用户机器没有 Node——第一版刻意不用打包器。
约束:便携 HTML 零 Node 可跑这批代码从来没有被「重写」过——只是被反复地切割和包装,构建系统再把碎片按原始顺序拼回去。一张图看三个月:
切割只动「文件的边界」,不动「执行的顺序」——清单顺序就是当年大文件里的段落顺序,所以全局行为一天都没变过。这就是全部 trick。
项目带着 web/editor.js 和几个卫星脚本问世。没有模块系统,靠 script 加载顺序保证「用之前先定义」;edit.py 把脚本按顺序内联进单文件 HTML,让没有 Node 的机器也能跑。
企划案定调:不换框架、不引打包器、不改任何行为。埋下两块基石:editor-scripts.txt 有序清单 + window.MAWE 注册表。企划案写完后的一个多月功能照常往大文件堆,开拆时已经 23,273 行。
AST 工具按「语句」为单位切割(重复声明检查、隐式全局扫描一整套),方案写成 JSON 规格再机械重放。语句逐字保留,按职责分目录。切完 editor.js 不复存在。
「工厂形状」的文件从自己调 MAWE.register 机械改写成 export function,登记动作由构建器统一生成(§02 的 factoryN)。
压缩产物不进仓库:启动时校验哈希、过期自动重建。仓库不被压缩代码刷屏,发布包仍零 Node 依赖。
机械迁移实验(红/绿两轮)产出 G00–G17 批次计划;G01 落地第一条生产消费边:editor-utils 转 init 模块,lrc 改用真 import。
页面加载的从来不是 192 个散文件,而是构建器现场「手写」的一个入口文件,交给 esbuild 打包:
factoryN 是什么?编号 = 模块在登记表里的数组下标(lrc 第 25 → factory25)。必须起别名,因为 32 个工厂都叫 createUtilsModule、25 个都叫 createWaveformModule,同名 import 无法共存。这个名字只活在构建入口里,压缩后连名字都没了。
// 64 个登记模块全部走真 ESM import;classic 粘进同一个函数作用域 import { createUtilsModule as factory25 } from 'maw-factory:shared/utils/lrc.js'; function initializeLegacy() { window.MAWE.register('utils-lrc', factory25); // 工厂:只登记,不执行 factory36(); // init:在清单位次直接调用 // …128 个 classic 文件的源码逐字粘贴…… } initializeLegacy();
生产流水线管「模块怎么找到彼此」,装配现场管「什么时刻执行什么」。
六张词卡(编号对应上图 ①–⑥):
「名字 → 工厂函数」的 Map。register 存、resolve 取,过渡期用它替代「直接叫别的文件里的名字」。
被 export function 包了一层的原代码,函数体一字未改;调用它才产出 API。构建器强制「恰好一个导出函数、零求值副作用」。
传给工厂的越滚越大的对象,替代旧全局作用域。工厂拿到「到目前为止的袋子」,返回值并回去——顺序因此是硬约束。
旧世界留给消费者的总服务台:304 个条目的巨型对象。名字不变、成员位置不变,背后组装方式全换——62 个消费者零修改。
把 DOM 事件连到逻辑上的纯粘合代码(39 个 editor-wiring-*.js),只在加载时执行 addEventListener,自己几乎不定义逻辑。
「在清单位次被执行的真 ESM」。工厂只会登记不会执行,必须在正确时刻运行的组装逻辑就用 init 表达:构建器在原位调用它。
不是野心,是三步各自回应一个具体约束:
产品必须同时支持「单文件便携 HTML」和「localhost 服务」,且用户机器没有 Node——第一版刻意不用打包器。
约束:便携 HTML 零 Node 可跑文件数到 192、出现真 import 依赖图。企划案早留了口子:「若无构建装配成为主要维护成本,可单独评估 esbuild」。
约束:与「是否用 React」分开决策源码仓库不被压缩产物刷屏,发布包自带产物。代价是「改了 web/ 必须重建」纪律与四层哈希新鲜度校验。
约束:源码 / 产物 / 发布链分层这些词只在迁移中间态里有意义——路线图的终点就是它们逐个消失:
迁移完成之后剩下的就是普通的 ESM 模块——现在的复杂度是施工脚手架,不是永久架构。想看其中一根线怎么换,去图解:一步迁移(以 LRC 为例)。