在 DSH 里开发插件最爽的方式是「动态插件」:即写即用、即时热更,特别适合迭代。但它有个致命短板——重启即失。我做的下载管理器一开始就是动态插件,每次重启都要重新加载,烦得不行。于是走上了「固化」之路,途中还让整个前端崩过一次。
什么是动态插件
动态插件是运行在沙箱里的一段代码,通过专用接口定义:定义即记录、运行即生效,还能热更新。开发体验一流,但一切副作用都随进程消失。想要「开机自启、重启自动加载」,就必须固化成正式包。
固化的标准姿势
固化其实不复杂,就是把动态代码变成一个本地包 + 一条启动配置:
node_modules/@local/my-plugin/ ← 固化包
├── package.json ← 声明入口与客户端入口
├── lib/
│ ├── index.js ← 主逻辑(服务端)
│ └── client.js ← 界面逻辑(浏览器端)
└── 配置注入 ← 在启动配置里挂载该插件
挂载后重启服务,插件随主程序自动加载,从此「固化」完成,再也不用手动恢复。
那次崩溃:沙箱全局的陷阱
第一次固化时,我直接把动态插件的代码原样搬进包——然后整个界面崩溃,报错 ReferenceError。排查后明白了:
坑动态代码里依赖的沙箱全局,固化环境里不存在
动态插件能用的某个专用方法,是沙箱专属的全局;固化后代码跑在正式环境,这个全局根本没被定义,一调用就 ReferenceError,直接带崩整个界面。
✅ 解法:固化版必须改用框架官方提供的注册接口——用 HTTP 端点注册替代沙箱方法,浏览器端用 fetch 访问端点替代专用调用通道。
这条经验让我之后写所有插件都先问一句:这段代码依赖的是「官方接口」还是「沙箱福利」?依赖沙箱福利的,固化必炸。
固化后的收益
- 重启自动加载:不用再手动恢复,开机即用。
- 稳定可靠:正式包有清晰的启动/停止生命周期,副作用可逆。
- 可发布:固化包可以打进仓库、一键安装,别人也能装。
版本迭代的哲学
我的下载管理器从动态版一路迭代到固化的 v18:每次升级都只动一处、验证一处。固化的价值不只是「重启不失」,而是让插件从一个试验品变成一件作品——能装、能卸、能分享。
动态是开发模式,固化是交付模式。开发时贪图热更的爽,交付时就要扛起稳定的责——两条路都要会走,才知道什么时候该切换。
想看固化后的成品?去插件页看 dsh-download-progress,它的完整进化史(含踩坑)都写在仓库里。