zoukankan      html  css  js  c++  java
  • 用GruntJS合并、压缩JS文件

    长期东忙西忙,却不忙更新自己的博客,缺少输出,甚为羞愧

    记得我当初刚接触GruntJS的时候对NodeJS一知半解,所以第一次使用花了些时间才熟悉起来。本文希望能帮助朋友们高速入门。


    为什么要合并、压缩你的JS文件?

    在開始之前,先重申一下这个问题。由于常常在帮忙改东西的时候看到HTML页面上引用了N个JS,而通常看到这个就知道这人JS写得有多糟糕了。HTML里穿插一堆JS代码的我就不吐槽了。

    一般在一个HTML文档载入的时候,浏览器会依据HTML代码从上到下读取所须要载入进来的CSS、JS、图片等文件,指定为异步载入的文件除外。每读取一个文件,浏览器都会向Webserver发送一个载入的请求,server认为这个请求没问题后,浏览器才会開始接收文件。也就是说,每次载入一个文件都会消耗一定的时间在server和client的来回上。

    载入一个文件消耗的时间能够忽略不计,问题是你显示一个复杂的网页可能会载入N多文件,那我们在我们能够控制的范围内,能少花点时间就少花点呗。用户但是对网页载入的速度非常挑剔的!

    对图片我们常常会把一些图标合并成一个大图片用CSS的background来取得对应图片以降低请求。CSS也通常对一种媒体仅仅写一个文件,当然这边要注意万恶的IE对CSS的限制,參考我的博文:用SCSS须要小心IE对css的几个限制。对JS,一般就会将本地的全部用到的文件合并及压缩。当然,以上对使用requireJS一类的框架载入的除外。

    所谓的压缩就是会将全部空格符、凝视等不影响代码都移除,把长的名称都替换为短的名称以节省字符。当你的JS被压缩后,除了头部可能会额外加点文件凝视外,全部的JS代码都并为一行,非常多变量名都变为a啊a的字母,全然失去了可读性。然后你看到自己的JS从300KB可能缩减为仅仅有5KB。这样做的唯一目的就是把JS文件变小,使其载入的速度更快。

    一切都是为了更好的performance……哪天咱下行网速和server上行网速都升级到GB级别哪还用操心这个?


    GruntJS的安装及使用

    GruntJS是一个建立在NodeJS基础上的任务管理工具。概念我不赘述,反正除了配置烦非常好使就对了。

    GruntJS的安装方法在官网上介绍得非常具体。点击查看官网教程>>

    总结下来事实上就那么几步:

    1. NodeJS官网下载安装适合你系统的NodeJS。如今的NodeJS安装会自带NPM包管理,所以你不用再另外装NPM了。
    2. 用NPM装GruntJS的CLI,由于你要在命令行执行GruntJS的命令:
      npm install -g grunt-cli
    3. 在开发项目根文件夹准备package.json文件。这个文件的内容我会在后面具体说明。
    4. 将命令行指定到这个根文件夹,执行
      npm install

    想要在你的项目里执行GruntJS呢,还须要下面几步:

    1. 准备文件Gruntfile.js或Gruntfile.coffee。文件的内容我会在后面具体说明。
    2. 将命令行指定到这个根文件夹,执行
      grunt

    package.json的配置

    这个JSON文件就是给NPM包管理用的。这里我们仅仅要依据GruntJS官网给的一个样例改就已足够。具体的配置请參考官网:https://www.npmjs.org/doc/files/package.json.html

    GruntJS官网的样例:

    {
      "name": "my-project-name",
      "version": "0.1.0",
      "devDependencies": {
        "grunt": "~0.4.5",
        "grunt-contrib-jshint": "~0.10.0",
        "grunt-contrib-nodeunit": "~0.3.3",
        "grunt-contrib-uglify": "~0.4.0"
      }
    }
    

    这个样例包括了配置这个项目的名称,项目的版本号,开发用到的NPM包。执行npm install的时候就是读取这个devDependencies的内容,来下载对应的包到项目根文件夹的node_modules文件夹内。还能够指定下载的包的版本号。关于版本号的写法另一些符号和写法来指定某个范围内的版本号。点击查看版本号号语法具体介绍>>

    一般性可在Github查找并选择你要使用的Grunt包,直接写上当前的版本号如0.3.3指定当前的版本号。或者在版本号号前加“~”符号选择临近版本号。或者用x来取代最后的3,写为0.3.x,选择0.3.开头的最新版,由于最后一个数字改变一般是开发人员修复了BUG而不会有配置或者语法上的改变。

    在这里,我们合并、压缩JS须要用到2-3个NPM包。各自是:

    名称中间带“contrib”的为GruntJS官方提供的插件。

    我说2-3个包是由于grunt-contrib-uglify也能够直接将多个文件合并为一个文件,可是它会“改”代码。这里我希望能终于生成两个文件:一个是纯粹将全部JS代码无修改地合并在一起,用来debug调试;还有一个是压缩过的JS,也就是全部调试通过公布项目时终于使用的JS。所以我还使用了grunt-contrib-concat。

    另外,演示样例其中使用的grunt-contrib-jshint是一个用来检查JS语法错误的插件,能够在你合并文件的时候就帮你检查出错误,只是有时候会有点蛋疼。这里我为了降低篇幅先不用它。

    把上面的演示样例改动例如以下:

    {
      "name": "my-project-name",
      "version": "0.1.0",
      "devDependencies": {
        "grunt": "~0.4.5",
        "grunt-contrib-concat": "0.5.x",
        "grunt-contrib-uglify": "0.5.x"
      }
    }
    

    Gruntfile.js的配置

    一个主要的Gruntfile包括下面几部分:

    module.exports = function(grunt) {
    
      grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        // 这里放插件的设置信息
        taskname: { }
      });
    
      // 加载要使用的插件
      grunt.loadNpmTasks('grunt-taskname');
      // 注冊任务
      grunt.registerTask('default', ['grunt-taskname']);
    
    };
    

    整段代码包括在一个函数中,利用了NodeJS一个把函数公开,能够被其它文件使用的一个写法。

    grunt.initConfig用来接收对各个插件的配置信息。每一个插件的配置选项都能够在它们自己的Github项目页面中找到,并且写法基本上都类似。如:

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        // 任务名称,需依据插件的说明来写
    	concat: {
    		// 子任务名称,这名称随你起
          	dev: {
          		// 可选的配置參数
    	        options: {
    	          banner: '/*!
     * <%= pkg.name %> - JS for Debug
     * @licence <%= pkg.name %> - v<%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd") %>)
     * http://blog.csdn.net/jennieji | Licence: MIT
     */
    '
    	        },
    	        // 源文件路径
    	        src: [
    	          'js/app/**/*.js'
    	        ],
    	        // 执行任务后生成的目标文件
    	        dest: 'js/app.debug.js'
          	}
        }
    });
    

    以上是一个对“grunt-contrib-concat"的配置实例。

    "concat"指定了这套配置所相应的插件。"dev"是我自己定义的一个子任务,我给它取名为"dev"。一个插件能够拥有多套不同的配置以应付不同的需求,也就是说在"concat"下能够包括随意多个自己定义的子任务,每一个子任务都能够有不同的配置。

    这里我设置了"banner"參数,这个參数在非常多对文件操作的插件中都有,如uglify, less, sass等等。它的作用是给终于的目标文件头部加上一些信息或者代码。

    在这个"banner"中,我为终于生成的app.debug.js加上了一段文件凝视。当中还使用了几个特殊的代码:

    换行符,写入文件后,前后的字符就会分行。
    <%= pkg.name %>
    类似ASP的写法。pkg是用grunt.file.readJSON('package.json')读取到的JSON,而且已经转换为JS对象。依照前面package.json的演示样例,这段代码会在写入文件时被替换为"my-project-name"。
    事实上从这里就能够看出在grunt的配置中,我们能够利用JS对象和JSON来做辅助的配置。
    <%= grunt.template.today("yyyy-mm-dd") %>
    这是利用了个grunt的方法,能够执行任务的时间而且指定生成的格式。

    执行这个concat任务时,我的app.debug.js的头部会有下面一段凝视:

    /*!
     * my-project-name - JS for Debug
     * @licence my-project-name - v0.1.0 (2014-07-07)
     * http://blog.csdn.net/jennieji | Licence: MIT
     */
    

    而在文件路径的写法上,则能够用一些匹配的符号。如我这里用了一个星号"*.js"表示随意名称的JS文件,两个星号"**"表示当前文件夹或者子文件夹下。所以这里"js/app/"文件夹下及其全部子文件夹下的JS文件都会被合并到app.debug.js的文件里。

    配置完后,还要记得加载插件和注冊你这个任务,否则会报错!

    加载插件就是把插件NPM包的名字"grunt-contrib-concat"传给grunt.loadNpmTasks方法。

    注冊任务呢,则是用grunt.registerTask方法。第一个參数为注冊的任务队列的名称,写为"default"则成为这个Gruntfile的默认任务队列。第二个參数就是这个任务队列要运行的任务名称的数组,这里的任务名称使用在initConfig配置时使用的名称,即"concat"。改动代码例如以下:

    // 加载要使用的插件
    grunt.loadNpmTasks('grunt-contrib-concat');
    // 注冊任务
    grunt.registerTask('default', ['concat']);
    

    假设这样写,那配置完后直接输入下面命令到命令行便能够运行一次JS的合并:

    grunt

    假设将"default"改为其它名字,比方"debug",那么命令行须要输入:

    grunt debug

    增加Uglify压缩JS也做类似的配置。注意的是这边源文件和目标文件的配置写法不一样。是在files參数里以“目标文件路径:[源文件路径1,源文件路径2,...]”的格式来写。此外我还直接利用了concat已经生成的合并文件来做压缩。完整的Gruntfile.js例如以下:

    module.exports = function(grunt) {
    	grunt.initConfig({
    	    pkg: grunt.file.readJSON('package.json'),
    		concat: {
    	      	dev: {
    		        options: {
    		          banner: '/*!
     * <%= pkg.name %> - JS for Debug
     * @licence <%= pkg.name %> - v<%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd") %>)
     * http://blog.csdn.net/jennieji | Licence: MIT
     */
    '
    		        },
    		        src: [
    		          'js/app/**/*.js'
    		        ],
    		        dest: 'js/app.debug.js'
    	      	}
    	    },
    	    uglify: {
    	    	prod:{
    		    	options: {
    		          	banner: '/*!
     * <%= pkg.name %> - compressed JS
     * @licence <%= pkg.name %> - v<%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd") %>)
     * http://blog.csdn.net/jennieji | Licence: MIT
     */
    '
    			        },
    			        files: {
    			        	'js/app.min.js': ['<%= concat.dev.dest %>']
    			        }
    			    }
    			}
    		}
    	});
    
    	grunt.loadNpmTasks('grunt-contrib-concat');
    	grunt.loadNpmTasks('grunt-contrib-uglify');
    
    	grunt.registerTask('default', ['concat','uglify']);
    };
    

    最后

    这个应该是最基础的使用方法了,我看bootstrap和angular的配置文件都超级复杂。

    假设不想每次改了代码都要在命令行里执行grunt,推荐使用watch插件,它会自己主动检測到文件的修改,然后执行对应的任务。

    另外将Less编译为CSS有"grunt-contrib-less".

    SASS编译为CSS有"grunt-contrib-compass"比較好用,由于能够引用compass-style里的mixin。

    还有"grunt-conritb-requirejs"来针对用requireJS写的JS文件做压缩。

  • 相关阅读:
    移动端触摸右侧菜单栏,页面内容对应项滚动到最上方
    swiper使用中一些点的总结
    javaScript正则表达式入门
    javaScript之数组操作方法(一)
    初识vue
    焦点控制切换和轮播
    文本内容只显示两行,然后加...
    图片父容器高度不定的图片垂直居中
    css3图片垂直居中
    【C#】两个list根据某个元素比较差集
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4046515.html
Copyright © 2011-2022 走看看