关于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了吧,这回又可以愉快的装逼了吧。

posted @ 2016-04-12 14:14  吹水哥  阅读(826)  评论(0编辑  收藏  举报