javascript调试
These days, the code you use to write your application isn’t usually the same code that’s deployed in production and interpreted by browsers. Perhaps you’re writing your source code in a language that “compiles” to JavaScript, like CoffeeScript, TypeScript, or the latest standards-body approved version of JavaScript, ECMAScript 2015 (ES6). Or, even more likely, you’re minifying your source code in order to reduce the file size of your deployed scripts. You’re probably using a tool like UglifyJS or Google Closure Compiler.
如今,用于编写应用程序的代码通常与生产环境中部署的代码和浏览器解释的代码不同。 也许您正在用“编译”到JavaScript的语言编写源代码,例如CoffeeScript,TypeScript或最新的标准机构批准JavaScript版本ECMAScript 2015(ES6)。 或者,甚至更有可能,您正在压缩源代码,以减小已部署脚本的文件大小。 您可能正在使用UglifyJS或Google Closure Compiler之类的工具。
Such transformation tools are often referred to as transpilers — tools that transform source code from one language into either the same language or another similar high-level language. Their output is transpiled code that, while functional in the target environment (e.g., browser-compatible JavaScript), typically bears little resemblance to the code from which it was generated.
此类转换工具通常称为编译器,即将源代码从一种语言转换为相同语言或另一种相似的高级语言的工具。 它们的输出是已编译的代码,尽管它们在目标环境中起作用(例如,与浏览器兼容JavaScript),但通常与生成它的代码几乎没有相似之处。
This presents a problem: when debugging code in the browser or inspecting stack traces generated from errors in your application, you are looking at transpiled and (typically) hard-to-read JavaScript, not the original source code you used to write your application. This can make JavaScript error tracking hard.
这就带来了一个问题:在浏览器中调试代码或检查由应用程序中的错误产生的堆栈跟踪时 ,您正在查看的是已转译的(通常)难读JavaScript,而不是用于编写应用程序的原始源代码。 这会使JavaScript错误跟踪变得困难。
The solution to this problem is a nifty browser feature called source maps. Let’s learn more.
解决此问题的方法是一个漂亮的浏览器功能,称为源映射。 让我们了解更多。
源地图 ( Source Maps )
Source maps are JSON files that contain information on how to map your transpiled source code back to its original source. If you’ve ever done programming in a compiled language like Objective-C, you can think of source maps as JavaScript’s version of debug symbols.
源映射是JSON文件,其中包含有关如何将已转换的源代码映射回其原始源的信息。 如果您曾经使用诸如Objective-C之类的编译语言进行编程,则可以将源映射视为JavaScript的调试符号版本。
Here’s an example source map:
这是一个示例源映射:
{
version : 3,
file: "app.min.js",
sourceRoot : "",
sources: ["foo.js", "bar.js"],
names: ["src", "maps", "are", "fun"],
mappings: "AAgBC,SAAQ,CAAEA"
}
You’ll probably never have to create these files yourself, but it can’t hurt to understand what’s inside:
您可能永远不必自己创建这些文件,但是了解其中的内容也无济于事:
- version: The version of the source map spec this file represents (should be “3”) 版本:此文件表示的源地图规范的版本(应为“ 3”)
- file: The generated filename with which this source map is associated 文件:与此源映射关联的生成的文件名
- sourceRoot: The URL root from which all sources are relative (optional) sourceRoot:所有来源都是相对的URL根(可选)
- sources: An array of URLs to the original source files 来源:原始来源文件的网址数组
- names: An array of variable/method names found in your code 名称:在代码中找到的变量/方法名称数组
- mappings: The actual source code mappings, represented as base64-encoded VLQ values 映射:实际的源代码映射,表示为以base64编码的VLQ值
If this seems like a lot to remember, don’t worry. We’ll explain how to use tools to generate these files for you.
如果要记住很多事情,请不要担心。 我们将说明如何使用工具为您生成这些文件。
sourceMappingURL (sourceMappingURL)
To indicate to browsers that a source map is available for a transpiled file, the sourceMappingURL
directive needs to be added to the end of that file:
为了向浏览器指示源映射可用于已编译的文件,需要将sourceMappingURL
指令添加到该文件的末尾:
// app.min.js
$(function () {
// your application ...
});
//# sourceMappingURL=/path/to/app.min.js.map
When modern browsers see the sourceMappingURL
directive, they download the source map from the provided location and use the mapping information inside to corroborate the running client-code with the original source code. Here’s what it looks like when we step through Sentry’s original ES6 + JSX code in Firefox using source maps (note: browsers only download and apply source maps when developer tools are open. There is no performance impact for regular users):
当现代的浏览器看到sourceMappingURL
指令时,它们从提供的位置下载源地图,并使用内部的映射信息将运行中的客户端代码与原始源代码相sourceMappingURL
。 这是当我们使用源地图在Firefox中逐步浏览Sentry的原始ES6 + JSX代码时的样子(注意:浏览器仅在开发人员工具打开时才下载和应用源地图。对普通用户没有性能影响):
![](https://i-blog.csdnimg.cn/blog_migrate/b5ae5f2d72b03a9fc992f6c17b2502f7.png)
生成源地图 ( Generating the Source Map )
Okay, we now roughly know how source maps work and how to get the browser to download and use them. But how do we go about actually generating them and referencing them from our transpiled files?
好的,现在我们大致了解了源映射的工作方式以及如何使浏览器下载和使用它们。 但是,如何实际生成它们并从转译的文件中引用它们呢?
Good news! Basically every modern JavaScript transpiler has a command-line option for generating an associated source map. Let’s take a look at a few common options.
好消息! 基本上,每个现代JavaScript翻译器都有一个命令行选项,用于生成关联的源映射。 让我们看一些常见的选项。
UglifyJS (UglifyJS)
UglifyJS is a popular tool for minifying your source code for production. It can dramatically reduce the size of your files by eliminating whitespace, rewriting variable names, removing dead code branches, and more.
UglifyJS是一种流行的工具,可用于最小化生产源代码。 通过消除空格,重写变量名,删除无效代码分支等,它可以大大减少文件的大小。
If you are using UglifyJS to minify your source code, the following command from UglifyJS 3.3.x will additionally generate a source map mapping the minified code back to the original source:
如果您使用UglifyJS缩小源代码,则来自UglifyJS 3.3.x的以下命令将另外生成一个源映射,将缩小的代码映射回原始源:
$ uglifyjs app.js -o app.min.js --source-map
If you take a look at the generated output file, app.min.js, you’ll notice that the final line includes the sourceMappingURL
directive pointing to our newly generated source map.
如果查看生成的输出文件app.min.js,您会注意到最后一行包括指向我们新生成的源映射的sourceMappingURL
指令。
//# sourceMappingURL=app.min.js.map
Note that this is a relative URL. In order for the browser to download the associated source map, it must be uploaded to and served from the same destination directory as the Uglified file, app.min.js. That means if app.min.js is served from http://example.org/static/app.min.js, so too must your source map be served from http://example.org/static/app.min.js.map.
请注意,这是一个相对URL。 为了使浏览器下载相关的源地图,必须将其上传到与Uglified文件app.min.js相同的目标目录中并从该目录提供服务。 这意味着,如果从http://example.org/static/app.min.js提供 app.min.js,那么也必须从http://example.org/static/app.min提供源地图。 js.map 。
Relative URLs aren’t the only way of specifying sourceMappingURL
. You can give Uglify an absolute URL via the --source-map-url <url>
option. Or you can even include the entire source map inline, although that is not recommended. Take a look at Uglify’s command-line options for more information.
相对URL不是指定sourceMappingURL
的唯一方法。 您可以通过--source-map-url <url>
选项为Uglify提供绝对URL。 或者甚至可以内联整个源地图,尽管不建议这样做。 查看Uglify的命令行选项以获取更多信息。
Webpack (Webpack)
Webpack is a powerful build tool that resolves and bundles your JavaScript modules into files fit for running in the browser. The Sentry project itself uses Webpack (along with Babel) to assemble and transpile its ES6 + JSX codebase into browser-compatible JavaScript.
Webpack是一个功能强大的构建工具,可将JavaScript模块解析并捆绑到适合在浏览器中运行的文件中。 Sentry项目本身使用Webpack(以及Babel)将其ES6 + JSX代码库组装并转换为与浏览器兼容JavaScript。
Generating source maps with Webpack is super simple. In Webpack 4, specify the devtool
property in your config:
使用Webpack生成源地图非常简单。 在Webpack 4中,在配置中指定devtool
属性:
// webpack.config.js
module.exports = {
// ...
entry: {
"app": "src/app.js"
},
output: {
path: path.join(__dirname, 'dist'),
filename: "[name].js",
sourceMapFilename: "[name].js.map"
},
devtool: "source-map"
// ...
};
Now when you run the webpack
command-line program, Webpack will assemble your files, generate a source map, and reference that source map in the built JavaScript file via the sourceMappingUrl
directive.
现在,当您运行webpack
命令行程序时,Webpack将组装您的文件,生成源映射,并通过sourceMappingUrl
指令在构建JavaScript文件中引用该源映射。
私人来源地图 ( Private Source Maps )
Until this point, all of our examples have assumed that your source maps are publicly available and served from the same server as your executing JavaScript code. In that case, any developer could use your source maps to obtain your original source code.
到目前为止,我们所有的示例都假定您的源映射是公开可用的,并且与执行JavaScript代码的服务器位于同一服务器上。 在那种情况下,任何开发人员都可以使用您的源映射来获取原始源代码。
To prevent this, instead of providing a publicly-accessible sourceMappingURL
, you can serve your source maps from a server that is only accessible to your development team. An example would be a server that is only reachable from your company’s VPN.
为避免这种sourceMappingURL
,您可以从只能由开发团队访问的服务器提供源地图,而不是提供可公开访问的sourceMappingURL
。 例如,只能通过您公司的VPN访问的服务器。
//# sourceMappingURL: http://company.intranet/app/static/app.min.js.map
When a non-team member visits your application with developer tools open, they will attempt to download this source map but get a 404 (or 403) HTTP error, and the source map will not be applied.
当非团队成员在开发人员工具打开的情况下访问您的应用程序时,他们将尝试下载此源映射,但会收到404(或403)HTTP错误,并且不会应用该源映射。
源地图和哨兵 ( Source Maps and Sentry )
If you use Sentry to track exceptions in your client-side JavaScript applications, we have good news! Sentry automatically fetches and applies source maps to stack traces generated by errors. This means that you’ll see your original source code and not minified and/or transpiled code. Here’s how the stack trace of your unminified code looks in Sentry:
如果您使用Sentry跟踪客户端JavaScript应用程序中的异常,那么我们有个好消息! Sentry自动获取源地图并将其应用于错误生成的堆栈跟踪。 这意味着您将看到原始的源代码,而不是缩小的和/或转译的代码。 这是Sentry中未缩小代码的堆栈跟踪的样子:
![](https://i-blog.csdnimg.cn/blog_migrate/218d7db3fa45ee6689ad95d0725bd6aa.png)
Basically, if you’ve followed the steps in this little guide and your deploy now has generated, uploaded source maps and transpiled files with sourceMappingURL
directives pointing to those source maps, there’s nothing more to do. Sentry will do the rest.
基本上,如果您已按照本小指南中的步骤进行操作,并且现在您的部署已生成,上传了源映射和带有指向这些源映射的sourceMappingURL
指令的已转译文件,则无需执行其他操作。 其余将由哨兵负责。
哨兵和离线源地图 ( Sentry and Offline Source Maps )
Alternatively, instead of hosting source maps yourself, you can upload them directly to Sentry.
或者,您可以自己直接将其上传到Sentry ,而不必自己托管源地图。
Why would you want to do that? A few reasons:
你为什么想这么做? 原因如下:
- In case Sentry has difficulty reaching your servers (e.g., source maps are hosted on VPN) 如果Sentry难以访问您的服务器(例如,源地图托管在VPN上)
- Overcoming latency — source maps would be inside Sentry before an exception is thrown 克服延迟-源地图将在抛出异常之前位于Sentry中
- You’re developing an application that runs natively on a device (e.g., using React Native or PhoneGap, whose source code/maps cannot be reached over the internet) 您正在开发一个在设备上本地运行的应用程序(例如,使用React Native或PhoneGap,它们的源代码/地图无法通过Internet访问)
- Avoid version mismatches where a fetched source map doesn’t match the code where the error was thrown 在获取的源映射与抛出错误的代码不匹配的地方,避免版本不匹配
结语 ( Wrapping Up )
You just learned how source maps can save your skin by making your transpiled code easier to debug in production. Since your build tools likely already support source map generation, it won’t take very long to configure, and the results are very much worth it.
您刚刚了解了源映射如何通过使已编译的代码更易于在生产中进行调试来节省皮肤。 由于您的构建工具可能已经支持源地图生成,因此配置时间不会很长,结果非常值得。
That’s it! Happy error monitoring.
而已! 快乐的错误监控 。
翻译自: https://scotch.io/tutorials/debug-javascript-in-production-with-source-maps
javascript调试