背景
做前端接私活的应该都遇到过:客户在 Webflow 上做了网站,想搬到自己的服务器。 Webflow 自带的导出功能,代码一言难尽…
核心挑战
1. 页面渲染
Webflow 大量使用客户端渲染,直接 fetch(url) 拿到的 HTML 不完整。 解决方案:用 Puppeteer 渲染页面,等待 networkidle2 后再获取 DOM。 javascript
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
// 滚动到底部触发懒加载
await autoScroll(page);
const html = await page.content();
2. DOM 清洗
Webflow 生成的 HTML 结构: html
<div class=\"w-layout-blockcontainer w-container\">
<div class=\"w-layout-hflex flex-block-3\">
<div data-w-id=\"a8f3\" class=\"div-block-47\">
<h1 class=\"heading-12\">Welcome</h1>
<!-- 清洗后: 干净的语义化HTML -->
<header class=\"hero\">
<h1>Welcome</h1>
核心逻辑:用 Cheerio 递归检测"无意义包裹 div"并展开:
javascript
// 展开无属性、单子元素的 div
$('div').each((_, el) => {
const $el = $(el);
if (!$el.attr('id') && !$el.attr('class') && !$el.attr('style')) {
if ($el.children().length === 1) {
$el.replaceWith($el.children());
}
}
});
3. CSS 处理
- 从 document.styleSheets 提取所有 CSS 规则
- 下载外部 CSS 文件
- 用 clean-css 去重压缩
- 替换 url() 中的资源路径为本地路径
4. 资产下载
并行下载图片、字体,自动分类到 images/fonts 目录,URL 替换为相对路径。
效果
做成了一个在线工具,输入 URL 就能导出:http://180.76.147.226:3000/ 免费体验 3 次,欢迎试用反馈。 — 技术栈:Node.js + Puppeteer + Cheerio + Clean-CSS + Express 如果对实现细节感兴趣,评论区交流 👇