var sassStyle = 'expanded';

  grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
output : {
options: {
style: sassStyle
},
files: {
'./style.css': './scss/style.scss'
}
}
},
concat: {
options: {
separator: ';',
},
dist: {
src: ['./src/plugin.js', './src/plugin2.js'],
dest: './global.js',
},
},
uglify: {
compressjs: {
files: {
'./global.min.js': ['./global.js']
}
}
},
jshint: {
all: ['./global.js']
}
}); grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask('outputcss',['sass']);
grunt.registerTask('concatjs',['concat']);
grunt.registerTask('compressjs',['concat','jshint','uglify']);
grunt.registerTask('default'); };

其中注册了一个 compressjs 任务 grunt.registerTask('compressjs',['concat','jshint','uglify']); 意思就是依次执行 合并、检查、压缩 任务。我们把刚生成的 global.js 文件删掉,在命令行执行 grunt compressjs 任务,结果 jshint 报错了:

grunt 遇到错误就退出了,就没法继续执行下面的任务。通过错误提示可以发现,是因为 concat 里面设置的参数——在两个文件合并间插入一个“;”——这本来是为了防止两个文件之间相互干扰设置的,结果无法被 jshint 验证通过,我们可以删掉这个参数,或者设置 jshint 验证这两个文件,然后再进行合并。

为了方便,我删掉了这个参数。再执行一下,成功了,项目目录里面多了 global.js 和 global.min.js 文件。

小明看到这里,痛哭流泪,自己每次打开好几个网站,辛苦挨个粘贴复制新建,没想到输入一条命令就可以了。不过让他更伤心的还在后面,连这些命令都不用重复输入。

我们可以通过 watch 来监听文件变动,当文件变化了(我们编写保存了),自动执行某些任务。此处为了节约版面,我连自动刷新的任务一块写上去。根据 grunt-contrib-watch 和 grunt-contrib-connect 这俩文档,我们可以写出下面的任务:

module.exports = function(grunt) {

  var sassStyle = 'expanded';

  grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
output : {
options: {
style: sassStyle
},
files: {
'./style.css': './scss/style.scss'
}
}
},
concat: {
dist: {
src: ['./src/plugin.js', './src/plugin2.js'],
dest: './global.js',
},
},
uglify: {
compressjs: {
files: {
'./global.min.js': ['./global.js']
}
}
},
jshint: {
all: ['./global.js']
},
watch: {
scripts: {
files: ['./src/plugin.js','./src/plugin2.js'],
tasks: ['concat','jshint','uglify']
},
sass: {
files: ['./scss/style.scss'],
tasks: ['sass']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'index.html',
'style.css',
'js/global.min.js'
]
}
},
connect: {
options: {
port: 9000,
open: true,
livereload: 35729,
// Change this to '0.0.0.0' to access the server from outside
hostname: 'localhost'
},
server: {
options: {
port: 9001,
base: './'
}
}
}
}); grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.registerTask('outputcss',['sass']);
grunt.registerTask('concatjs',['concat']);
grunt.registerTask('compressjs',['concat','jshint','uglify']);
grunt.registerTask('watchit',['sass','concat','jshint','uglify','connect','watch']);
grunt.registerTask('default'); };

添加了 connect 任务,用来新建一个本地服务器,以当前目录作为服务器根目录,然后添加 watch 任务,监听 Scss 文件变动,如果变了,执行一下 sass 任务,监听那俩 JS,如果变了,执行 合并、检查、压缩 任务,监听 html、css、js 文件,如果变动,livereload 自动刷新打开的页面。

而注册的 watchit task 就是我们的终极 task,第一次执行,先编译 sass、再合并、检查、压缩、开启服务器、监听文件变动。我们执行一下 grunt watchit 就可以看到效果了,你可以修改一下 scss 文件,把字体设置大一点,切换到浏览器的时候,就看到了实时刷新效果。也可以修改一下 JS,故意改错一下,会发现 jshint 会提示你出错了。

看到这里,小明和小红相拥而泣。。。。

项目文件传输与协作

项目开发完成之后,往往需要 push 到 Github 或者上传 FTP 等。或许其他人会接手你的项目继续开发,或者你会换台电脑进行开发。

当小明用 git 上传 Github 的时候,傻了眼,项目里 node_modules 文件夹下面的东西要十几M呢,这比我项目本身还大,上传下载都不方便。

其实这些插件和 grunt 不需要上传,因为有 package.json 这个文件记录了你这个项目中依赖的 grunt 插件,你只需要上传这个文件即可。下载下来之后,只需要在这个项目文件夹下面,输入命令 npm install,NPM 会自动读取 package.json 文件,将 grunt 和有关插件给你下载下来,很方便的。

也不需要在本地上传的时候删除,用 git 的话,可以使用 .gitignore 文件来过滤掉这个文件夹,禁止 git 追踪。

总结与扩展阅读

Grunt 就是这样一种任务自动运行器,应用好它可以减轻很多不必要的人工操作,只需要专注 coding 就可以。甚至还有Grunt 插件帮你自动完成 CSS Sprite,更多功能还需要你自己去摸索。

新手看完本文,再看一下 Grunt 官方文档 应该没有太多疑问了,那就再看一遍把。当然也有中文版

