如何设置源映射以帮助调试生产JavaScript

发布于:2021-01-06 17:22:16

0

95

0

JavaScript tutorials 源映射

开发人员可以使用源映射将转译的代码映射回其原始源代码。这五个技巧可帮助开发人员在JavaScript中使用源地图,从而使他们可以花费更少的时间进行调试,而将更多的时间花在编写软件上。

根据GitHub的说法,JavaScript是世界上最受欢迎的编程语言。这是因为开发人员转向JavaScript来构建仅在浏览器中提供的引人注目的用户体验。为了支持这些复杂的应用程序,已经出现了有助于加快Web开发速度的新工具和框架:您可能听说过React,TypeScript和Webpack。

这些新兴工具虽然可以极大地提高生产力,但也带来了新的挑战,尤其是在调试生产JavaScript应用程序时。开发人员现在必须使用编译后的代码调试实时软件,这些编译后的代码与他们熟悉的原始源代码几乎没有相似之处。这使得修复生产问题的速度变慢,可能会给用户带来糟糕的体验。

好消息是,开发人员可以使用源映射将转译的代码映射回其原始源代码。正确配置源映射后,Web浏览器和可观察性工具会将堆栈跟踪,源文件和其他有价值的调试信息转换为原始形式。

所有这些都取决于正确设置源地图,这可能比您预期的更具挑战性。以下是五个技巧,可帮助开发人员使源地图正常工作,从而使他们可以花费更少的时间进行调试,而将更多的时间用于执行自己喜欢的事情:编写软件。

实际生成源地图

源映射听起来很复杂,但是它们只是JSON文件,其中包含浏览器和其他工具可以理解的映射定义。但是它们并不会突然出现-由开发人员来生成这些源映射是他们应用程序构建过程的一部分。幸运的是,几乎每个生成JavaScript的编译器都有生成它们的选项。

例如,如果原始源代码在TypeScript中,则可以在编译过程中使用TypeScript编译器生成随附的源映射。

$ tsc example.ts --outFile=example.js --source-map

上面的示例命令通过TypeScript编译器发送example.ts,输出一个名为example.js的JavaScript文件,还输出一个名为example.js.map的随附源映射文件。

无论您使用的是TypeScript,还是像Elm一样编译为JavaScript的另一种语言,还是像Webpack一样的捆绑程序,请查看工具的文档以获取如何生成源地图。像上面的示例一样,它通常像单个命令行参数一样简单。

验证sourceMappingURL指令

使源映射正常工作的下一步是确保正确声明了sourceMappingURL指令。这是已编译的JavaScript文件末尾的一行,表示源映射可用以及在何处可以找到。

//# sourceMappingURL=example.js.map

当浏览器看到此行时,他们将下载源映射,以确认在浏览器中运行的代码与生成它的原始源代码是一致的。可以将其声明为完全限定的URL(即,它包括http://或https://),也可以相对于包含指令的源文件进行解析。

启用源地图生成时,生成JavaScript的编译器会自动将此行插入最终的编译文件中。但是,从最初对代码进行转换到到达用户要下载的Web服务器或CDN,通常要经过一段漫长的旅程。例如,后续的构建工具可能会移动此行的位置或将其删除。某些CDN为了最大程度地减少线上字节传输,甚至已知自动从JavaScript文件中删除该行。

为确保您做的正确,重要的是要检查sourceMappingURL不仅在构建时生成,而且在用户通过网络下载此文件时也可以显示。您可以使用浏览器,甚至使用cURL之类的工具来验证其是否存在:

$ curl -s http://example.com/static/example.js | tail -1 //# sourceMappingURL=example.js.map

验证指令存在后,请解析其指向的URL,以确保源映射存在并且可以通过网络访问。

将您的源文件嵌入到源图中

源图可能会出现问题,因为可以使用不同级别的粒度来构建源图。例如,可以在不引用任何原始源文件的情况下创建“最小”源映射,这使浏览器仅能够转换基本元数据,如文件名和行/列位置。

如果要从源地图中获得最大价值,建议将原始源代码嵌入源地图中。这样,您不仅可以获得基本位置转换的好处,而且还为浏览器和其他监视工具提供了逐步浏览原始源代码的功能。这在调试生产JavaScript时非常重要–否则,您会发现自己逐步遍历了比人可读的代码更接近于汇编的已编译和最小化的代码。

大多数可生成JavaScript的编译器都提供了将源代码直接嵌入到源映射中的功能。例如,流行的JavaScript缩小工具UglifyJS使您可以在命令行上指定此选项。

$ uglifyjs --output=example.min.js example.js --source-map includeSources

运行此命令不仅会生成源映射并指定sourceMappingURL指令,而且还会将整个输入文件(example.js)嵌入到源映射本身中。这为浏览器提供了关于如何向后处理原始代码的最清晰画面。

查看工具的源地图文档,以了解如何将源代码嵌入到源地图中。(注意:如果您不想与世界共享您的源代码,请确保不要在公共互联网上共享您的源地图-请考虑在VPN后面对其进行保护。)

使用一个工具来管理JavaScript转换

JavaScript开发人员使用多个编译器来生成最终的编译文件并不少见。例如,开发人员可能首先通过TypeScript编译器运行其TypeScript代码,然后使用UglifyJS缩小输出。这些工具中的每一个都会生成一个源映射。将一种工具的输出输入另一种工具时会发生什么?

答案是:通常转换会变得混乱,并且看起来您已经生成了“有效的”源映射,但实际情况是,映射指向源代码中的错误位置。浏览器将让您浏览完全不正确的源代码,因为它不了解映射是不正确的-只是它们是“有效的”。

最简单的解决方案是使用一个工具在一个地方管理所有转换,以生成单个,最终的,正确的源地图。Webpack是一种实现此目的的工具,它是一种流行的JavaScript捆绑程序。

Webpack的配置可能有些陈旧,因此这里没有提供示例。如果您遇到了错误的映射,我的建议是确认您没有背对背使用多种工具。如果是这样,请探索使用Webpack之类的工具来管理您的转换,而不是单独使用输出JavaScript的编译器。

版本文件和源映射

即使您已经完成了我们所讨论的所有内容,但是有一种最终的方法可以让您被残破的源映射咬住:版本不匹配。当浏览器下载转换后的文件的一个版本,然后下载其随附的源地图的更新的,不兼容的版本时,就会发生这种情况。因为源映射是从文件的不同版本生成的,所以即使文件稍有更改,浏览器最终仍会显示不正确的转换。

这看似罕见的情况,但是它可以通过多种方式发生。例如,如果在调试浏览器先前缓存的文件时触发了代码部署,则会发生这种情况。

为了阻止这种情况的发生,开发人员需要通过对每个文件名,URL的查询字符串或文件的父目录进行版本控制来对文件和源映射进行版本控制。每个编译文件和源映射都应共享相同的版本和版本方案,以确保每个浏览器都下载属于每个编译文件的源映射。

// example.v1337.js *code goes here* //# sourceMappingURL=example.v1337.js.map

在上面的示例中,编译文件的文件名(v1337)中嵌入了一个版本。sourceMappingURL指令指向嵌入了相同版本的源映射。只要此文件的新版本的文件名中带有颠簸的版本号,浏览器就不可能错误地下载错误的附带源映射。

总结

JavaScript继续流行。在无数新框架和新技术的辅助下,它不仅用于为动态网页提供动力,现在还为移动应用程序,游戏和服务器端代码提供动力。使用源映射的开发人员可以更好地调试生产中的已编译JavaScript代码,从而使他们更快地修复应用程序问题并减少对用户的影响。