@lark-apaas/coding-miaoda-sandbox-skills 0.1.41 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: browser-compat
3
+ description: "Use when 应用在部分手机、部分浏览器或旧版本系统上白屏、打不开、样式错乱,而在电脑或其他设备上正常;或用户要求确认应用能否在某个浏览器版本上运行、调整打包目标 build.target。触发词:手机白屏, 部分手机打不开, 安卓打不开, 苹果手机打不开, 旧手机打不开, 旧手机样式错乱, 电脑正常手机白屏, 某些手机报 SyntaxError, 低版本浏览器, 浏览器兼容, 浏览器版本, iOS 15, Chrome 93, build.target, blank page on some phones, browser compatibility, old browser"
4
+ ---
5
+
6
+ # 浏览器兼容排查与修复
7
+
8
+ ## 铁律:没有真实版本,不构建、不扫描、不改配置
9
+
10
+ 验证只认出问题环境的**真实** UA,或用户明确给出的「浏览器 + 版本」。项目文档(如 AGENTS.md)、记忆、机型、系统版本、截图推测出来的版本都不算:拿推测的版本去扫描,结论没有意义,还会把后续判断带偏。
11
+
12
+ 还没有真实版本时只做一件事:把下面这段原样发给用户,然后结束本轮,不做其他分析。
13
+
14
+ > 需要出问题那台设备的浏览器信息,二选一发我:
15
+ >
16
+ > 1. 用 Chrome 打开的:地址栏输入 `chrome://version`,复制「用户代理」整行。
17
+ > 2. 在豆包、飞书、微信等 App 里打开的:在同一个 App 里打开任意一个显示「User-Agent」的网页(比如搜「UA 查询」),把那一整行复制或截图发我。
18
+ >
19
+ > iPhone 只需告诉我「设置 → 通用 → 关于本机」里的 iOS 版本。拿到之前我不会改任何配置。
20
+
21
+ ## 适用前提
22
+
23
+ - 同一个页面在部分设备或浏览器上异常、在其他设备上正常,或用户明确要求确认对某个浏览器版本的支持。所有设备都白屏、开发预览本身就白屏,多半是代码或构建问题,按常规方式看控制台和构建报错,不走本流程。
24
+ - 项目用 Vite 构建(根目录有 `vite.config.ts`)。不是 Vite 项目时本流程不适用,如实告诉用户。
25
+
26
+ ## 为什么要这样做
27
+
28
+ - 旧浏览器遇到不认识的 JS 语法(例如 `class` 里的 `static {}`),会在**解析阶段**直接报错,整份脚本不执行,表现就是白屏。
29
+ - 样式是另一层:不认识的 CSS 规则被整块丢弃。Tailwind v4 的样式几乎都包在 `@layer` 里,不支持它的浏览器能打开页面,但样式大面积缺失,这一层 `build.target` 修不了。
30
+ - 产物里有哪些语法取决于依赖(包括平台 SDK)**当前版本**的代码,会随升级变化。不要凭记忆判断「某个 SDK 支持到哪个版本」,每次都扫描实际产物。
31
+
32
+ ## 流程
33
+
34
+ 本 skill 在沙箱里的目录是 `.agent/skills/browser-compat/`;路径不同时以本文件所在目录为准。
35
+
36
+ ### 1. 拿到真实版本
37
+
38
+ 见上方铁律。脚本 `--browser` 接受完整 UA,或简写:`chrome 93`、`android 93`(安卓 Chrome 内核)、`webview 93`、`ios 15.4`、`safari 16`、`firefox 92`、`edge 90`、`samsung 14`。
39
+
40
+ ### 2. 在项目副本里构建
41
+
42
+ ```bash
43
+ node .agent/skills/browser-compat/scripts/check-browser-compat.mjs --prepare && (cd /tmp/browser-compat-debug/project && NODE_ENV=production npx vite build) > /tmp/browser-compat-debug/build.log 2>&1
44
+ ```
45
+
46
+ - 在项目根目录用 `run_in_background: true` 执行,之后用 `tail -n 20 /tmp/browser-compat-debug/build.log` 确认出现 `built in`。构建失败先按报错修好构建。
47
+ - `--prepare` 先确认排查目录是当前用户自己的真实目录(不是指向别处的符号链接),再把项目复制到 `/tmp/browser-compat-debug/project`:不复制 `node_modules`(用软链接指回项目)、`dist`、`.git`,每次都重新复制。它失败时会停下并说明原因,不要改用 `mkdir -p`、`cp` 绕过。
48
+ - 副本只用来构建。改代码、改配置都在项目里改,复验时重新执行这一步。
49
+ - 在副本里按项目自己的配置构建,不要加 `--outDir` 之类的参数:有的项目在构建插件里按固定路径整理、清理产物,改了输出目录不但构建失败,还会删掉项目里已有的产物。也不要在项目里构建:会改动发布流程和开发服务在用的 `dist/`(全栈应用的开发态页面就在 `dist/client/index.html`,覆盖它开发预览会挂掉)。
50
+ - 不用 `npm run build`:全栈应用会连服务端一起构建,服务端代码会混进扫描。
51
+ - `/tmp/browser-compat-debug/` 是本 skill 专用的排查目录,项目副本、构建日志、MDN 数据缓存都放这里。
52
+
53
+ ### 3. 用脚本验证
54
+
55
+ ```bash
56
+ node .agent/skills/browser-compat/scripts/check-browser-compat.mjs --browser "<真实 UA 或简写>" --dir /tmp/browser-compat-debug/project/dist
57
+ ```
58
+
59
+ 脚本对照 MDN 的浏览器兼容数据(运行时现查,首次运行需要能访问 npm 源)检查产物里的 JS 语法和 CSS。
60
+
61
+ | 退出码 | 含义 | 下一步 |
62
+ | ---- | ---- | ---- |
63
+ | 0 | 兼容 | **不要改打包配置**,转到下文「验证兼容但仍白屏」 |
64
+ | 1 | 有 JS 在该浏览器上无法解析,所在脚本整份失败 | 第 4 步 |
65
+ | 3 | JS 都能解析,但有打包配置修不了的问题(运行时正则报错、样式大面积缺失) | 如实告诉用户,不要自己写插件或补丁去改 |
66
+ | 2 | 无法判断(参数、网络、环境问题) | 看报错处理,不要改配置 |
67
+
68
+ 退出码不是 0 时,先读 [references/script-output.md](references/script-output.md),里面有每类输出的含义和处理方式。
69
+
70
+ ### 4. 修复:设置 build.target
71
+
72
+ 在 `vite.config.ts` 传给 `defineConfig` 的对象里加 `build.target`。preset 会把这份配置合并进最终配置,加上就生效;`defineConfig` 的导入和其他原有配置都保持不动。
73
+
74
+ ```ts
75
+ export default defineConfig({
76
+ build: {
77
+ target: ['chrome87', 'edge88', 'firefox78', 'safari14'],
78
+ },
79
+ // 原有配置保持不变
80
+ });
81
+ ```
82
+
83
+ - **默认用这组**(约等于 ES2020),产物体积大约只增加 1%。它只管打包产物里的 JS,样式和打包之外的脚本以脚本输出为准。
84
+ - **四个浏览器家族都要写**:只写一个家族时,其他家族还不支持的语法会原样保留。
85
+ - 用户浏览器比默认值还旧(比如 Chrome 80、iOS 13):把对应家族调到用户的版本,例如 `'chrome80'`、`'safari13'`。已有 `build.target` 时只下调需要的家族。
86
+ - 不要靠 `@vitejs/plugin-legacy` 或额外的 polyfill 解决语法问题:polyfill 补不了语法,plugin-legacy 只服务不支持 ES 模块的浏览器。
87
+
88
+ 改完用**同一个浏览器版本**重复第 2、3 步,复验结果怎么处理见 [references/script-output.md](references/script-output.md)。
89
+
90
+ ### 5. 交付
91
+
92
+ 1. 可以清理:`rm -rf /tmp/browser-compat-debug/project /tmp/browser-compat-debug/build.log`(MDN 缓存 `bcd/` 留着复用)。
93
+ 2. 提交改动,提交说明写清目的,例如「降低打包目标以兼容 Chrome 93」。
94
+ 3. **不要自行发布**:请用户点击发布,发布后在原设备上重新打开页面(App 内页面要完全关闭再打开)。
95
+
96
+ 回复用户时说清:原因(哪个语法、哪个文件、需要的版本与用户版本的对比)、改了什么、修复前后的验证结论、剩下的问题(复验不是 0 时如实说明,版本号只用脚本输出里的数字,不要说「升级到某版本就完全正常」)、下一步(发布并在原设备复测)。
97
+
98
+ ## 验证兼容但仍白屏
99
+
100
+ 按顺序排查,都不要改打包配置:
101
+
102
+ 1. **线上还是旧版本**:确认最近一次发布是否包含当前代码。
103
+ 2. **运行时报错**:请用户提供控制台报错(安卓用电脑 Chrome 的 `chrome://inspect`,iPhone 用 Mac Safari 的「开发」菜单)。脚本不检查内置 API(例如 `Promise.withResolvers` 在 iOS 17.4 以下没有),看到 `xxx is not a function` 时优先怀疑它。
104
+ 3. **其他原因**(接口失败、权限、网络):按常规方式排查。
105
+
106
+ ## Common Mistakes
107
+
108
+ | 错误 | 正确做法 |
109
+ | ---- | -------- |
110
+ | 用文档、记忆、机型推测的版本去扫描 | 只认真实 UA 或用户给的版本;没有就用模板问 |
111
+ | 没拿到版本先构建、先分析 | 先问,拿到再动手 |
112
+ | 所有设备都白屏也套用本流程 | 只有部分设备异常时才适用 |
113
+ | 在项目里构建、给 vite 加 `--outDir`,或用 `npm run build` | `--prepare` 后在副本里 `npx vite build`,检查 `/tmp/browser-compat-debug/project/dist` |
114
+ | `target` 只写报障浏览器那一个家族 | 四个家族都写 |
115
+ | 为语法问题装 plugin-legacy 或 polyfill | 语法问题靠 `build.target` |
116
+ | 降了 `build.target` 仍是 1,继续往下调 | 按 references 判断剩下的问题归属 |
117
+ | 复验不是 0 时笼统地说「修好了」 | 如实说明这台设备上还会有什么问题 |
118
+ | 在应用里手写插件改写 `@layer` | 如实告知,转平台处理或请用户升级浏览器 |
119
+ | 自己发布 | 请用户确认后发布 |
120
+ | 用 `run_skill` 调脚本 | 脚本没有可执行权限,用 `node <路径>` 运行 |
@@ -0,0 +1,55 @@
1
+ # 检查脚本的输出与处理
2
+
3
+ 检查脚本 `check-browser-compat.mjs` 的输出分【JS】【CSS】两段,最后一行是结论。退出码不是 0 时按下面对应的小节处理。
4
+
5
+ ## 退出码 1:有 JS 在该浏览器上无法解析
6
+
7
+ 【JS】段列出每种语法:MDN 条目名和说明、需要的版本、所在文件和代码片段。一般情况做 SKILL 第 4 步(设置 `build.target`)。两种特殊情况 `build.target` 修不了:
8
+
9
+ - 「在模块顶层构造的正则」:这个 `RegExp(…)` 在脚本加载时就执行,效果和解析失败一样。要改写正则或换依赖。
10
+ - 「该浏览器不支持 ES 模块」:Vite 产物在这个浏览器上整体不会执行。如实告诉用户需要升级浏览器。
11
+
12
+ ## 改完 build.target 后复验
13
+
14
+ 用同一个浏览器版本重新构建、重新检查:
15
+
16
+ - **退出码 0**:修好了。
17
+ - **退出码 3**:JS 都能解析了,剩下的按下文「退出码 3」处理。正则字面量降级后会被打包器改写成 `RegExp(…)`:在函数里的会从 1 变成 3,在模块顶层的仍然是 1。这只是把报错从解析期推迟到执行期,正则本身还是不被支持,用户自己代码里的正则要改写到复验为 0。
18
+ - **仍然是 1**:对比修复前后的输出,修复后还在的问题 `build.target` 管不到,不要继续往下调:
19
+ - 在 `public/` 拷贝来的文件、或你写在 `index.html` 的内联脚本里:改对应源文件的写法。
20
+ - 在平台单独构建的文件(例如 `polyfills.js`)或平台注入的内联脚本里:应用里改不了,如实告诉用户并转平台处理。单独用 `<script>` 引入、不被别的脚本 `import` 的文件解析失败只影响它自己(比如 polyfills 失效),不一定白屏。
21
+ - 在打包产物里还在,或者是「在模块顶层构造的正则」:打包器降不了,要改源码写法;在依赖里自己改不了时,如实告诉用户并转人工处理。
22
+
23
+ 剩下的都属于这几类时可以交付,但要在回复里逐条说明。
24
+
25
+ ## 退出码 3:JS 都能解析,但有打包配置修不了的问题
26
+
27
+ 结论会写明是哪一种。都**不要**在应用里自己写插件、补丁去改。
28
+
29
+ - **函数里构造的正则**:`RegExp(…)` 用了该浏览器不支持的正则语法,执行到这段代码时报错。如果这个函数在页面加载过程中就会被调用(组件渲染、依赖初始化),页面仍会白屏,所以不能据此说白屏已修好。按文件和代码片段找到它属于哪个功能:
30
+ - 在用户自己的代码里:改写这个正则,改完复验到 0。
31
+ - 在依赖里(常见于 Markdown 渲染一类的库):如实告诉用户哪个功能会出错、页面可能仍白屏,必须在原设备复测确认。
32
+ - **样式会被丢弃**:超过一成时结论为 3,常见原因是 Tailwind v4 的样式几乎都包在 `@layer` 里。如实告诉用户这台设备上样式会大面积缺失,并给出输出里「样式基本可用」和「全部生效」两个版本。「全部生效」不含该浏览器任何版本都不支持的个别特性,这些会单独列出。
33
+
34
+ 第一次检查就是 3,说明白屏不是 JS 解析失败造成的,按 SKILL 的「验证兼容但仍白屏」继续排查。
35
+
36
+ ## 退出码 2:无法判断
37
+
38
+ 看报错处理,都**不要盲改配置**:
39
+
40
+ - 浏览器无法识别:换一种写法。提示「看起来是安卓系统版本」:请用户提供 Chrome 内核版本。提示 UA 里没有 `Chrome/` 版本号(老系统自带浏览器等):这类浏览器判断不了内核版本,如实告诉用户无法验证。
41
+ - 产物目录不存在:回到构建那一步。
42
+ - 提示排查目录不能安全使用(是符号链接、不属于当前用户,或其他用户可写):不要删除或绕过,如实告诉用户这个沙箱里的 `/tmp/browser-compat-debug` 需要人工检查。
43
+ - `--prepare` 提示项目里没有 `node_modules`:先在项目里装好依赖,再从构建那一步开始。提示不要在排查目录里执行:回到项目根目录再执行。
44
+ - 无法获取 MDN 兼容数据:网络问题,稍后重试。数据缓存在 `/tmp/browser-compat-debug/bcd`。
45
+ - 提示 vite 不提供 parseAst:项目的 Vite 版本太旧(Vite 7、8 已验证可用)。
46
+ - 结论是「无法完整判断」(有脚本解析失败),或提示 MDN 数据里没有某个条目:脚本本身需要维护。
47
+
48
+ 重试无效时,如实告诉用户这次无法验证。
49
+
50
+ ## 输出里的其他信息
51
+
52
+ - 「JS 能解析所需的最低版本」「样式基本可用 / 全部生效」:回复用户时都带上。说「升级到某版本就完全正常」时,只能用「全部生效」那个版本。
53
+ - 样式条目前的「✗」表示会导致样式大面积缺失,「·」表示只影响局部效果(个别属性、选择器)。
54
+ - 「写在 try 块里的 RegExp」:catch 把异常吞掉了,多为特性检测(先试一下浏览器支不支持),没有计入结论,排查运行时报错时再看。没有 catch、或 catch 里又 throw 的,照常计入结论。
55
+ - 「⚠ 无法解析」:这些脚本或样式没有参与判断。结论是 1 或 3 时照常处理,并在回复里说明。