Webflow 中国加速

SkillDB 作者 shenyeah v1.0.2

Webflow + Cloudflare Worker 中国大陆访问加速专项技能。当用户想要优化 Webflow 网站在中国大陆的访问速度时,必须使用此技能。 触发场景:用户提到 Webflow 网站速度慢、中国大陆无法访问、CF Worker 反向代理优化、Google 资源被屏蔽、Webflow CDN 加速、 字体加载慢、视频加载慢、jsdmirror 替换、R2 缓存、ICP 备案合规、EdgeOne 国内节点、双域名双 CDN 架构、DNS 地理分流、 多项目扩展、Geo-DNS、华为云 DNS、腾讯 EdgeOne、大陆备案最小成本方案等话题。 即使用户只是问"我的 Webflow 网站在中国大陆很慢怎么办"也要触发。

源码 ↗

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install skilldb:shenyeah~webflow-china-speed
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/skilldb%3Ashenyeah~webflow-china-speed/file -o webflow-china-speed.md
Git 仓库获取源码
git clone https://github.com/openclaw/skills/commit/2a2e606699d2265253194cc787d8e4c616631b29
# Webflow 网站中国大陆访问加速

解决 Webflow 网站在中国大陆打不开/极慢的问题。方案基于 Cloudflare Worker 反向代理,涉及多项操作:移除被墙的 Google 资源、jQuery 替换为国内镜像、静态资源缓存到 R2、CSS/视频/字体路径改写等。如需更彻底的加速(延迟降至 50-100ms),则需要 ICP 备案并接入腾讯 EdgeOne 国内节点。

---

## 前置条件确认

在开始前,先了解用户现有架构:
- **域名与 Webflow URL**:用户自定义域名是什么?原始 Webflow URL(*.webflow.io)是什么?
- **是否已有 CF Worker**:如果已有,让用户提供现有 Worker 代码;如果没有,需要从头建
- **是否已有 R2 Bucket**:R2 是持久化静态资源缓存的关键
- **CF Account ID**:部署 Worker 需要
- **网站特殊内容**:有没有视频背景、自定义字体、第三方 JS 库?

---

## 诊断清单:检测哪些资源有问题

在中国大陆,以下资源**必然**被屏蔽或严重降速:

| 资源类型 | 问题根源 | 影响 |
|---------|---------|------|
| Google Fonts (`fonts.googleapis.com`) | GFW 封锁 | 字体加载失败,页面渲染阻塞 |
| Google 相关 preconnect/dns-prefetch | DNS 解析超时 | 每次页面请求额外增加 2-5s |
| Google Analytics / gtag | GFW 封锁 | 统计失效(不阻塞渲染,但浪费连接) |
| WebFont Loader (`webfont.js`) | Google 相关 | 同 Google Fonts |
| Webflow CDN (Fastly + CloudFront) | 无大陆节点 | 静态资源从海外回源,RTT 高 |
| Webflow 注入的 jQuery (d3e54v103j8qbb.cloudfront.net) | CloudFront 无大陆节点 | 每次页面加载阻塞约 500ms-2s |
| 视频文件 (`.mp4`/`.webm`) | 无大陆 CDN 节点 | 视频无法起播,需要完整下载 |

**如何快速诊断**:用 `curl` 从国内 IP 测试关键资源,或让用户在国内打开浏览器 DevTools 的 Network 面板,按耗时排序。

---

## 架构方案

```
用户 (中国大陆)
    ↓
Cloudflare Worker (全球节点,含香港/日本/新加坡)
    ↓ 静态资源命中 R2 → 直接返回 (延迟极低)
    ↓ 静态资源未命中 → 回源 Webflow CDN → 异步写入 R2
    ↓ HTML/动态请求 → 回源 Webflow → HTMLRewriter 改写后返回
    ↓
shenye.webflow.io(原始 Webflow 站点)
```

