我们来解决几个在浏览器中排查、调试时遇到的问题。
同一页面多脚本文件时不容易区分
问题
我们的脚本文件用中文命名,中文在URL中会自动编码成%E4%B8%AD%E6%96%87这种形式,因此如果一个页面有多个脚本文件,在浏览器DevTools的Network中就无法直接通过URL区分谁是谁,必须看代码。但是,开发环境的脚本文件前面是一大段模板代码,生产环境的脚本文件又是压缩的,都很难快速从代码看出是什么功能。
解决办法
构建时,在写入脚本文件之前,在脚本文件的开头附加脚本目录的路径(相对于src/,形如流程布局/流程名称/功能名称),相当于脚本文件的名称。
// code是编译、压缩(根据环境)后的脚本文件代码
// name是脚本文件的名称
code = `// ${name}\n${code}`;
现在,在Network中就只要看脚本文件的第一行就能知道是什么功能。
更进一步,很多时候看Network主要是想知道某个脚本文件是否加载了、代码是否执行了,那么,可以在脚本文件的开头写一个固定的打印,直接看控制台即可。
code = `// ${name}\nconsole.log("执行脚本: ${name}");\n${code}`;
无法断点调试
问题
虽然我们在代码块中写的是<script src="http://xxx.js">,但是OA加载脚本文件时会自动在URL后加上时间戳?_=123,这导致我们在浏览器DevTools中对脚本文件打断点,刷新页面后,断点并不会保留,因为浏览器认为前后是不同的资源。
解决办法
利用浏览器提供的sourceURL标记,该标记可以让JS文件显式声明自己的URL。
构建时,在写入脚本文件之前,先根据脚本目录的路径计算出脚本文件的URL路径部分urlPath(形如/A/B/C.js),然后在脚本文件的开头附加sourceURL标记。
// code是编译、压缩(根据环境)后的脚本文件代码
// urlPath是脚本文件的URL路径部分
code = `//# sourceURL=${urlPath}\n${code}`;
设置sourceURL后,因为每次声明的URL都相同,所以浏览器就认为前后是同一个脚本文件,断点就可以正常保留、生效了。
为什么这里sourceURL的取值为URL路径部分?sourceURL最精确的取值当然是Network中脚本文件的URL去掉时间戳,但这会包含服务器/本地的主机名、端口号,构建时无法确定。实际上,sourceURL本质就是一个别名机制,完全不影响脚本文件的获取和执行。因此,我们取对任何部署位置都统一的URL路径部分。
因为sourceURL以/开头,所以在浏览器DevTools的Source中,会看到脚本文件显示在OA的主机名下,而不是脚本文件实际部署的那个主机名。这没什么问题,因为我们的脚本文件的路径是以中文开头的,所以很容易跟OA自己的资源文件区分开。如果希望在Source中让脚本文件显示在一个单独的主机名下,则可以给sourceURL加上前缀,例如http://codeblock,此时在Source中就会看到codeblock这个主机名(同样因为是别名,这个主机名完全可以不存在)。
sourceURL还解决了在Source中脚本文件名显示为%E4%B8%AD%E6%96%87这种形式的问题,现在显示为中文了。