假设模块a,b,b2,c,d,e,f依赖如:
a b b2
\ /| |
c | |
/ \| |
d e\ |
f
即:
- 模块c依赖a,b
- 模块d依赖c
- 模块e依赖c,b
- 模块f依赖c,b2
/**
1. Gruntfile.js就是个Node模块
2. grunt plugin: commonly used task service as plugin
3. Task & Target
4. 异步task ?
5. 配置
不能做什么
- The optimizer cannot load network resources
Task执行函数
- return false
*/
var requirejs = require('requirejs');
var path = require('path');
// Wrap function
module.exports = function(grunt) {
/**
- Project configuration,ConfigData
- Task configuration取ConfigData中跟task同名的属性
*/
grunt.initConfig({
});
grunt.registerTask('demo1',function() {
var r,w;
var done = this.async();
var config = {
appDir: '../src',baseUrl: './scripts',optimize: 'none',// 不使用uglifyJs处理
dir: '../dest',mainConfigFile: '../mainConfigFile.js',/**
* dirOptimize方式不会进行模块依赖解析。这个跟modules方式指定的优化方式不一样。
*/
//skipDirOptimize: true,/**
* 背景:模块解析过程大致是:
1. 读取模块文件内容,
2. 然后根据内容(字符串)解析该模块依赖,并依次递归的方式解析各个依赖(即重复步骤1,2,3)
3. 把模块的所有依赖优化处理并写入bundle
4. 优化模块本身并写入bundle
* 读取模块文件时会调用该回调函数。即上述步骤1执行完且步骤2执行前调用。可以动态修改内容。
* 所有进行优化的模块都会调用
*/
onBuildRead: function (moduleName,path,contents) {
console.log('onBuildRead--->' + moduleName)
// if(!r) {
// r= true;
// //contents = contents.replace(/a/,'b');
// console.log(contents)
// }
return contents;
},/**
所有进行优化的模块都会调用
*/
onBuildWrite: function (moduleName,contents) {
grunt.log.ok('onBuildWrite--->' + moduleName)
// if(!w) {
// w= true;
// console.log(contents)
// }
return contents;
},onModuleBundleComplete: function(data) {
console.log('onModuleBundleComplete--->' + data.name + '\n')
},/**
指定进行优化处理(optinized)的模块。每个指定的元素都是生成一个bundle。该bundle包含指定的模块,以及该模块的依赖和依赖的依赖
*/
modules: [
{
name: 'c',//exclude: ['a']
},// {
// name: 'e',// 场景1:模块c和其依赖都不打入bundle。 e bundle里只有模块e,虽然模块b也是模块e的直接依赖,但也是模块c的依赖故也被排除了。
// 原因:模块e依赖c,a,b。排除的依赖:c,b
// 场景2:模块c也配置了exclude: ['a'],则模块c和其依赖b不打入bundle,但模块a会打入bundle.
// 原因:模块e依赖c,b。模块a被模块c排除了,所以对于模块e不记为被排除,负负得正。
// 场景3:模块e没有配置exclude,则模块c和其依赖都打入bundle,不管模块c是否配置exclude。
// 一句话:最终的bundle = name模块(如果有) + 模块的所有依赖 - exclude指定模块和模块的依赖
// //exclude: ['c']
// },// {
// name: 'd'
// },// {
// name: 'f'
// }
],}
console.log(JSON.stringify(requirejs))
requirejs.optimize(config,function (buildResponse) {
done();
},function(err) {
grunt.log.error(err)
});
});
// r.js
grunt.registerTask('requirejs',function () {
var done = this.async();
var config = {
appDir: '../src',//name: 'main',// 不使用uglifyJs处理
//out: './build/main-build.js',paths: {
onlineSrc: 'empty:',text: path.join(__dirname,'text')
},//include: ['four'],//excludeShallow: ['two']
/* 多文件输出 */
//skipDirOptimize: true,// 如果optimize: 'none',那这个配置也没意义了。
dir: '../dest/multi',stubModules: ['text'],//A function that if defined will be called for every file read in the
//build that is done to trace JS dependencies. This allows transforms of
//the content.
onBuildRead: function (moduleName,contents) {
console.log('onBuildRead--->' + moduleName)
//Always return a value.
//This is just a contrived example.
return contents.replace(/foo/g,'bar');
},onBuildWrite: function (moduleName,contents) {
// text模块已存在框架里面
if (moduleName == 'text') {
return '';
}
return contents;
},modules: [{
name: 'main',exclude: ['one','two']
}],optimizeCss: false,//inlineText: false,onModuleBundleComplete: function(data) {
console.log('\n************************')
console.log(data)
}
}
// function parseModuleName(contents) {
// var matchs,// moduleNames = [],// regExp = /define\(\'([^']+)/gm;
// while((matchs = regExp.exec(contents)) !== null) {
// moduleNames.push(matchs[1]);
// }
// return moduleNames;
// }
requirejs.optimize(config,function(err) {
grunt.log.error(err)
});
});
}