最近有一个项目使用了 requirejs 来解决前端的模块化,但是随着页面和模块的越来越多,我发现我快要hold不住这些可爱的js文件了,具体表现在每个页面都要设置一堆 requirejs 的配置( baseUrlpaths 之类的)。

不知谁说过,一些事重复做了三次,就该考虑一下自动化了,于是我小心翼翼的掏出了我的 grunt

我们得使用 grunt-contrib-requirejs 这个插件来实现如上所说的自动化功能,这个就是根据 r.js 封装的 grunt 插件。

安装 grunt-contrib-requirejs

npm i --save-dev grunt-contrib-requirejs

配置 Grantfile

首先我们来看下项目目录

src 是每个页面的依赖文件

moduleslib 是一些模块和库

dist 是合并压缩后的文件

Gruntfile 中首先得到需要处理的文件列表,并创建一个空对象,用来装requirejs的配置

var files = grunt.file.expand('static/js/src/*.js');
var requireOptions = {};

然后遍历这个文件列表数组,得到js文件的名称:

files.forEach(function (file) {
var filenamelist = file.split('/');
var num = filenamelist.length;
var filename = filenamelist[num - 1].replace(/\.js$/,'');
}

接下来为每个js文件配置一个任务,任务名称就是js的文件名称:

files.forEach(function (file) {
requireOptions[filename] = {
options: {
baseUrl: 'static/js',
paths: {
jquery: 'lib/jquery.min',
lrz: 'lib/lrz.all.bundle',
zepto: 'lib/zepto.min',
ajax: 'modules/ajax',
validators: 'modules/validators',
page: 'modules/mixins/to_page',
dialog: 'modules/mixins/toggle_login_dialog',
},
optimizeAllPluginResources: true,
name: 'src/' + filename,
out: 'static/js/dist/' + filename + '.js'
}
};
}

接着初始化 grunt 配置并加载并注册任务

grunt.initConfig({
requirejs: requireOptions
}) grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.registerTask('require', ['requirejs']);

到这里 requirejs 的配置部分就结束了,在命令行输入 grunt require 就会看到 static/js/dist 目录下面有东西蹦出来了,而且全部都是合并后并压缩好的。

在html页面中只需要:

<script src="static/js/require.js"></script>
<script src="static/js/dist/index.js"></script>

就能成功加载了。

增加js文件的版本号

浏览器有时会对加载过的js或css进行缓存,如果你的某些js依赖发生改变,那么就可能发生错误,解决办法是在文件后面增加查询字符串,例如 a.js?v=dsd712sd

那么如何控制版本,首先我们肯定想到用 new Date() ,但是如果每次发布都让浏览器重新加载(尽管有些文件根本就没有改变),难免会造成浪费。正确的方案是根据文件内容生成MD5值来作为版本号,这样当文件没有改变时,hash就不会变。

那么如何自动解决版本号的问题,我们可以用到 asset-cache-control 这个grunt插件

首先安装:

npm i --save-dev asset-cache-control

asset-cache-control 的用法个很简单,只要设置一个源文件,再设置html文件的路径就可以了

grunt.initConfig({
cache: {
demo: {
assetUrl: 'js/demo.js',
tmp: ['demo.html']
}
}
})

注意的是:html文件中需要引入 js/demo.js

<script src='js/demo.js'></script>

然后加载和注册 asset-cache-control 插件

grunt.loadNpmTasks('asset-cache-control');
grunt.registerTask('cache', ['cache']);

接着在命令行敲 grunt cache 就会发现 index.html 中的 script 标签加上了查询字符串。

<script src='js/demo.js?t=92e26c5d'></script>

对每个js文件配置 cache 的任务:

var files = grunt.file.expand('static/js/src/*.js');
var cacheOptions ={};
files.forEach(function (file) {
var filenamelist = file.split('/');
var num = filenamelist.length;
var filename = filenamelist[num - 1].replace(/\.js$/,'');
cacheOptions[filename] = {
assetUrl: 'static/js/dist/' + filename +'.js',
files: {
'tmp': [filename+'.php']
}
}
});

检测每个文件的变化,自动执行任务

用到 grunt-contrib-watch 这个官方组件

grunt.initConfig 中配置:

watch: {
files: ['static/js/src/*.js','static/js/modules/*.js'],
tasks: ['requirejs', 'cache'],
options: {
spawn: false
}
}

这样,当你修改 static/js/src/static/js/modules/ 下的所有js文件时,就会执行 requirejscache 任务。

完整配置清单

module.exports = function (grunt) {
var files = grunt.file.expand('static/js/src/*.js');
var requireOptions = {};
var cacheOptions ={};
files.forEach(function (file) {
var filenamelist = file.split('/');
var num = filenamelist.length;
var filename = filenamelist[num - 1].replace(/\.js$/,'');
requireOptions[filename] = {
options: {
baseUrl: 'static/js',
paths: {
jquery: 'lib/jquery.min',
lrz: 'lib/lrz.all.bundle',
zepto: 'lib/zepto.min',
ajax: 'modules/ajax',
validators: 'modules/validators',
page: 'modules/mixins/to_page',
dialog: 'modules/mixins/toggle_login_dialog',
},
optimizeAllPluginResources: true,
name: 'src/' + filename,
out: 'static/js/dist/' + filename + '.js'
}
};
cacheOptions[filename] = {
assetUrl: 'static/js/dist/' + filename +'.js',
files: {
'tmp': [filename+'.php']
}
}
}); grunt.initConfig({
requirejs: requireOptions,
cache: cacheOptions,
watch: {
files: ['static/js/src/*.js','static/js/modules/*.js'],
tasks: ['requirejs', 'cache'],
options: {
spawn: false
}
}
}); grunt.loadNpmTasks('asset-cache-control');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('require', ['requirejs','cache'])
};

另外,浏览器加载一个大文件比加载n个小文件的效率要高很多,所以模块的合并对性能也有很大的提高。

使用grunt完成requirejs的合并压缩和js文件的版本控制的更多相关文章

  1. uglifyjs2压缩混淆js文件

    uglifyjs可以用来压缩混淆js文件,发布release版本应用利器.在StackOverflow浏览了一下,相比Google Closure和YUI compressor,uglifyjs被推荐 ...

  2. GZip压缩的js文件IE6下面不能包含<script>标签

    IE6下面,GZip压缩的js文件,如果js中包含<script>标签,一遇到这样的标签,后面的内容居然都截断了,狂晕! 花了我一个晚上来找原因.. 需要将字符串'<script&g ...

  3. 简单使用grunt、bower工具合并压缩js和css

    前段时间因为项目中的报表写了一个Jquery插件,开源到github上,参考以往大神们写的插件的姿势,决定搞了像模像样一点.言归正传.前端工程师对这些工具:Node,bower,grunt,npm这些 ...

  4. vs合并压缩css,js插件——Bundler & Minifier

    之前做了一个大转盘的抽奖活动,因为比较火,部分用户反馈看不到页面的情况,我怀疑js加载请求过慢导致,所以今天针对之前的一个页面进行调试优化. 首先想到的是对页面的js和css进行压缩优化,百度了下vs ...

  5. rjs 合并压缩完 js 后 js 不压缩的问题

    线下用 requirejs 开发完后,代码上线前要用 rjs 将多个有依赖关系的 js 文件压成一个,然后某天居然发现压成一个的 js 文件,没有压缩!!!几万行的 js!!! 很显然,是 uglif ...

  6. ASP.NET MVC Bundles 合并压缩(js css)

    Chrome浏览器有并发的Http请求限制,Bundles可以将多个JS文件合并成一个文件并进行压缩,最终得到一个单文件的压缩包. 第一步:BundleConfig public class Bund ...

  7. gulp 图片、样式、js、实时刷新等压缩gulpfile.js文件各个模块

    1.压缩tinypng图片   gulp-tinypng-nokey,但不压缩gif格式(另外一个gulp-imagemin压缩率不高,可以压缩gif格式) // 获取 gulp var gulp = ...

  8. NodeJs 实时压缩 项目js文件

    + 1. 下载nodejs : "http://nodejs.org/". + 2. 以administrator权限打开cmd.+ 3. cmd路径定位到要压缩的目录: &quo ...

  9. 批量压缩 css js 文件 包含多个文件 自动识别

    注意事项  css 注释压缩不会造成影响      因为是块注释     当然也可以选择去注释压缩 js 带注释压缩  要注意注意 注意  //行注释会造成 压缩后的代码在一行 导致注释后的代码都失效 ...

随机推荐

  1. 最近iOS开发遇到的问题

    1)计算器,编辑框键盘: 2)类间参量引用传递: 3)饼状图: 4)折线图: 5)uicollection使用: 6)富文本开发: 7)separatorInset,layoutMargins uit ...

  2. 绘图——Android绘图基础:Canvas、Paint等

    Android的绘图应该继承View组件,并重写它的onDraw(Canvas canvas)方法即可. 重写onDraw(Canvas canvas)方法时涉及一个绘图API:Canvas,Canv ...

  3. YII 1.0 分页类

    在控制器中 方法1 $criteria = new CDbCriteria();//AR的另一种写法 $model = Article::model(); $total = $model->co ...

  4. HUD-5124-lines

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5124 这题题目做的好悲催,比赛时题目意思不理解,也没有深究了,赛后又看了很久没有看懂,问了很多才搞懂, ...

  5. 支付宝开发中return_url和notify_url的区别分析

    在处理支付宝业务中出现过这样的问题,付费完成后,在支付宝跳转到商家指定页面时,订单状态已经更新,通过调试发现是支付宝先通知notify_url,完成了订单状态. 支付宝return_url和notif ...

  6. 报错找不到jquery-1.10.2.min.map解决办法

    http://fruithardcandy.iteye.com/blog/1941452

  7. document.body.clientHeight的取值

    http://www.cnblogs.com/fullhouse/archive/2012/01/05/2313800.html 有时候需要取页面的底部, 就会用到document.body.clie ...

  8. java_JDBC(3)

    Batch和Fetch两个特性非常重要.Batch相当于JDBC的写缓冲,Fetch相当于读缓冲 如果把JDBC类比为JAVA IO的话,不使用Fetch和Batch相当于直接使用FileInputS ...

  9. 关于小程序swiper不显示图的那些事

    还有几天快过年了,在这里提前祝大家新年快乐! 今天没事研究了一下小程序,想整个轮播图玩玩,然后开始看看文档https://mp.weixin.qq.com/debug/wxadoc/dev/compo ...

  10. 关于js 构造 onclick 方法中传递Guid参数问题

    转义字符单双引号用法:\'  与 \" 例如: $.getJSON("data.json", function(data, status, xhr) { $(" ...