【问题标题】:Using sourceURL and sourceMappingURL with relative paths将 sourceURL 和 sourceMappingURL 与相对路径一起使用
【发布时间】:2019-10-29 04:07:37
【问题描述】:

似乎sourceURL 在 Firefox 和 Chrome 中的相对不同 - 当某些工具在 JS 文件中生成与它们所在的文件相关的 //# sourceURL=... 字符串时,Firefox 将 URL 视为相对于 JS 文件, 而 Chrome 将其视为相对于原始 HTML 文件。哪个是正确的,或者有更清晰的方式来说明这一点?


在这个示例应用程序中,我尝试使用 sourceURL 来允许将许多较小的文件组合成一个大文件,但仍然允许浏览器知道应该调用什么较小的文件,以及 sourceMappingURL然后指定源映射文件,相对于该原始文件。

目录结构:

index.html
js/
  all.js
  uncompiled/
    app.js
    app.js.map
    app.min.js

index.html 是加载js/all.jsjs/uncompiled/app.min.js 的最小页面。没有其他 JS 被烘焙到 js/all.js 中(因为这是一个最小的例子),但理论上这里可能有很多。该文件的目的只是将各种缩小的 JS 文件合并为一个更大的文件,但仍然允许开发人员查看原始代码,并相应地设置断点。

app.js的内容:

class App {

    constructor(name) {
        this.name = name;
    }

    sayHi() {
        window.alert("Hello " + this.name);
    }
}

new App("Colin").sayHi();

然后,运行一个简单的 minifier 将其重建为 app.min.js 并带有匹配的 app.js.map 文件:

var App=function(a){this.name=a};App.prototype.sayHi=function(){window.alert("Hello "+this.name)};(new App("Colin")).sayHi();
//# sourceMappingURL=app.js.map
{
"version":3,
"file":"./app.min.js",
"lineCount":1,
"mappings":"AAAA,IAAMA,IAELC,QAAW,CAACC,CAAD,CAAO,CACjB,IAAAA,KAAA,CAAYA,CADK,CAIlB,IAAA,UAAA,MAAAC,CAAAA,QAAK,EAAG,CACPC,MAAAC,MAAA,CAAa,QAAb,CAAwB,IAAAH,KAAxB,CADO,CAKTC,EAAA,IAAIH,GAAJ,CAAQ,OAAR,CAAAG,OAAA;",
"sources":["app.js"],
"names":["App","constructor","name","sayHi","window","alert"]
}

最后,将缩小后的输出包装在 eval 中,并将 sourceURL 参数添加到末尾(添加换行符以提高可读性):

eval('var App=function(a){this.name=a};App.prototype.sayHi=function
(){window.alert("Hello "+this.name)};(new App("Colin")).sayHi();\n
//# sourceMappingURL=app.js.map\n//# sourceURL=uncompiled/app.min.js');

如果index.html直接指向js/uncompiled/app.min.js,那么Firefox和Chrome都正确理解app.js.map在同一个目录下,调试时应该使用。但是,如果index.html 指向js/all.js,那么虽然两个浏览器都正确地在单个文件中显示eval 的内容,但只有Firefox 使路径相对于all.js

在这个结构上使用python -m http.server 会在 Firefox 中显示这些结果:

127.0.0.1 - - [14/Jun/2019 08:33:37] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [14/Jun/2019 08:33:37] "GET /js/all.js HTTP/1.1" 200 -
127.0.0.1 - - [14/Jun/2019 08:33:38] code 404, message File not found
127.0.0.1 - - [14/Jun/2019 08:33:38] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [14/Jun/2019 08:33:41] "GET /js/uncompiled/app.js.map HTTP/1.1" 200 -
127.0.0.1 - - [14/Jun/2019 08:33:41] "GET /js/uncompiled/app.js HTTP/1.1" 200 -

另一方面,这是 Chrome 的尝试:

127.0.0.1 - - [14/Jun/2019 08:34:22] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [14/Jun/2019 08:34:22] "GET /js/all.js HTTP/1.1" 200 -
127.0.0.1 - - [14/Jun/2019 08:34:22] code 404, message File not found
127.0.0.1 - - [14/Jun/2019 08:34:22] "GET /uncompiled/app.js.map HTTP/1.1" 404 -
127.0.0.1 - - [14/Jun/2019 08:34:23] code 404, message File not found
127.0.0.1 - - [14/Jun/2019 08:34:23] "GET /favicon.ico HTTP/1.1" 404 -

Chrome 似乎假设js/app.js 中的sourceURLindex.html 相关,而Firefox(从我的角度来看是正确的)将其解释为与app.js 相关。我建议 Firefox 是正确的,因为它允许任何 HTML 文件在任何路径中包含该 JS,并且仍然可以正确加载源映射。

示例来源,包括不同相对路径的两个 html 文件:https://github.com/niloc132/sourceurl-and-sourcemapping-url-relative-paths

【问题讨论】:

    标签: google-chrome-devtools source-maps firefox-developer-tools


    【解决方案1】:

    来自规范(或https://sourcemaps.info/spec.html 的副本):

    当源映射 URL 不是绝对的时,它是相对于生成代码的“源源”的。来源来源由以下情况之一确定:

    • 如果生成的源不与具有“src”属性的脚本元素相关联,并且生成的代码中存在//# sourceURL 注释,则应使用该注释来确定源来源。注意:以前,这是“//@ sourceURL”,与“//@ sourceMappingURL”一样,两者都接受是合理的,但首选//#。
    • 如果生成的代码与脚本元素相关联并且该脚本元素具有“src”属性,则该脚本元素的“src”属性将为源源。
    • 如果生成的代码与脚本元素相关联并且脚本元素没有“src”属性,则源源将是页面的源。
    • 如果使用eval() 函数或new Function() 将生成的代码作为字符串评估,则源源将是页面的源。

    js/all.js 的情况下,它属于最后一种情况:源原点将是页面的原点。因此,Chrome 似乎正在遵循规范,尽管这似乎违反直觉。

    【讨论】:

    • 对,我更关注“这有什么用”而不是“规范实际上规定了什么”——这不是第一次浏览器规范模棱两可、令人困惑或完全适得其反。根据您对规范的阅读,是否正确理解没有办法明确指出此类文件中使用的源,但任何此类 JS 文件都必须在服务器或客户端上进行后处理,然后再进行评估,相对于引用者?
    • 或者,“总是内联整个源映射内容”,但这只是意味着除非您在 JS 的目录之外没有 HTML 文件,否则不能一起使用 sourceURL 和 sourceMappingURL,或者构建 JS围绕 HTML 的路径,而不是让它独立(“后处理”选项)。
    猜你喜欢
    • 2020-10-16
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    相关资源
    最近更新 更多