博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端工程化二(requirejs + gulp)
阅读量:6375 次
发布时间:2019-06-23

本文共 4963 字,大约阅读时间需要 16 分钟。

利用gulp+requirejs解决了目前项目的两个主要问题。

静态资源缓存问题

requirejs对于js文件的版本号是通过config.js配置文件中的urlArgs参数统一管理的。

requirejs.config({        ...        urlArgs:"v=1.0.0"        path:{            "module1":"./module1",            "module2":"./module2"        }        ...})

requirejs会在装载module1和module2时,在请求后面拼接上"?v=1.0.0"。

问题在于,每次发布,不管哪个环境,都需要手动去修改urlArgs这个参数,否则就会出现缓存问题。
而希望实现的目标是,所有静态资源根据MD5码生成版本号。
解决思路:
一种是利用gulp将配置文件调整成以下样子:

requirejs.config({        ...        urlArgs:""        path:{            "module1":"./module1.js?v=dFe82Pzk",            "module2":"./module2.js?v=1a0Ak9pY"        }        ...})

大致实现流程:

1.读取配置文件,将文件中path解析成JSON对象,前提条件是配置文件中path的键值都是string且都用引号引起来,否则无法转换成json对象;

//获取requireCOnfig中的paths JSON对象const __getRequireConfigPaths = function (file) {    let configContents = file.contents.toString();    let matches = /"paths": (\{[^}]*}),/.exec(configContents);    return JSON.parse(matches[1]);};

2.遍历所有require管理的js文件进行MD5编码,建立moduleName:md5键值对构成的对象verMap;

//根据文件内容计算md5串const __getDataMd5 = function (data) {    return crypto.createHash('md5').update(data).digest('base64');};//根据paths JSON对象生成[{moduleName:moduleNamev?=MD5}]对照关系verMapgulp.task("createMD5VerMap", function (cb) {    gulp.src("./config/common-config.js")        .pipe(through2.obj(function (file, encoding, done) {                let paths = __getRequireConfigPaths(file);                //将through2异步操作封装成promise对象,利用Promise.all等待所有through2异步任务执行完毕后调用gulp.task的callback                let promises = [];                for (let moduleName in paths) {                    let filePath = './' + paths[moduleName];                    let suffix = '';                    if(/([Cc]ss$)/.test(moduleName)){                        //需约定moduleName以css或者Css结尾对应的都是css文件                        filePath = './' + paths[moduleName]+'.css';                        suffix = '.css'                    }else if(!/(\.html$)/.test(filePath)){                        //需约定文件名不以.html结尾的都是js文件                        filePath = './' + paths[moduleName]+'.js';                        suffix = '.js'                    }                    promises.push(                        new Promise(function (resolve) {                            gulp.src(filePath)                                .pipe(through2.obj(function (file) {                                        verMap[moduleName] = paths[moduleName]+suffix+"?v="+__getDataMd5(file.contents).slice(0, 6);                                        resolve();                                    }, function () {                                        //不处理失败任务                                        console.log("未获取到文件:"+paths[moduleName])                                        verMap[moduleName] = paths[moduleName];                                        resolve();                                    })                                )                        })                    );                }                Promise.all(promises).then(cb());            })        );});
这里利用Promise.all来保证全部文件完成MD5编码后再进行后续处理,防止异步问题导致verMap未完整生成就被拿去做其他处理。

3.读取配置文件,根据verMap改写path中的值("module1":"./module1" => "module1":"./module1?v=dFe82Pzk")

//将[{moduleName:MD5}]对照关系verMap写入requireConfig.js配置文件中gulp.task("modifyRequireConfig", function () {    return gulp.src("js/requirejs-config.js")        .pipe(through2.obj(function (file, encoding, done) {            let contents = file.contents.toString();            contents = contents.replace(/"paths": (\{[^}]*}),/, '"paths": '+JSON.stringify(verMap));            file.contents = new Buffer(contents);            this.push(file);            done();        }))        .pipe(rename("requirejs-config.js"))        .pipe(gulp.dest("./js"));});

这种方法的弊端在于静态资源的覆盖率,对于未在path中配置的静态文件,是没办法打上md5版本号的,所以需要对所有用require或者define引入的js文件,全部写到path里去,导致配置文件臃肿。

网上还有种思路是修改require.js源码,将urlArgs改为允许传入Function,在根据所有静态文件生成moduleName:MD5键值对以后,通过动态获取MD5码来拼接url。(参考:)

如果对修改源码没有限制,可以采用这种方式。

代码合并、压缩

利用requirejs的optimize方法,可以将存在相互依赖关系的几个js合并成单个js文件,并提供uglify压缩。

module1:    define("module1", function(){        return {            key: "value"        }    });module2:    require(["module1"], function(module1){        console.log(module1.key);    })    gulpfile.js    gulp.task("concat", function(){        rjs.optimize({            baseUrl: "./",            name: "./test/module2.js",            out: "./test/app.js",            optimize: "uglify"//压缩        }, function () {            console.log(name + ":" + out + " is OK!");        });    });

执行gulp任务后会将module1和module2合并生成app.js。

app.js:    define("module1",[],function(){return{key:"value"}}),define("test/module1.js",function(){}),require(["./module1.js"],function(e){console.log(e.key)}),define("test/module2.js",function(){});

而对于没有相互依赖关系的js,可以用gulp-concat进行合并,再用gulp-uglify压缩

//公共模块合并gulp.task('buildCommModule', function () {    return gulp.src(["./js/a.js", "./js/b.js"])        .pipe(concat("common.js"))        .pipe(uglify())        .pipe(gulp.dest('./dist/js/'))})

最后,对于入口html文件,引入js的代码如下

转载地址:http://rjnqa.baihongyu.com/

你可能感兴趣的文章
将Java应用部署到SAP云平台neo环境的两种方式
查看>>
JS引擎执行机制
查看>>
Node脚手架编写初学者教程
查看>>
08_Node js 工具模块 util
查看>>
手把手教你如何安装水晶易表——靠谱的安装教程
查看>>
Python PyCharm编辑器配置和使用
查看>>
Python单例模式(Singleton)的N种实现
查看>>
requirejs的插件介绍与制作
查看>>
SpringBoot整合Angular应用第二弹-配置支持Angular
查看>>
Facebook、纽约大学利用机器学习5分钟搞定核磁共振检查
查看>>
221. Maximal Square
查看>>
MySQL基础
查看>>
机器学习A-Z~支持向量机
查看>>
PAT A1010 二分进制结合重点题
查看>>
LeetCode35.搜索插入位置 JavaScript
查看>>
数据结构java版之大O表示法
查看>>
DOM事件全面总结
查看>>
CSS3径向渐变radial-gradient实现波浪边框和内倒角
查看>>
5个让人赞不绝口的微信小程序,拒绝占用手机内存!
查看>>
Spring Security整合KeyCloak保护Rest API
查看>>