关于seaJs合并压缩(gulp-seajs-combine )路径与文件ID匹配问题。
前段时间和有大家介绍过用 gulp-seajs-combine 来打包seaJs文件。大家会发现合并seaJs一个很奇怪的现象,那就是它的 ID和路径匹配原则。使得有些文件已经合并过去了,但还是会提示会去加载这些文件。更可怕的是404 Not Found
加载不到文件
。俗话说办法总比困难多,就算坑再多也会有先驱帮我们去填的(不好意思,又装逼了)。下面用个实例来讲讲:
一般我的做比较大型一点的项目的时候,前端会按项目把文件细分到各文件夹,以便管理。例如下图:
这个项目分有共公的common文件夹,各子站点的像list,user,www站点文件夹。这里就拿www文件夹来做个简单的例子。
我们先来看下index.html文件
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>this is seaCombo test</title> 6 </head> 7 <body> 8 <p> 9 this is seaCombo test 10 </p> 11 12 <script type="text/javascript" src="./src/common/js/sea.js" charset="utf-8"></script> 13 <script type="text/javascript"> 14 seajs.use('./src/www/js/main'); //未压缩 15 </script> 16 17 <!-- <script type="text/javascript" src="./dist/common/js/sea.js" charset="utf-8"></script> 18 <script type="text/javascript" src="./dist/www/js/main.js" charset="utf-8"></script> 压缩的js引用--> 19 </body> 20 </html>
www文件夹下的js文件,main.js
1 define(function(require, exports, module) { 2 var cmmon = require('../../common/js/cmmon');// common下的共公Js 3 var b = require('./b'); //www 站点下的文件 4 var c = require('./c'); //www 站点下的文件 5 var $ = require('jquery'); 6 7 exports.init = function() { 8 console.log('1111'); 9 // 点击body 时才加载的d.js 10 function bodyClick() { 11 require.async('../../common/js/async/d', function(d) { 12 console.log('d='); 13 d.init(); 14 }); 15 } 16 $('body').on('click', bodyClick); 17 }; 18 exports.init(); 19 });
b.js
1 define(function(require, exports, module) { 2 var $ = require('jquery'); 3 exports.init = function() { 4 console.log('this is b.js'); 5 }; 6 exports.init(); 7 })
c.js
1 define(function(require, exports, module) { 2 var $ = require('jquery'); 3 exports.init = function() { 4 console.log('this is c.js') 5 }; 6 exports.init(); 7 })
common下的cmmon.js
1 define(function(require, exports, module) { 2 exports.init = function() { 3 console.log(' this is common.js') 4 }; 5 exports.init(); 6 })
common文件夹下有个按需加载的d.js
1 define(function(require, exports, module) { 2 var $ = require('jquery'); 3 var mod={}; 4 mod.init = function() { 5 console.log("this is async d.js"); 6 console.log('$'+$); 7 }; 8 module.exports = mod; 9 })
*关于jquery 这个文件怎么用别名,请查看 seajs.org相关文档。
用运行环境的方式打开index文件。我们看到
点击body后 common/js/async/d.js也加载了进来。
到目前为止,一切都正常。我们就先当这个www站点已经开发完成了,要进行js合并。
合并前,需要先改造一下www/js的main.js文件,手动添加文件ID与文件入口。
1 define('main',function(require, exports, module) { 2 var cmmon = require('../../common/js/cmmon');// common下的共公Js 3 var b = require('./b'); //www 站点下的文件 4 var c = require('./c'); //www 站点下的文件 5 var $ = require('jquery'); 6 7 exports.init = function() { 8 console.log('1111'); 9 // 点击body 时才加载的d.js 10 function bodyClick() { 11 require.async('../../common/js/async/d', function(d) { 12 console.log('d='); 13 d.init(); 14 }); 15 } 16 $('body').on('click', bodyClick); 17 }; 18 exports.init(); 19 }); 20 seajs.use('main');
来看下 gulpfile文件
1 var gulp = require('gulp'); 2 var seajs = require('gulp-seajs-combine');//seaJS 合并 3 var uglify = require('gulp-uglify');//js压缩 4 gulp.task('jscombine', function() { 5 return gulp.src('./src/www/js/main.js') 6 .pipe(seajs(null, { 7 except: ['jquery']//排除合并对象 8 })) 9 .pipe(uglify({ 10 mangle: {except: ['require', 'exports', 'module','$']},//排除混淆关键字 11 compress: true //类型:Boolean 默认:true 是否完全压缩 12 })) 13 .pipe(gulp.dest('./dist/www/js')); 14 });
运行下 jscombine这个任务
会到到dist/www/js里多了一个main.js文件
先来看下这个main.js文件
1 define("../../common/js/cmmon",[],function(require,exports,module){exports.init=function(){console.log(" this is common.js")},exports.init()}),define("c",["jquery"],function(require,exports,module){require("jquery");exports.init=function(){console.log("this is c.js")},exports.init()}),define("b",["jquery"],function(require,exports,module){require("jquery");exports.init=function(){console.log("this is b.js")},exports.init()}),define("main",["../../common/js/cmmon","b","c","jquery"],function(require,exports,module){var $=(require("../../common/js/cmmon"),require("b"),require("c"),require("jquery"));exports.init=function(){function n(){require.async("../../common/js/async/d",function(n){console.log("d="),n.init()})}console.log("1111"),$("body").on("click",n)},exports.init()}),seajs.use("main");
omg,完全不怎么好看是吧。先格式化一下再来看。
define("../../common/js/cmmon", [], function(require, exports, module) { exports.init = function() { console.log(" this is common.js") }, exports.init() }), define("c", ["jquery"], function(require, exports, module) { require("jquery"); exports.init = function() { console.log("this is c.js") }, exports.init() }), define("b", ["jquery"], function(require, exports, module) { require("jquery"); exports.init = function() { console.log("this is b.js") }, exports.init() }), define("main", ["../../common/js/cmmon", "b", "c", "jquery"], function(require, exports, module) { var $ = (require("../../common/js/cmmon"), require("b"), require("c"), require("jquery")); exports.init = function() { function n() { require.async("../../common/js/async/d", function(n) { console.log("d="), n.init() }) } console.log("1111"), $("body").on("click", n) }, exports.init() }), seajs.use("main");
看到了吧,cmmon.js,b.js,c.js都合并到了main.js这里,并且入口 seajs.use("main")也在main.js文件里。
来改造之前的index.html文件,把js的路径指向dist文件
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>this is seaCombo test</title> 6 </head> 7 <body> 8 <p> 9 this is seaCombo test 10 </p> 11 <!-- 12 <script type="text/javascript" src="./src/common/js/sea.js" charset="utf-8"></script> 13 <script type="text/javascript"> 14 seajs.use('./src/www/js/main'); //未压缩 15 </script> 16 --> 17 <script type="text/javascript" src="./dist/common/js/sea.js" charset="utf-8"></script> 18 <script type="text/javascript" src="./dist/www/js/main.js" charset="utf-8"></script> 19 </body> 20 </html>
再次用运行环境的方式打开index文件。
看的出来,b.js与c.js已经成功的合并到了main.js里,但cmmon.js这个文件出现了问题。虽然cmmon.js文件合并到了main.js里面,但还是再次去加载了这个文件,并告诉我们加载不到。这个路径id“../../common/js/cmmon” 的问题所引发的。
果不其然啊。。。
前面有说过,办法总比困难多。可以学seaJs的精神,你不兼容我,那么我就去兼容你好了。
先来改造一下gulpfile.js
1 var gulp = require('gulp'); 2 var seajs = require('gulp-seajs-combine');//seaJS 合并 3 var uglify = require('gulp-uglify');//js压缩 4 gulp.task('jscombine', function() { 5 return gulp.src('./src/www/js/main.js') 6 .pipe(seajs(null, { 7 base: '../../common/js/', 8 alias: { //合并的 js 列表以外的按 seajs.config{alias: {……} }别名加载 9 'cmmon': 'cmmon' 10 }, 11 except: ['jquery'] //强行排除 12 })) 13 .pipe(uglify({ 14 mangle: {except: ['require', 'exports', 'module','$']},//排除混淆关键字 15 compress: true //类型:Boolean 默认:true 是否完全压缩 16 })) 17 .pipe(gulp.dest('./dist/www/js')); 18 });
再来改造一下src下的main.js
1 define('main',function(require, exports, module) { 2 var cmmon = require('cmmon');// common下的共公Js 3 var b = require('./b'); //www 站点下的文件 4 var c = require('./c'); //www 站点下的文件 5 var $ = require('jquery'); 6 7 exports.init = function() { 8 console.log('1111'); 9 // 点击body 时才加载的d.js 10 function bodyClick() { 11 require.async('../../common/js/async/d', function(d) { 12 console.log('d='); 13 d.init(); 14 }); 15 } 16 $('body').on('click', bodyClick); 17 }; 18 exports.init(); 19 }); 20 seajs.use('main');
细心的你看到区别了吗?把cmmon.js弄成别名去合并,运行jscombine 任务后
格式化看下dist/www/js/main.js
1 define("cmmon", [], function(require, exports, module) { 2 exports.init = function() { 3 console.log(" this is common.js") 4 }, exports.init() 5 }), define("b", ["jquery"], function(require, exports, module) { 6 require("jquery"); 7 exports.init = function() { 8 console.log("this is b.js") 9 }, exports.init() 10 }), define("c", ["jquery"], function(require, exports, module) { 11 require("jquery"); 12 exports.init = function() { 13 console.log("this is c.js") 14 }, exports.init() 15 }), define("main", ["cmmon", "b", "c", "jquery"], function(require, exports, module) { 16 var $ = (require("cmmon"), require("b"), require("c"), require("jquery")); 17 exports.init = function() { 18 function n() { 19 require.async("../../common/js/async/d", function(n) { 20 console.log("d="), n.init() 21 }) 22 } 23 console.log("1111"), $("body").on("click", n) 24 }, exports.init() 25 }), seajs.use("main");
看到 define("cmmon", [], function(require, exports, module) { 这行了吧。这就说明已经有cmmon这个别名的文件合并了进来。这时再来看下index的环境运行结果
还有点击一下body,看按需加载的d.js是否也ok
nice了吧,这回又可以愉快的装逼了吧。