详解使用grunt完成requirejs的合并压缩和js文件的版本控制


Posted in Javascript onMarch 02, 2017

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

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

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

安装 grunt-contrib-requirejs

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

配置 Grantfile

首先我们来看下项目目录

详解使用grunt完成requirejs的合并压缩和js文件的版本控制

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文件时,就会执行 requirejs cache 任务。

完整配置清单

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个小文件的效率要高很多,所以模块的合并对性能也有很大的提高。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
List the UTC Time on a Computer
Jun 11 Javascript
jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、Chrome、Opera
Aug 28 Javascript
Js,alert出现乱码问题的解决方法
Jun 19 Javascript
js和html5实现手机端刮刮卡抽奖效果完美兼容android/IOS
Nov 18 Javascript
js结合正则实现国内手机号段校验
Jun 19 Javascript
JavaScript如何实现对数字保留两位小数一位自动补零
Dec 18 Javascript
详解javascript事件绑定使用方法
Oct 20 Javascript
基于BootStrap实现简洁注册界面
Jul 20 Javascript
微信小程序实现跑马灯效果完整代码(附效果图)
May 30 Javascript
Node.js 如何利用异步提升任务处理速度
Jan 07 Javascript
微信小程序列表时间戳转换实现过程解析
Oct 12 Javascript
vue-router之实现导航切换过渡动画效果
Oct 31 Javascript
jQuery上传多张图片带进度条样式(DEMO)
Mar 02 #Javascript
jquery仿京东侧边栏导航效果
Mar 02 #Javascript
关于jQuery EasyUI 中刷新Tab选项卡后一个页面变形的解决方法
Mar 02 #Javascript
JavaScript html5利用FileReader实现上传功能
Mar 27 #Javascript
利用ES6语法重构React组件详解
Mar 02 #Javascript
深入理解在JS中通过四种设置事件处理程序的方法
Mar 02 #Javascript
JavaScript表单验证完美代码
Mar 02 #Javascript
You might like
php随机获取金山词霸每日一句的方法
2015/07/09 PHP
php表单习惯用的正则表达式
2017/10/11 PHP
PHP attributes()函数讲解
2019/02/03 PHP
tagName的使用,留一笔
2006/06/26 Javascript
在你的网页中嵌入外部网页的方法
2007/04/02 Javascript
前淘宝前端开发工程师阿当的PPT中有JS技术理念问题
2010/01/15 Javascript
JQuery团队打造的javascript单元测试工具QUnit介绍
2010/02/26 Javascript
JS动态添加option和删除option(附实例代码)
2013/04/01 Javascript
让table变成exls的示例代码
2014/03/24 Javascript
JavaScript验证图片类型(扩展名)的函数分享
2014/05/05 Javascript
jQuery实现HTML5 placeholder效果实例
2014/12/09 Javascript
jQuery实现的图片分组切换焦点图插件
2015/01/06 Javascript
JavaScript获取当前网页最后修改时间的方法
2015/04/03 Javascript
基于Jquery实现焦点图淡出淡入效果
2015/11/30 Javascript
JS两种类型的表单提交方法实例分析
2016/11/28 Javascript
详解Windows下安装Nodejs步骤
2017/05/18 NodeJs
JS禁止浏览器右键查看元素或按F12审查元素自动关闭页面示例代码
2017/09/07 Javascript
微信小程序中添加客服按钮contact-button功能
2018/04/27 Javascript
JavaScript学习笔记之DOM操作实例分析
2019/01/08 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
2019/05/07 Javascript
Python splitlines使用技巧
2008/09/06 Python
Python使用正则匹配实现抓图代码分享
2015/04/02 Python
python 实现矩阵上下/左右翻转,转置的示例
2019/01/23 Python
Mac安装python3的方法步骤
2019/08/09 Python
使用CSS3来绘制一个月食图案
2015/07/18 HTML / CSS
苏格兰在线威士忌商店:The Whisky Barrel
2019/05/07 全球购物
马来西亚在线购物:POPLOOK.com
2019/12/09 全球购物
几道PHP面试题
2013/04/14 面试题
初中生学习生活的自我评价
2013/11/20 职场文书
2014年公司植树节活动方案
2014/03/04 职场文书
六一节目主持词
2014/04/01 职场文书
小学教研工作总结2015
2015/05/13 职场文书
Python Socket编程详解
2021/04/25 Python
django学习之ajax post传参的2种格式实例
2021/05/14 Python
MySQL修改默认引擎和字符集详情
2021/09/25 MySQL
Python内置的数据类型及使用方法
2022/04/13 Python