**关键路径**:
- `/_cdn/{host}/{path}` — 所有 Webflow 静态资源的 R2 缓存路由
- HTMLRewriter — 流式改写 HTML,替换/删除被墙资源链接,无需等待完整 HTML
- R2 Bucket — 永久缓存静态资源(字体、图片、JS、视频),冷启动后无需再回源

---

## 10 项核心优化(已验证)

### [优化 1] HTML 响应加缓存头 + CF 边缘 cacheTtl

**问题**:Webflow 默认返回的 HTML 无缓存头,CF 每次都回源,大陆用户每次都经历完整 RTT。
**方案**:给 HTML 响应加 `cache-control: public, max-age=300, s-maxage=300`,同时在 `fetch()` 里设 `cacheTtl: 300`,让 CF 边缘节点缓存 5 分钟。
**注意**:要 `delete("set-cookie")` 避免带 cookie 的响应被缓存后污染其他用户。

### [优化 2] 移除 Google preconnect / dns-prefetch / gstatic 标签

**问题**:即使不加载 Google Fonts,HTML 里残留的 `<link rel="preconnect" href="fonts.googleapis.com">` 等标签也会让浏览器发起 DNS 查询,在大陆超时后才放弃,消耗 2-5s。
**方案**:用 HTMLRewriter 移除所有 `href` 含 `google` 或 `gstatic` 的 `preconnect`/`dns-prefetch` 标签,以及直接指向 `fonts.googleapis.com`/`fonts.gstatic.com` 的 `<link>` 标签。

### [优化 3] CSS 内 @import fonts.googleapis.com 过滤

**问题**:Webflow 有时会把 Google Fonts 的 `@import` 放进 CSS 文件里(而非 HTML `<link>`),HTMLRewriter 无法处理 CSS 内容。
**方案**:对 `text/css` 响应做文本替换,用正则删除所有 `@import url(...)` 中含 `fonts.googleapis.com` 的行。

### [优化 4] R2 objectKey 包含 query string

**问题**:某些静态资源 URL 带有版本参数(如 `?v=xxx`),如果 R2 key 只用路径,不同版本会映射到同一个 key,导致缓存错乱。
**方案**:objectKey 格式为 `assets/{host}/{path}_{base64(queryString)}`,有 query 时包含编码后的 query 部分。

### [优化 5] jQuery 直接替换为 jsdmirror

**背景**:Webflow 在所有网站的 `</body>` 前自动注入 jQuery 3.5.1,源固定来自 `d3e54v103j8qbb.cloudfront.net`(所有 Webflow 网站共用,URL 中的哈希前缀固定不变)。
**问题**:CloudFront 在大陆没有节点,这个 script 标签会阻塞页面完成渲染。
**方案**:用 HTMLRewriter 将该 `<script src>` 替换为 jsdmirror URL。
**验证**:三个源(CloudFront、cdnjs、jsdmirror)提供的字节完全一致,SHA256 相同,所以标签上原有的 `integrity` SRI 属性仍然能通过校验,无需修改。
```javascript
// HTMLRewriter 里的替换规则
.on('script[src*="d3e54v103j8qbb.cloudfront.net"][src*="jquery"]', {
  element(el) {
    el.setAttribute("src", "https://cdn.jsdmirror.com/npm/jquery@3.5.1/dist/jquery.min.js");
    // crossorigin 属性保留,SRI 跨域校验必须
  }
})
```

### [优化 6] 重写 data-video-urls 属性(背景视频)

**问题**:Webflow 背景视频用 `data-video-urls="url1.mp4,url2.webm"` 属性存储视频地址,这个属性是自定义 attribute,不是标准 `src`,普通的资产 URL 重写(`link/script/img/source`)会遗漏它。
**方案**:单独加一个 HTMLRewriter 规则匹配 `[data-video-urls]`,把属性值按逗号分割后逐个重写到 `/_cdn/` 路径。

### [优化 7] /_cdn/ 支持 HTTP Range 请求

