html2canvas 1.4.1 在 iOS Safari 中生成图片卡住的问题排查与修复

html2canvas 1.4.1 在 iOS Safari 中生成图片卡住的问题排查与修复

问题现象

在 iOS Safari / 移动端 vConsole 环境中,使用 html2canvas 1.4.1 时无法成功生成图片。

最初看到的报错类似:

text 复制代码
TypeError: undefined is not a function

(near '...t.match(...)...')

同时 html2canvas 日志停在:

text 复制代码
Starting document clone...

之后没有进入 resolved,也没有正常输出 canvas。

最小复现

为了判断是脚本问题还是业务 DOM 问题,先做了一个最小 DOM 测试:

js 复制代码
function testHtml2canvasCore(scriptUrl) {

    scriptUrl = scriptUrl || "https://cdn.staticfile.org/html2canvas/1.4.1/html2canvas.min.js";

  


    $.getScript(scriptUrl + "?v=iframefix").done(function () {

        var demo = document.createElement("div");

        demo.id = "html2canvasCoreDemo";

        demo.style.cssText = [

            "position:fixed",

            "left:10px",

            "top:10px",

            "width:120px",

            "height:60px",

            "background:#fff",

            "color:#111",

            "font-size:14px",

            "z-index:999999"

        ].join(";");

        demo.innerHTML = "core demo";

        document.body.appendChild(demo);

  


        html2canvas(demo, {

            scale: 1,

            useCORS: true,

            logging: true

        }).then(function (canvas) {

            console.log("core demo ok", canvas.width, canvas.height);

        }).catch(function (err) {

            console.error("core demo error", err);

        });

    });

}

测试结果:

  • 使用 1.4.1:最小 DOM 也卡住。

这说明问题第一层不在业务 DOM,而在 html2canvas 1.4.1 自身的 document clone / iframe 流程。

根因定位

html2canvas 1.4.1 在生成图片前会 clone 当前 document 到一个隐藏 iframe 中,然后等待 iframe 加载完成。

相关的 minified 代码原本类似:

js 复制代码
In=function(B){

    return new Promise(function(e,A){

        var t=B.contentWindow;

        if(!t)return A("No window assigned for iframe");

        var r=t.document;

        t.onload=B.onload=function(){

            t.onload=B.onload=null;

            var A=setInterval(function(){

                0<r.body.childNodes.length&&"complete"===r.readyState&&(clearInterval(A),e(B))

            },50)

        }

    })

}

关键问题在这里:

js 复制代码
t.onload = B.onload = function () { ... }

原逻辑必须等 iframe 的 load 事件触发后,才开始轮询 iframe document 是否准备好。

在当前 iOS Safari 环境中,这个隐藏 iframe 的 load 事件没有稳定触发,导致 Promise 一直不 resolve,于是 html2canvas 日志停在:

text 复制代码
Starting document clone...

这也是为什么业务 DOM 和极简 DOM 都失败。

修复方案

修复思路是:不要完全依赖 iframe 的 load 事件。注册 onload 的同时,立即启动一次相同的检查逻辑。

补丁后的 In 函数:

js 复制代码
In=function(B){

    return new Promise(function(e,A){

        var t=B.contentWindow;

        if(!t)return A("No window assigned for iframe");

        var r=t.document,n=function(){

            t.onload=B.onload=null;

            var A=setInterval(function(){

                r.body&&0<r.body.childNodes.length&&("complete"===r.readyState||"interactive"===r.readyState)&&(clearInterval(A),e(B))

            },50)

        };

        t.onload=B.onload=n,setTimeout(n,0)

    })

}

相比原逻辑,改动点有三个:

  1. onload 回调提取成 n

  2. 保留原来的 t.onload = B.onload = n

  3. 增加 setTimeout(n, 0),避免 iframe load 事件不触发时永久卡住。

同时轮询条件也做了兼容:

js 复制代码
r.body &&

0 < r.body.childNodes.length &&

("complete" === r.readyState || "interactive" === r.readyState)

这样 iframe document 已经进入 interactive 状态时也可以继续。

验证方式

在移动端 vConsole 中验证最小 DOM:

js 复制代码
testHtml2canvas141()

成功后再验证当前业务 DOM:

js 复制代码
testHtml2canvasCurrentDom()

最终结果:

  • 最小 DOM 可以生成 canvas。

  • 当前业务 DOM 可以继续生成图片。

  • 1.4.1 的样式表现优于旧 plugin 版本。

经验总结

这次问题容易被误判成业务 DOM 或 CSS 问题,因为 html2canvas 的报错栈经过压缩后很难直接读,vConsole 里显示的 t.match 也不一定是根因。

更有效的排查路径是:

  1. 先确认实际加载的是哪一个 html2canvas 文件。

  2. 用极简 DOM 做最小复现。

  3. 如果极简 DOM 也失败,就优先排查 html2canvas 初始化、clone、iframe、资源加载这些基础流程。

  4. 观察 html2canvas 日志停在哪一步。

本次的关键判断点是:极简 DOM 也卡在 Starting document clone...,所以问题不在业务 DOM,而在 1.4.1 的隐藏 iframe clone 等待逻辑。

相关推荐
AlienZHOU1 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc4 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师6 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen6 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒7 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow7 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林8187 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang800787 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明7 小时前
第 6 章 组件进阶
前端·vue.js
江华森7 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端