UNPKG

gulp-alias-combo

Version:

一个根据alias配置合并js文件的gulp插件,合并时会自动提取模块间的依赖

197 lines (183 loc) 5.64 kB
/* * alias module combo pulgin for gulp * Author : mukezhai@gmail.com * Date : 2015-06-03 */ var through = require('through2') var gutil = require('gulp-util') var fs = require('fs') var path = require('path') var PLUGIN_NAME = 'gulp-alias-combo' var requireReg = /require\s*\(\s*(["'])(.+?)\1\s*\)/g var requirejsReg = /require(js)?\s*\(\s*\[(.+?)\]/g var commentReg = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg /* * 提取模块中的依赖 * param { String } content 文件内容 * param { Object } options 配置参数 * param { filePath } filePath 文件路径 * return 提取的依赖存到options里 */ function analyseDeps(content, options, filePath){ content = content.replace(commentReg, '') var deps = getDeps(content) if(deps.length > 0){ options[filePath] = options[filePath] || {} deps.forEach(function(dep){ if(dep){ if(options.alias && options.alias[dep]){ options[filePath][dep] = mergePath(dep, options) analyseDeps(readModule(dep, options), options, filePath) } } }) } } /* * 使用正则提取依赖 * param { String } content 内容 * return { Array } 提取的依赖 */ function getDeps(content){ var deps = [], moduleId, moduleIds var requires = content.match(requireReg) if(requires){ requires.forEach(function(dep){ moduleId = dep.substring(dep.indexOf('(') + 1, dep.lastIndexOf(')')).trim() moduleId = moduleId.substring(1, moduleId.length-1) deps.push(moduleId) }) } requires = content.match(requirejsReg) if(requires){ requires.forEach(function(dep){ moduleIds = eval(dep.substring(dep.indexOf('['), dep.lastIndexOf(']') + 1)) if(moduleIds && moduleIds.length > 0){ deps = deps.concat(moduleIds) } }) } return deps } /* * 读取依赖的文件内容 * param { String } moduleId 模块ID * param { Object } options 配置参数 * return { String } 模块内容 */ function readModule(moduleId, options){ var content, filePath = mergePath(moduleId, options) try{ content = fs.readFileSync(filePath) return content.toString() }catch(e){ gutil.log(gutil.colors.red('Can not find ' + moduleId + ':[' + filePath + ']')) } } /* * 获取模块ID对应的文件地址 * param { String } moduleId 模块ID * param { Object } options 配置参数 * return { String } 文件地址 */ function mergePath(moduleId, options){ return options.baseUrl + options.alias[moduleId] } /* * 根据模块路径获取模块的ID * param { String } filePath 文件路径 * param { Object } options 配置参数 * return { String } 模块ID */ function getModuleId(filePath, options){ var moduleId = '' for(var key in options.alias){ if(path.normalize(mergePath(key, options)) == path.normalize(filePath)){ moduleId = key } } return moduleId } /* * 获取模块ID对应的文件地址 * param { String } moduleId 模块ID * param { String } filePath 配置参数 * return { String } 文件地址 */ function tranform(moduleId, filePath){ var content = fs.readFileSync(filePath).toString() content = content.replace(/define\s*\(/, 'define("' + moduleId + '", ') return new Buffer(content) } /* * 合并依赖的模块到入口文件中 * param { Object } deps 依赖的模块 * param { String } filePath 入口文件路径 * param { String } moduleId 入口文件对应的模块ID * return { Buffer } 合并后的Buffer */ function concatDeps(deps, filePath, moduleId){ var buffers = [] for(var key in deps){ buffers.push(new Buffer('\n'), tranform(key, deps[key])) } if(moduleId){ buffers.push(tranform(moduleId, filePath)) }else{ buffers.push(fs.readFileSync(filePath)) } return Buffer.concat(buffers) } /* * 判断数组中是否含有某个元素 * param { Array } array 数组 * param { String,Int } e 要判断的元素 * return { Boolean } 是否含有此元素 */ function inArray(array, e){ for(i=0; i<array.length && array[i]!=e; i++); return !(i==array.length) } /* * 打印构建日志 * param { filePath } filePath 构建的文件 * param { Object } e 依赖的模块 */ function buildLog(filePath, deps){ gutil.log(gutil.colors.green('build ' + filePath + ':')) for(var key in deps){ console.log(' ' + key + ':[' + deps[key] + ']') } } /* * 插件入口函数 * param { Object } options 配置参数,必须参数 */ function combo(options){ return through.obj(function(file, enc, callback){ if(!options){ gutil.log(gutil.colors.red(PLUGIN_NAME, 'The options param is required')) return callback() } if(!options.alias){ gutil.log(gutil.colors.red(PLUGIN_NAME, 'The option alias is required')) return callback() } if(!options.baseUrl){ gutil.log(gutil.colors.red(PLUGIN_NAME, 'The option baseUrl is required')) return callback() } if(file.isBuffer()){ var moduleId = getModuleId(file.path, options) analyseDeps(file.contents.toString(), options, file.path) file.contents = concatDeps(options[file.path], file.path, moduleId) buildLog(file.path, options[file.path]) callback(null, file) } else{ callback(null, file) } }) } module.exports = combo