今天开宝塔后台看一些东西,结果发现面板很多弹窗实际上会直接显示在页面底部,多半就是 CSS 炸了。

排查发现是 layer.css 这个文件指向了 https://static.cloudflareinsights.com/beacon.min.js/layer.css?v=版本。这个路径当然是不对的,正常应该是 https://面板地址/static/layer/layer.css?v=版本

探索了一会发现了问题所在……这搭配但凡缺了一个都不至于出现这憨批问题

layer.css 实际通过 layer.js 加载,后者有一部分代码:

var i, n, a = e.layui && layui.define,
o = {
    getPath: function() {
        var e = document.scripts,
        t = e[e.length - 1],
        i = t.src;
        if (!t.getAttribute("merge")) return i.substring(0, i.lastIndexOf("/") + 1)
    } (),
    config: {},
    end: {},
    minIndex: 0,
    minLeft: [],
    btn: ["确定", "取消"],
    type: ["dialog", "page", "iframe", "loading", "tips"]
},
r = {
    v: "3.0.1",
    ie: function() {
        var t = navigator.userAgent.toLowerCase();
        return !! (e.ActiveXObject || "ActiveXObject" in e) && ((t.match(/msie\s(\d+)/) || [])[1] || "11")
    } (),
    index: e.layer && e.layer.v ? 1e5: 0,
    path: o.getPath,
    config: function(e, t) {
        return e = e || {},
        r.cache = o.config = i.extend({},
        o.config, e),
        r.path = o.config.path || r.path,
        "string" == typeof e.extend && (e.extend = [e.extend]),
        o.config.path && r.ready(),
        e.extend ? (a ? layui.addcss("modules/layer/" + e.extend) : r.link("skin/" + e.extend), this) : this
    },
    link: function(t, n, a) {
        if (r.path) {
            var o = i("head")[0],
            l = document.createElement("link");
            "string" == typeof n && (a = n);
            var s = (a || t).replace(/\.|\//g, ""),
            f = "layuicss-" + s,
            c = 0;
            l.rel = "stylesheet",
            l.href = r.path + t,
            l.id = f,
            i("#" + f)[0] || o.appendChild(l),
            "function" == typeof n &&
            function t() {
                return++c > 80 ? e.console && console.error("layer.css: Invalid") : void(1989 === parseInt(i("#" + f).css("width")) ? n() : setTimeout(t, 100))
            } ()
        }
    },
    ready: function(e) {
        var t = "skinlayercss",
        i = "1110";
        return a ? layui.addcss("modules/layer/default/layer.css?v=" + r.v + i, e, t) : r.link("layer.css?v=" + r.v + i, e, t),
        this
    },

我的 JS 是废物,只能靠盲猜了……

按我的思路,layer.css 的实际请求路径由 layer.js 补全

→ 可以找到调用了 r.link(...)

→ 找到 l.href = r.path + t,得知路径确实是补全的

r.path 的值由 path: o.getPath 提供

i = t.src 配合 i.substring(0, i.lastIndexOf("/") + 1) 获得当前 JS 文件所在的域名

本来是一件很正常的事情……但由于 Rocket Loader 的设计……

没错,发起源会变成 Rocket Loader

这就直接导致 t.src 获取的值是 https://static.cloudflareinsights.com/beacon.min.js/,导致补全 CSS 路径的时候直接暴毙🤥

目前来说我的解决方案只有关闭 Rocket Loader🐸