除了 Grunt 之外,同类型比较火的还有 Gulp 这个工具。其实两个东西的功能是一样的,只不过是任务配置 JS 的语法不同,Gulp 的 Gulpfile.js 的写法更加通俗易懂,上手更快。但是 Gulp 的插件等感觉不如 Grunt,Grunt 官方提供了一些常见的插件,满足大部分日常工作,而且可靠值得信赖,而 Gulp 好像没有太多官方出品,各种插件不太规范。简单的说,Grunt 和 Gulp 就像 iPhone 与 Android 一样,一个质量高学习难一点,一个学起来简单但是有点那个,你懂得。

此外,可以看一些高手的项目,你会发现更好的 Grunt 用法,比如 Yeoman 生成的项目,就有很完善的 Grunt 任务和插件,此外,jQuery 等也用 Grunt 进行打包,这些 Grunt 文件你都可以查看研究一下他们的写法和用法,受益匪浅。

最后,如果你懒得跟着文章一点点的配置示例项目,你也可以跳转到示例项目的 grunt 分支,这里面是我配置好的,你需要先 npm install 然后就可以直接执行那些命令。

Grunt 新手一日入门的更多相关文章

  1. [转]Grunt 新手一日入门

    本文转自:http://yujiangshui.com/grunt-basic-tutorial/ 当时学习 Grunt 的时候,真是很头疼.分了两个时间段,学习了两次才硬啃下来,之后才能用在项目中. ...

  2. GitHub新手快速入门日常操作流程

    GitHub新手快速入门日常操作流程 1. 注册帐号 打开https://github.com/,填写注册信息并提交. 2. 登录帐号 打开https://github.com/login,输入注册的 ...

  3. Django2.1新手图文入门教程

    第一个django Web Django2.1新手图文入门教程 http://www.liujiangblog.com/blog/36/

  4. Sql Server新手学习入门

    Sql Server新手学习入门 http://www.tudou.com/home/_117459337

  5. 新手如何入门pytorch?

    我最近的文章中,专门为想学Pytorch的新手推荐了一些学习资源,包括教程.视频.项目.论文和书籍.希望能对你有帮助:一.PyTorch学习教程.手册 (1)PyTorch英文版官方手册:https: ...

  6. Django新手图文入门教程

    版权所有,转载需注明来源! 本文是广受大家欢迎的<Django1.10新手图文入门教程>的2.1版本升级篇,原1.10版本传送门点击我 本文面向有一些的Python基础,但刚接触web框架 ...

  7. Grunt新手入门篇

    今天看到一篇通俗易懂的Grunt入门文章,博主写得很用心,原文请戳:http://yujiangshui.com/grunt-basic-tutorial/ 当时学习 Grunt 的时候,真是很头疼. ...

  8. PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引

    一.框架的由来  快速入门 有关框架的更多信息,请看框架官方主页! 本套框架的思想是借鉴Java平台的Hibernate 和 iBatis 而来,兼有ORM和SQL-MAP的特性,同时还参考了后来.N ...

  9. 史诗手册!微信小程序新手自学入门宝典!

    一.小程序官方指南 1:官方开发工具下载: https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html?t=201714 0.12 ...

随机推荐

  1. 使用redis做mysql缓存

    应用Redis实现数据的读写,同时利用队列处理器定时将数据写入mysql. 同时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增 ...

  2. bzoj 2748: [HAOI2012]音量调节

    2748: [HAOI2012]音量调节 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 872  Solved: 577[Submit][Status] ...

  3. Spring中Bean管理的常用注解

    在Spring中,主要用于管理bean的注解分为四大类:1.用于创建对象.2.用于给对象的属性注入值.3.用于改变作用的范围.4.用于定义生命周期.这几个在开发中经常接触到,也可以说每天都会遇见.其中 ...

  4. RBAC权限控制

    1.什么是RBAC权限模型rity2.RBAC权限模型表设计3.整合Mybatis数据库4.UserDetailsService5.动态查询数据库登陆6.动态权限角色拦截 什么是RBAC权限模型r 基 ...

  5. 自然语言处理中的语言模型预训练方法(ELMo、GPT和BERT)

    自然语言处理中的语言模型预训练方法(ELMo.GPT和BERT) 最近,在自然语言处理(NLP)领域中,使用语言模型预训练方法在多项NLP任务上都获得了不错的提升,广泛受到了各界的关注.就此,我将最近 ...

  6. Multiply Strings,字符串相乘

    问题描述:给定两个字符串,返回他们的乘积. public class MultiplyStrings { public String multiply(String num1, String num2 ...

  7. 用Java编程计算猴子吃桃问题

    猴子吃桃问题:猴子吃桃子问题:猴子第一天摘下N个桃子,当时就吃了一半,还不过瘾,就又吃了一个.第二天又将剩下的桃子吃掉一半,又多吃了一个.以后每天都吃前一天剩下的一半零一个.到第10天在想吃的时候就剩 ...

  8. Java条件语句之 if

    生活中,我们经常需要先做判断,然后才决定是否要做某件事情.例如,如果考试成绩大于 90 分,则奖励一个 IPHONE 5S .对于这种“需要先判断条件,条件满足后才执行的情况”,就可以使用if 条件语 ...

  9. scala学习手记33 - 使用trait进行装饰

    在上一节看到了scala的在实例一级的选择性混入就不得不感叹scala在语法上的扩展性.就通过这样一个特性scala简化了很多在java中的编程概念和设计模式. 比如说在java中常用的组合,以及装饰 ...

  10. 两种以太网 RDMA 协议: iWARP 和 RoCE

    本文是讲演 How Ethernet RDMA Protocols iWARP and RoCE Support NVMe over Fabrics[1]的摘要. 如果 NVMe 存储系统与主机是分离 ...