js
压缩js
压缩对前端开发者来讲是一门必修课。javascript
通常来讲,压缩 js
主要出于如下两个目的:html
压缩 js
使用的工具库:前端
es5
es6+
google
的 js
压缩、优化工具压缩 js
的主要过程:java
去掉全部对解析引擎来讲无用的字符,包括空格、注释、换行、没有用的变量声明、函数声明等。webpack
把一些局部变量名称、函数名称等用 a, b, ...
、$1, $2, ...
、_1, _2, ...
之类的简略字符进行替换,达到混淆的目的。git
源代码es6
(function () { var hello = 'hi'; var print = function (str) { console.log(str); }; print(hello); })();
压缩后的代码(仅演示混淆功能)github
(function () { var a = 'hi'; var b = function (c) { console.log(c); }; b(a); })();
把不依赖外部环境的逻辑提早进行运算,并把运算结果替换到相应的源码处,而后从源码中移除这段逻辑。web
源代码浏览器
(function () { var hello = 'hi' + ' everyone, '; var count = 3 * 5; console.log(hello + count + ' girls'); })();
压缩后的代码(仅演示预编译功能)
(function () { var hello = 'hi everyone, '; var count = 15; console.log(hello + count + ' girls'); })();
对于 js
来讲,嵌套越深,执行越慢,对代码进行扁平化处理也是优化代码的一种方式。
源代码
(function () { var say = { hello: function (str) { console.log('hello ' + str); } }; say.hello('everyone'); })();
压缩后的代码(仅演示扁平化结构功能)
!function(str){console.log("hello "+str)}("everyone");
源代码
(function () { var say = { hello: function (str) { console.log('hello ' + str); } }; say.hello('everyone'); })();
压缩后的代码
!function(l){console.log("hello "+l)}("50 girls");
sourcemap
一般 js
压缩后只有一行代码,而且里面的变量名与函数名等都是混淆了的,这在实际运行中会有一个问题,就是 js
的报错信息将会失真,没法追踪到是在源代码哪一行哪一列报的错。
sourcemap
即是为了解决这个问题而生的。
sourcemap
文件就是记录了从源代码文件到压缩文件的一个代码对应关系记录表,经过压缩文件和 sourcemap
文件能够原本来本找出源代码文件。
查看阮一峰老师的 JavaScript Source Map 详解 了解 sourcemap
的原理与格式。
通常在压缩 js
的过程当中,会生成相应的 sourcemap
文件,而且在压缩的 js
文件末尾追加 sourcemap
文件的连接 //# sourceMappingURL=bundle-file-name.js.map
。这样,浏览器在加载这个压缩 js
的时候,就知道还有一个相应的 sourcemap
文件,也一并加载下来,运行的过程当中若是 js
报错,也会给出相应源代码的行号与列号,而非压缩文件的。
好比,对下面的源码进行压缩:
(function () { var say = { hi: function () { console.log('hi'); } }; say.hello(); return say; })();
未加 sourcemap
文件时,报错信息是:
加上 sourcemap
文件时,报错信息是:
sourcemap
扩展webpack 对 sourcemap
作了扩展,定义在 devtool
配置项中:
eval
: 每一个模块都使用 eval()
执行,而且都有 //@ sourceURL
,构建很快,但没法正确显示行号eval-source-map
: 每一个模块使用 eval()
执行,而且 source map
转换为 DataUrl
后添加到 eval()
中,通常开发模式中使用这种方式cheap-eval-source-map
: 相似 eval-source-map
,但只映射行,不映射列,并忽略源自 loader
的 source map
,仅显示转译后的代码cheap-module-eval-source-map
: 相似 cheap-eval-source-map
,但会保留源自 loader
的 source map
inline-source-map
: source map
转换为 DataUrl
后添加到 bundle
中cheap-source-map
: 只映射行,不映射列,并忽略源自 loader
的 source map
,仅显示转译后的代码inline-cheap-source-map
: inline-source-map
与 cheap-source-map
的结合cheap-module-source-map
: 相似 cheap-module-eval-source-map
,但不使用 eval()
执行inline-cheap-module-source-map
: inline-source-map
与 cheap-module-source-map
的结合source-map
: 整个 source map
做为一个单独的文件生成,产品环境通常使用这种模式hidden-source-map
: 相似 source-map
,但不会把 //# sourceMappingURL=bundle-file-name.js.map
追加到压缩文件后面nosources-source-map
: 相似 source-map
,但只有堆栈信息,没有源码信息更详细信息能够参考:
对于使用 webpack 来构建项目,建议在开发时使用 eval-source-map
,产品环境使用 source-map
。
由于用压缩文件与 sourcemap
文件是能够原本来本的找到源代码的,因此,为了保护源代码,能够这样隐藏 sourcemap
文件:
web
服务器设置外部不能访问 sourcemap
文件,只能内部访问sourcemap
文件存放到其余地方sourcemap
查找原始报错信息通常而言,在产品阶段,咱们会用 window.onerror
来捕获 js
报错,而后上报到服务器,以此来收集用户使用时发生的 bug
:
window.onerror = function(message, source, lineno, colno, error) { // message: 错误信息 // source: 报错脚本的 url 地址 // lineno: 行号 // colno: 列号 // error: 错误对象 // 上报必要的信息到服务器 }
但产品环境的代码都是压缩的,行号和列号都是失真的,因此就须要用 sourcemap
文件来找到错误对应源代码的行号与列号,以及其余的信息。
使用工具: mozilla/source-map
源代码
(function () { var say = { hi: function () { console.log('hi'); } }; say.hello(); return say; })();
压缩后报错信息
window.onerror = function(message, source, lineno, colno, error) { console.log(`message: ${message}`); console.log(`source: ${source}`); console.log(`lineno: ${lineno}`); console.log(`colno: ${colno}`); console.log(`error: ${error}`); } // message: Uncaught TypeError: e.hello is not a function // source: url/to/bundle.min.js // lineno: 1 // colno: 982 // error: TypeError: e.hello is not a function
经过 source-map
查找原始报错信息
const fs = require('fs'); const SourceMap = require('source-map'); const { readFileSync } = fs; const { SourceMapConsumer } = SourceMap; const rawSourceMap = JSON.parse(readFileSync('path/to/js/map/file', 'utf8')); SourceMapConsumer.with(rawSourceMap, null, consumer => { const pos = consumer.originalPositionFor({ line: 1, column: 982 }); console.log(pos); });
查找到的原始信息
{ source: 'path/to/index.js', line: 8, column: 7, name: 'hello' }
这样,便找到了原始报错信息:
path/to/index.js
hello
如此,便能一会儿就找到错误在哪里了。
更多用法,参考 mozilla/source-map
更多博客,查看 https://github.com/senntyou/blogs
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)