**问题**:视频文件需要 Range 请求才能边加载边播放(206 Partial Content)。如果不处理 Range,R2 会返回整个文件,视频播放器会等待完整下载,首帧延迟高。
**方案**:
- R2 命中时:用 `env.MY_BUCKET.get(key, { range: { offset, length } })` 返回 206
- R2 未命中时:将 Range 头转发给上游,但不缓存分段响应到 R2(只缓存完整 200 响应)

### [优化 8] /_cdn/ CSS 文件缓存前先改写内部 URL

**问题**:`/_cdn/` 处理器默认把资源原样透传并缓存。CSS 文件内部的 `@font-face src: url(https://cdn.prod.website-files.com/...)` 和背景图片等绝对 URL 不会被改写,浏览器加载 CSS 后直接向 Fastly 拉取字体/图片,完全绕过 R2 缓存。这个问题不容易被发现——DevTools 里字体确实是 `.woff2`,但实际走的是 Fastly 而非 R2。
**诊断方法**:`curl` 拉取 `/_cdn/...min.css`,用 `grep -oP 'https?://[^")\\s,]+'` 查找其中所有绝对 URL,看是否仍指向 `cdn.prod.website-files.com`。
**方案**:在 `/_cdn/` 处理器的 R2 未命中回源路径里,对 CSS 文件(`content-type: text/css` 或路径以 `.css` 结尾)先做 URL 改写,再写入 R2 缓存。

### [优化 9] 移除 stylesheet `<link>` 的 SRI integrity 属性

**问题**:Webflow 生成的 HTML 里,CSS `<link>` 标签带有 `integrity="sha384-..."` 属性(Subresource Integrity)。Worker 改写了 CSS 文件内部 URL(优化 8),导致文件内容变化,SHA-384 哈希不再匹配。浏览器会静默拒绝加载该 CSS,**页面彻底失去样式**,且控制台报错容易被忽略。
**方案**:HTMLRewriter 里加一条规则,移除所有 `<link rel="stylesheet">` 上的 `integrity` 属性。
**注意**:jQuery 的 `<script integrity>` 不需要处理,因为我们只是换了 URL 而没有修改文件内容,字节完全一致,SRI 仍然通过。
```javascript
.on('link[rel="stylesheet"][integrity]', {
  element(el) { el.removeAttribute("integrity"); }
})
```
**R2 旧缓存处理**:部署新 Worker 后,R2 里已缓存的 CSS 文件(未经改写的版本)仍然会被命中返回,导致问题持续。需要在 CF Dashboard → R2 → Bucket 里手动删除对应的 CSS 对象,强制下次请求走回源流程重新处理。

### [优化 11] meta og:image / twitter:image 改写到 /_cdn/

**问题**:OG 图片 URL 存在于 `<meta property="og:image" content="...">` 的 `content` 属性里,HTMLRewriter 标准资产选择器 `link[href], script[src], img[src], source[srcset]` **不覆盖 `<meta>` 标签**。

两条路径的后果不同:
- `handleCN`:依赖全文正则兜底改写,属脆弱副作用路径
- `handlePassthrough`(海外爬虫路径):**完全未处理**——微信/微博/Twitter/Slack 爬虫抓取 OG 图时仍拿到原始 `cdn.prod.website-files.com` 地址,图片不走 R2 缓存

**注意**:不影响浏览器页面加载速度(非阻塞资源),但影响社交分享缩略图抓取速度和成功率。

**方案**:`handleCN` 和 `handlePassthrough` 两条路径的 HTMLRewriter 均需新增规则:

```javascript
.on('meta[property="og:image"], meta[property="og:image:secure_url"], meta[name="twitter:image"], meta[itemprop="image"]', {
  element(el) {
    const v = el.getAttribute("content");
    if (v) el.setAttribute("content", rewriteAsset(v));
  }
})
```

修复后社交爬虫打到 `/_cdn/...` 路径,Worker 代理图片并写入 R2,二次抓取直接命中缓存。

**诊断命令**:`curl -s https://your-domain.com/ | grep -i "og:image"`,确认 `content` 属性已改写为 `/_cdn/cdn.prod.website-files.com/...`。

---

