在Visual Studio 2015中调试捆绑的javascript

时间:2015-09-07 20:32:24

标签: javascript visual-studio debugging webpack source-maps

我正在使用带有这个简单配置文件的WebPack捆绑我的应用程序。

var path = require('path');

module.exports = {
    debug: true,
    devtool: 'source-map',

    context: path.join(__dirname, 'js'),
    entry: './main.js',
    output: {
        path: path.join(__dirname, 'Built'),
        filename: '[name].bundle.js'
    }
};

这会创建源映射,我可以轻松地在所有流行的浏览器中调试我的原始javascript文件。但是,在Visual Studio中设置断点并运行项目不起作用,断点被禁用说“没有为此文档加载符号”。我正在通过IE11进行调试,可以通过Visual Studio立即调试简单的javascript,但是在捆绑之后这不再适用了。

有一个迹象表明源映射有效,因为我进入了控制台输出Unsupported format of the sourcemap。生成上面使用配置的源地图如下所示

{"version":3,"sources":["webpack:///webpack/bootstrap 2919a5f916c286b8e21a","webpack:///./main.js","webpack:///./structure_editor/content.js","webpack:///./structure_editor/test_bundle.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;ACtCA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;;;;;;ACVA,8C;;;;;;ACAA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,6B","file":"main.bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 2919a5f916c286b8e21a\n **/","document.write(require(\"./structure_editor/content.js\"));\r\nvar TestBundle = require(\"./structure_editor/test_bundle.js\");\r\n\r\nvar test = new TestBundle();\r\ntest.testMe();\r\n\r\n//var StructureEditor = require(\"./structure_editor/structure_editor.js\");\r\n\r\n//var editor = new StructureEditor(0x00FF00);\r\n\r\n//editor.run();\r\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./main.js\n ** module id = 0\n ** module chunks = 0\n **/","module.exports = \"It works from content.js.\";\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./structure_editor/content.js\n ** module id = 1\n ** module chunks = 0\n **/","var TestBundle = function () {\r\n    \r\n}\r\n\r\nTestBundle.prototype.testMe = function() {\r\n    var a = 10;\r\n    var b = 12;\r\n    var c = a + b;\r\n    document.write(c);\r\n};\r\n\r\nmodule.exports = TestBundle;\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./structure_editor/test_bundle.js\n ** module id = 2\n ** module chunks = 0\n **/"],"sourceRoot":""}

所以我可以理解,由于webpack://可能不支持这种格式(尽管IE确实理解它)。但是,如果我知道VS的正确格式如何,我可能能够调整webpack来生成这样的格式。

我要求任何想法,教程,......无论如何工作。

2 个答案:

答案 0 :(得分:5)

我没有完整解决问题的方法,但我确实缩小了一点。

要确保的第一件事是Visual Studio可以使用源映射和原始文件的路径。我发现其中一些请求是将登录页面作为响应。我授予了对地图和ts文件的匿名访问权限。我确实尝试使用适用于Visual Studio的ts文件的绝对文件系统路径,但浏览器似乎并不高兴。

据我所知,以下是配置SourceMapDevToolPlugin插件的快捷方式。直接进入插件可以让您更好地控制生成的源地图。

devtool: 'source-map'

这意味着用以下内容替换上面的行。

config.plugins.push(new webpack.SourceMapDevToolPlugin({
    filename: '[file].map',
    moduleFilenameTemplate: "[resource-path]",
    fallbackModuleFilenameTemplate: "[resource-path]?[hash]"
}));

请注意[absolute-resource-path]宏,它将导致Visual Studio可以用来访问文件的文件系统路径,而无需通过网站加载它们。这些是在sources属性中输出的,反斜杠使用第二个反斜杠进行转义(例如,C:\ Projects \ ...)。正如我上面提到的那样,这打破了浏览器中的调试。

此外,[resource-path]宏似乎在调试期间被解析,就好像它是相对于包含源映射的文件夹一样。这对我的设置不正确。我添加了一个前缀,并使用类似于以下内容的方法对其进行排序。

"../../app/[resource-path]"

下一个问题是映射属性中某些行的最后一个段(在映射文件中)。这个explanation of the source map format在这里非常有帮助,但是你需要知道的是,半冒号分隔线条,每条线条可以有多个用逗号分隔的段。这些段可以编码以下信息。

  • 生成的列
  • 原始文件出现在
  • 原始行号
  • 原始专栏
  • 如果有原始名称。

我发现如果我删除了Visual Studio可以处理地图的行末端的任何短段,我可以在原始文件中设置断点等(转换为javascript的Typescript文件,然后捆绑在我的案例中) )。

要删除短片段,我在Visual Studio中为每个地图文件使用了以下手动过程。请注意,通过右键单击文档正文并从上下文菜单中选择“格式化文档”,我发现在格式化文件后,我发现更容易解释文件。

  • 在启用正则表达式的情况下执行替换操作。在查找字段中使用以下表达式,并使用$ 1作为要替换的值。

    ,\ S * [^ \ s \ “的;({1,3}; | \)?”

enter image description here

这将替换行末尾只包含1,2或3个字符的所有段。

在行的末尾设置断点可能会有问题,但到目前为止我还无法破解它。我确实注意到,当有错误导致执行在调试器中停止时,行并不总是匹配 - 可能是这种操作的结果?

我还写了一个小的控制台应用程序,它将对给定文件夹中的所有地图文件执行此修改。我在构建结束时自动运行它。

    static void Main(string[] args)
    {
        var sourceMapFolder = new DirectoryInfo(args[0]);

        foreach (var sourceMapFile in sourceMapFolder.EnumerateFiles("*.map"))
        {
            var sourceMapFilePath = sourceMapFile.FullName;

            var regex = new Regex(",\\s*[^\\s\\\";]{1,3}?(;|\\\")");

            var oldContent = File.ReadAllText(sourceMapFilePath);

            var newContent = regex.Replace(oldContent, "$1");

            File.WriteAllText(sourceMapFilePath, newContent);
        }
    }

我不确定Webpack是否应该生成段或Visual Studio应该处理它们。

更新:我在Visual Studio的Connect网站上创建了一个Bug来解决此问题。

答案 1 :(得分:1)

我找到了解决问题的方法。

在webpack.config.js中添加此插件

plugins: [
  new webpack.SourceMapDevToolPlugin(
    sourceMapFilename, null,
    "[absolute-resource-path]", "[absolute-resource-path]")
]

sourceMapFilename应该是您的包的名称 如果使用多个入口点,也可以使用[name]标签。

从webpack.config.js

中删除它
devtool: 'source-map'

现在,当您使用Internet Explorer在VS中开始调试时,您应该点击在.ts文件中设置的断点。

来源:https://github.com/webpack/webpack/issues/238

希望这有帮助。