前端自动化grunt的使用
作为前端开发人员,有必要也有义务掌握前端自动化工具grunt;
这样可以极大地降低前端的复杂工作,提高工作效率,把所有的精力都投入到
编码中去。
grunt API列表
- config
- event
- fail
- file
- log
- option
- task
- template
- util
在使用grunt构建前端自动化中,我主要使用的config、file、template以及util这几个API。
现在贴一份gruntfilejs代码,基本上前端的自动化工作都可以完成:
'use strict' var ASSETS_DIR = 'assets/'; module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), /* jsdoc生成js文档 */ jsdoc: { dist: { src: ['assets/scripts/test.js'], options: { destination: 'docs' } } }, /* css代码合并 */ concat: { } }); /*grunt-contrib-less模块,使用less预编译css文件*/ grunt.config.merge({ less: { dev: { files: [{ expand: true, cwd: ASSETS_DIR + 'less/' + './', src: ['*.less'], dest: ASSETS_DIR + 'css', ext: '.css' }] } } }); /*grunt-contrib-sprite模块,生成雪碧图*/ grunt.config.merge({ sprite: { options: { banner: '/*<%=pkg.name %> <%=grunt.template.today("yyyy-mm-dd")%>*/' }, all: { src: [ASSETS_DIR + "images/sprites/*.png"], engine: require('pixelsmith'), dest: ASSETS_DIR + "images/sprite.png", destCss: ASSETS_DIR + "css/sprite.css", padding: 10, algorithm: "binary-tree", cssVarMap: function(sprite) { var iconIndex, activeIndex; iconIndex = sprite.name.indexOf('icon-'); activeIndex = sprite.name.lastIndexOf('-active'); if (activeIndex > 0) { // sprite.name=sprite.name.replace(sprite.name.substr(activeIndex),":active"); } if (iconIndex === 0) { sprite.name = sprite.name.replace(sprite.name.substr(0, 5), ''); } } } } }); /*grunt-contrib-cssmin模块,压缩css文件*/ grunt.config.merge({ cssmin: { add_banner: { options: { banner: '/* minify the css file <%= grunt.template.today("yyyy-mm-dd") %> */' }, files: { 'assets/css/output.css': [ASSETS_DIR + 'css/bootstrap.css', ASSETS_DIR + 'css/home.css'] } }, minify: { options: { banner: '/* minify the css file\n Author:lidasong\n Time: <%= grunt.template.today("yyyy-mm-dd") %>*/' }, expand: true, cwd: ASSETS_DIR + 'dest/css/', src: ['*.css', '!*.min.css'], dest: ASSETS_DIR + 'dest/release', ext: '.min.css' } } }); /**js、css代码检测工具, *grunt-contrib-jshint模块、grunt-contrib-csslint模块 **/ grunt.config.merge({ jshint: { all: { options: { '-W069': true, '-W064': true, '-W040': true }, src: ['assets/scripts/*.js'] } }, csslint: { strict: { options: { import: false }, src: [ASSETS_DIR + 'css/*.css'] } } }); /*grunt-contrib-uglify模块,压缩js文件*/ grunt.config.merge({ uglify: { jscomp: { files: [{ expand: true, cwd: ASSETS_DIR + 'scripts', src: '**/*.js', dest: ASSETS_DIR + 'dest/scripts' }] } }, }); /*grunt-contrib-copy模块,文件复制*/ grunt.config.merge({ copy: { release: { options: { process: function(content, srcpath) {}, timestamp: true }, expand: true, cwd: ASSETS_DIR + 'dest/', src: ['**'], dest: ASSETS_DIR + 'release' // flatten:true, // filter:'isFile' } } }); /*grunt-contrib-clean模块,清除文件*/ grunt.config.merge({ clean: { concatCss: { options: { force: true }, src: [ASSETS_DIR + 'dest/css/'] }, miniCss: { options: { force: true }, src: [ASSETS_DIR + 'dest/release/'] } } }); /*grunt-contrib-watch模块,监控文件变化*/ grunt.config.merge({ watch: { 'less-dev': { files: [ASSETS_DIR + 'less/*.less', ASSETS_DIR + 'less/partials/**/*.less'], tasks: ['less:dev'] }, 'less-bootstrap': { files: [ASSETS_DIR + 'less/lib/bootstrap/**/*.less'], tasks: ['less:bootstrap'] } } }); /*grunt-contrib-*模块加载*/ require('load-grunt-tasks')(grunt); /*grunt注册任务列表*/ grunt.registerTask('default', ['less:dev', 'watch:less-dev']); grunt.registerTask('bootstrap', ['less:bootstrap']); grunt.registerTask('js-hint', 'JS代码质量检查', ['jshint']); grunt.registerTask('css-lint', 'CSS代码质量检查', ['csslint']); grunt.registerTask('all-concat', 'css 代码合并', ['clean:concatCss', 'css-concat', 'concat']); grunt.registerTask('minify-css', 'CSS代码压缩', ['clean:miniCss', 'cssmin:minify']); grunt.registerTask('doc', 'jsdoc生成js文档', ['jsdoc']); grunt.registerTask('sprites', '生成雪碧图', ['sprite:all']); grunt.registerTask('js-comp', '压缩js代码', ['uglify:jscomp']); grunt.registerTask('copyCss', '复制合并压缩后的css', ['copy:release']); grunt.registerTask('css-concat', 'css代码合并', function() { grunt.file.expand(ASSETS_DIR + 'css/*').forEach(function(dir) { var dirName = dir.substr(0, dir.indexOf('.')), concat = grunt.config.get('concat') || {}; dirName = dirName.substr(dirName.lastIndexOf('/') + 1); if (grunt.file.isFile(dir)&&dirName !== 'bootstrap' && dirName !== 'sprite') { concat['options'] = { stripBanners: true, banner: '/*合并css后的代码*/' }; concat[dirName] = { src: [dir, ASSETS_DIR + 'css/bootstrap.css'], dest: ASSETS_DIR + 'dest/css/' + dirName + '.css' }; grunt.config.set('concat', concat); } }); }); };
使用grunt.file:
grunt.file.readJSON可以读取文件的json内容返回;使用grunt.file.readJSON('package.json')读取package文件,然后使用文件的内容。
grunt.file.expand返回包含匹配给定通配符模式的文件或者目录路径的特殊数组,可以对返回的特殊数组走处理;比如此处的gruntfile文件中有grunt.registerTask中使用grunt.file.expand('文件夹path').forEach(function(dir){...});这个任务就是将文件夹中的每个原始文件使用grunt-contrib-concat执行合并操作。
当然grunt.file还有很多方法,比如目录操作:grunt.file.mkdir;复制操作:grunt.file.copy等等,这里就不一一列举。
分离grunt.initConfig({})初始化函数
首先grunt.initConfig({})函数就是grunt.config.init的另一种初始化形式;为了让grunt.initConfig函数简短,每个功能更加明晰,这个使用grunt.config的方法实现每个任务都简单明了,也使得grunt.initConfig不再那么臃肿;当然也可以使用模块化的方式将每个任务分离出gruntfile文件,然后使用commonJS的模块加载方式把每一个任务文件加载到gruntfile中来。但是我使用的是前者,直接在gruntfile文件中,使用grunt.config的方法把每个人物分离出来,单个处理。
grunt.config.set('task',taskTool)方法实现在grunt.initConfig(configObject)中的configObject添加任务;
grunt.config.merge(taskObject)同样方法实现在configObject中合并taskObject,从而添加任务。
grunt.template使用
grunt.template主要实现使用数据将模板渲染出来:
var obj = { foo: 'c', bar: 'b<%= foo %>d', baz: 'a<%= bar %>e' }; grunt.template.process('<%= baz %>', {data: obj})
使用grunt.template。process(template,data);把data渲染到template中,呈现结果,比如上面的输出结果是:
'abcde'
总结:
其实前端自动化还是比较好学,当然也是相当好用的,在繁杂的前端工作中,这可以减少相当一部分工作,
尤其是雪碧图的合成。学习基础的nodejs,然后熟悉grunt的api,你就可以欢快的使用自动化工具解决那些繁杂的
琐事了。