详解使用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 相关文章推荐
Add a Table to a Word Document
Jun 15 Javascript
JavaScript 计算当天是本年本月的第几周
Mar 22 Javascript
javascript实现链接单选效果的方法
May 13 Javascript
JavaScript对表格或元素按文本,数字或日期排序的方法
May 26 Javascript
浅析JavaScript中的事件机制
Jun 04 Javascript
移动端点击图片放大特效PhotoSwipe.js插件实现
Aug 25 Javascript
vue.js中过滤器的使用教程
Jun 08 Javascript
JavaScript数据结构与算法之队列原理与用法实例详解
Nov 22 Javascript
vue 配置多页面应用的示例代码
Oct 22 Javascript
JS实现textarea通过换行或者回车把多行数字分割成数组并且去掉数组中空的值
Oct 29 Javascript
新手快速上手webpack4打包工具的使用详解
Jan 28 Javascript
JS实现指定区域的全屏显示功能示例
Apr 25 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 启动时报错的简单解决方法
2014/01/27 PHP
joomla实现注册用户添加新字段的方法
2016/05/05 PHP
php实现微信扫码自动登陆与注册功能
2016/09/22 PHP
php实现的简单数据库操作Model类
2016/11/16 PHP
laravel框架中间件 except 和 only 的用法示例
2019/07/12 PHP
jQuery源码分析-03构造jQuery对象-源码结构和核心函数
2011/11/14 Javascript
跨浏览器的事件对象介绍
2012/06/27 Javascript
自定义右键属性覆盖浏览器默认右键行为实现代码
2013/02/02 Javascript
jQuery多项选项卡的实现思路附样式及代码
2014/06/03 Javascript
jquery中页面Ajax方法$.load的功能使用介绍
2014/10/20 Javascript
AngularJS 日期格式化详解
2015/12/23 Javascript
js获取form表单所有数据的简单方法
2016/08/18 Javascript
Node.js 基础教程之全局对象
2017/08/06 Javascript
webpack3+React 的配置全解
2017/08/21 Javascript
JS实现常见的查找、排序、去重算法示例
2018/05/21 Javascript
利用Bootstrap Multiselect实现下拉框多选功能
2019/04/08 Javascript
JQuery获取可视区尺寸和文档尺寸及制作悬浮菜单示例
2019/05/14 jQuery
解决ant Design中Select设置initialValue时的大坑
2020/10/29 Javascript
利用 Chrome Dev Tools 进行页面性能分析的步骤说明(前端性能优化)
2021/02/24 Javascript
Python 自动刷博客浏览量实例代码
2017/06/14 Python
Python实现可设置持续运行时间、线程数及时间间隔的多线程异步post请求功能
2018/01/11 Python
Python机器学习之scikit-learn库中KNN算法的封装与使用方法
2018/12/14 Python
利用python将图片版PDF转文字版PDF
2019/05/03 Python
Python 、Pycharm、Anaconda三者的区别与联系、安装过程及注意事项
2019/10/11 Python
Python 读取有公式cell的结果内容实例方法
2020/02/17 Python
Python爬虫实战案例之爬取喜马拉雅音频数据详解
2020/12/07 Python
欧洲第一的摇滚和金属乐队服装网站:EMP
2017/10/26 全球购物
美国酒店控股公司:Choice Hotels
2018/06/15 全球购物
奥地利领先的在线药房:SHOP APOTHEKE
2019/10/07 全球购物
推广普通话共筑中国梦演讲稿
2014/09/21 职场文书
2014年部门工作总结
2014/11/12 职场文书
巾帼文明岗汇报材料
2014/12/24 职场文书
在职证明书模板
2015/06/15 职场文书
2019如何书写演讲稿?
2019/07/01 职场文书
python中的sys模块和os模块
2022/03/20 Python
Java数组详细介绍及相关工具类
2022/04/14 Java/Android