最近用gulp压缩了一下requirejs项目中的文件,出现了让人很纠结的错误,原代码html
define(funciton(require){ var $ require = $("jquery"); });
压缩后:jquery
define(function(n){var $ = n("jquery")}); 报错:Uncaught Error: Module name "jquery" has not been loaded yet for context
能够看到压缩先后惟一的区别就是,函数名require被替换了更精简的n。讲道理require做为一个形参,叫啥名字应该都不要紧的,可恰恰就出了错。
更神奇的是只要将函数内部的n改为require就不报错了:git
define(function(n){var $ = require("jquery")});
蛋疼,明明传进来的是n,哪来的require啊。
虽然局部require只是requirejs的一个语法糖,但没道理压缩后就会报错啊。一番搜索后终于找到缘由。
根据官网文档局部require最终会被转化为define([])形式,可是转化的方法比较特殊,是经过Function.prototype.toString()来获取依赖值的。问题就出在这个Function.prototype.toString()方法上,它将整个回调函数转成了string,而后在string中经过"require"字符串来寻找依赖。因此,局部require不能被替换成其它名字,并且require()中不能放变量或者path,由于转成字符串后可识别不出这些。
其实,在执行Function.prototype.toString()前会执行另外一个方法,参考文章得知,首先会执行unction.prototype.length来判断回调函数中有几个参数,1个参数时就认为传入了require,2个参数时就认为传入了require和exports,3个参数时认为传入了require,exports和module。这也是为何github
define(function(n){var $ = require("jquery")});
可以正常运行的缘由。
官网推荐的解决办法是全改为常规的define([])来定义依赖。
我目前的作法是配置gulp不压缩name:gulp
var uglify = require("gulp-uglify"); gulp.task("default",function(){ gulp.src(path).pipe(uglify({mangle:false})); });
但愿此文章对你们有所帮助。api