gulp项目构建小结(续)

来源:互联网 发布:去分化 细胞编程 编辑:程序博客网 时间:2024/06/05 17:57

最近抽时间重新调整了下gulp任务,把所有模块都独立了出来。

源码放在了github上:

kick   (名字随意起的,不要在意这些细节。


这个项目主要是提供了一种对前端项目开发及部署的解决方案。

包含了开发时的ES6的支持(babel),模块打包(browserify)以及同步刷新浏览器等动作。

同时还有项目部署时文件的压缩,添加MD5戳等操作。

另外单独提供了文件合并的方法。(实际上使用的是gulp的文件合并方法)


对于不同项目的不同结构目录提供了配置文件(config.json)。


这个项目大多数都是gulp任务的简单配置。提供最大的便捷在于ES6模块之间的依赖查找。

事情是这样的。。。

使用babelify结合browserify是可以根据import导入的模块路径查找到对应的模块的,并且每次编辑这个文件都会触发watch,将ES6编译成ES5并刷新浏览器,听起来没什么问题,不是吗?

可事实上不是这样的,考虑下面的情况:

如果有文件a.js,import了文件b.js,并且html中引用的是a.js,当你修改b.js的时候虽然会触发watch操作,但编译的是b.js,而不是a.js,所以当你修改了被依赖的模块,主文件并不会收到通知、进行编译。


所以FileDevManager就是用来解决这个问题的(我并不清楚市面上有没有对应的解决方案,为了更好管理我自己写了一个)。

/** 所有文件的依赖管理器*1、在每次更新文件时应该坚持依赖对象是否有变化*   2、初始化形成相对于gulp执行时目录的绝对路径*/var fs = require('fs');var fileDevManager = (function(){var FileDevMaps = [],updateFileDevMaps = (function(rimports, rmodule){/*** 根据传入的文件夹前缀和当前依赖文件的路径返回正确的前缀和依赖文件的路径*/var rfolderFile = /(.+\/)(.+)$/,filePathManager = (function(){var rprevs = /\.\.\//g;var rstripFile = /(.+\/).+?\/$|^.+?\/$/;var rfolders = /(?:\.\/)(.+\/)(.+)$/;var rcurrentPath = /^\.\//;var pathCache = {};return {getCurrentFilePathWithPrefix: function (file, prefix){if(!prefix || pathCache[file]){return pathCache[file];}var prevs = file.match(rprevs);var tmp = file;if(prevs){while(prevs.length && prefix){prefix = prefix.replace(rstripFile, '$1');file = file.replace(prevs.pop(), '');}}var ret = file.match(rfolders);if(ret){prefix = prefix + ret[1];file = ret[2];}else{file = file.replace(rcurrentPath, '');}ret = (prefix+file).match(rfolderFile);return this.setPathWithFile(ret[2], ret[1]);},setPathWithFile: function(file, path){return pathCache[path+file] = {file: file,prefix: path};},getFullMap: function(){return pathCache;}};})(),rprefix = /(.+\/|)/;return function(results, prefix){if(!Array.isArray(results)){if(!prefix){var ret = results.match(rfolderFile);results = ret[2];prefix = ret[1];}results = [results];}//results.length=8;/*** 每个文件对应该文件的所在路径前缀 => 为了得到依赖文件的正确路径!*/results.forEach(function(tmp){var ret = filePathManager.getCurrentFilePathWithPrefix(tmp);if(ret){FileDevMaps[tmp] = mapDev(tmp, ret.prefix);}else{filePathManager.setPathWithFile(tmp, prefix+tmp.match(rprefix)[0]);FileDevMaps[prefix+tmp] = mapDev(prefix+tmp, prefix);}});//console.log(filePathManager.getFullMap())function mapDev(tmp, oprefix){//tmp = tmp.replace(rprevs, '');if(!fs.existsSync(tmp)){console.log('can\'t find the ', tmp);return [];}return (fs.readFileSync(tmp, "utf-8").match(rimports) || []).map(function(i){var ret = i.match(rmodule),module = ret[1] + ".js";var prefix = filePathManager.getCurrentFilePathWithPrefix(tmp).prefix;var file = filePathManager.getCurrentFilePathWithPrefix(module, prefix).file;prefix = filePathManager.getCurrentFilePathWithPrefix(module, oprefix).prefix;//console.log(module, file, oprefix, prefix)FileDevMaps[prefix+file] = mapDev(prefix+file, prefix);//return module;return prefix+file;});}}})(/(?:import.*?\.+?\/)(.+?)(?:'|")/g, /(?:'|")(.+?)(?:'|")/, /.+\/|/),getFileDevMaps = function(){return FileDevMaps;},build = function(){updateFileDevMaps.apply(null, arguments);updateDevsMap();console.log('map is ready!');},updateDevsMap = function(){for(var key in FileDevMaps){FileDevMaps[key] = mapBy(key, FileDevMaps[key]);}function mapBy(key, map){var devBy;var devs = [];if('devs' in Object(map)){devs = map.devs;devBy = map.devBy;}else{devs = map;devBy = [];}for(var k in FileDevMaps){//console.log(FileDevMaps[k],k)var current = FileDevMaps[k];var cdevs = current.devs;var tmpArr;if(cdevs){tmpArr = cdevs;}else {tmpArr = current;}tmpArr.indexOf(key)!=-1 && devBy.push(k);}var map = {devs: devs,devBy: devBy};return map;};}return {update: updateFileDevMaps,updateMap: updateDevsMap,build: build,get: getFileDevMaps};})();module.exports = fileDevManager;

FileDevManager会在watch任务启动时构建对应目录下所有主文件的依赖对象。

所以watch任务触发时(无论是a.js或b.js),会查找该文件的所有依赖的被哪些文件所依赖,去编译所有相关的模块。


以上。

1 0
原创粉丝点击