### [优化 10] 补全视频 poster 及 `<source src>` 的改写

**问题**:Webflow 背景视频在 HTML 里同时存在三条并行路径,[优化 6] 只处理了其中一条:

| 属性 | 谁读取 | 优化 6 前 |
|------|-------|---------|
| `data-video-urls` | Webflow JS 运行时 | ✅ 已改写 |
| `<source src>` | 浏览器原生回退 | ❌ 漏网 |
| `data-poster-url` | Webflow JS 设置海报帧 | ❌ 漏网 |
| `<video style="background-image:url(...)">` | 浏览器直接渲染海报 | ❌ 漏网 |

前三条会导致视频/海报仍从 Fastly 加载;`video[style]` 是最隐蔽的——poster 作为内联 CSS 背景图注入,不走任何 src 属性,普通属性扫描完全看不到。

**诊断方法**:`curl` 拉 HTML,搜索 `data-poster-url` 和 `video[style]`,看是否仍有 `https://cdn.prod.website-files.com` 地址。

**方案**:
- 将 `source[srcset]` 改为 `source[src], source[srcset]`,同时覆盖视频源和图片多分辨率
- 新增 `[data-poster-url]` handler 改写 poster URL
- 新增 `video[style]` handler,用正则替换 `background-image:url(...)` 里的绝对地址

---

## 字体优化建议

字体是另一个重要的加速点,与 Worker 改动独立:

1. **格式**:TTF 未压缩,WOFF2 约小 40-60%。在 Webflow Project Settings → Fonts 里,删除 TTF 字体文件,重新上传同一字体的 WOFF2 版本。(转换工具:`woff2_compress` 命令行,或在线工具)
2. **排查无用字体**:在 Webflow 里上传了字体不一定实际用到了。先用 `curl` 拉取网站 HTML,搜索每个字体名,确认实际有被 CSS `font-family` 或 Webflow 样式引用后再保留。未使用的字体是纯负担(169KB/字体的典型值),直接删除。
3. **Adobe Fonts**:Webflow 有 Adobe Fonts 集成入口,但只要没有实际激活的 Kit,不会产生任何网络请求,不需要处理。

---

## 第三方 JS 库注意事项

### 使用 jsdmirror 的正确姿势

jsdmirror (`cdn.jsdmirror.com`) 是 jsDelivr 的镜像,由腾讯 EdgeOne 提供大陆 CDN 节点。URL 格式:
```
https://cdn.jsdmirror.com/npm/{package}@{version}/dist/{file}.min.js
```

**必须**指定版本号和具体文件路径,否则 URL 无效。例:
- ✅ `https://cdn.jsdmirror.com/npm/lenis@1.0.27/dist/lenis.min.js`
- ❌ `https://cdn.jsdmirror.com/npm/lenis`(缺版本和路径,404)

### Lenis 平滑滚动(特别注意)

Webflow 社区流行的 Lenis 集成方案通常是一个**定制 bundle**,包含:
- Lenis 核心库(特定版本)
- Webflow 专属初始化层:读取 `[data-id-scroll]` 元素上的 `data-*` 属性作为配置
- 全局 `window.SScroll` 实例化
- `useAnchor`、`useOverscroll`、`useControls` 等扩展功能

这个定制 bundle **不在 npm 上**,因此 jsdmirror 没有它。如果用户在 Webflow 里自托管了这个 bundle(`.txt` 文件),正确做法是继续使用原有的 Webflow CDN URL——该 URL 属于 `cdn.prod.website-files.com`,Worker 会自动将其重写到 `/_cdn/` 路径并缓存到 R2,无需手动迁移。

**诊断方法**:检查 `.txt` 文件内容,看是否含有 `window.SScroll`、`I("[data-id-scroll]"` 等 Webflow 专属代码,如果有,就不能用 npm 版替换。

---

## Worker 代码模板

完整的可直接部署的 Worker 代码见 `references/worker-template.js`。

使用前需要替换的变量:
- `WEBFLOW_HOST` → 用户的 Webflow 内部