用grunt搭建自动化的web前端开发环境实战教程(详细步骤)
jQuery在使用grunt,bootstrap在使用grunt,百度UEditor在使用grunt,你没有理由不学、不用!
前端自动化,这样的一个名词听起来非常的有吸引力,向往力。当今时代,前端工程师需要维护的代码变得及为庞大和复杂,代码维护、打包、发布等流程也变得极为繁琐,同时浪费的时间和精力也越来越多,当然人为的错误也随着流程的增加而增加了更多的出错率。致使每一个团队都希望有一种工具,能帮助整个团队在开发中能精简流程、提高效率、减少错误率。随之讨论自动化部署也越来越多,并且国内很多大型团队也都有自己成熟的自动化部署工具。据我所知,百度有FIS,腾讯有Modjs,360有燕尾服,还有很多团队在使用Ant,Shell等,而现在讨论较多的是Grunt。
在平常的工作之中,我们都不断的在重复着做相同的事情,比如说将Sass编译成CSS,检测JavaScript语法,压缩CSS、JavaScript。特别在团队合作开发中,常常会为了各自的习惯而不断的发生麻烦,给开发带来极大的不便。而且前端开发人员在周而复始的做这些相同的,乏味的事情。很多时候我们想工作变得更有意义,更能专注于开发,就希望有一种工具能让我们不去做这些重复而乏味的工作。这就有了Grunt,而这个Grunt让我们编码变得更意义,更开心。
Grunt是一个任务管理器,能大大提高您运行前端开发工作流程。使用大量的Grunt插件可以自动执行任务,例如编译Sass和CoffeeScript,优化图像和验证您的JavaScript代码与JSHint。在过去你可能使用类似CodeKit或Hammer来处理这些任务。我认为这两种应用程序是伟大的(过去广泛的使用他们),但Grunt比他们更优秀,他可以定制任务。有很多插件可以帮助你优化图片和在你的工作流中加入CSS样式。
--------------------------------
Grunt: JavaScript世界的构建工具 -- Grunt中文网
http://www.gruntjs.net/
grunt是一套前端自动化工具,一个基于nodeJs的命令行工具,一般用于:压缩文件,合并文件,简单语法检查。
GRUNT JavaScript 世界的构建工具
为何要用构建工具?
一句话:自动化。对于需要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,自动化工具可以减轻你的劳动,简化你的工作。当你在 Gruntfile 文件正确配置好了任务,任务运行器就会自动帮你或你的小组完成大部分无聊的工作。
为什么要使用Grunt?
Grunt生态系统非常庞大,并且一直在增长。由于拥有数量庞大的插件可供选择,因此,你可以利用Grunt自动完成任何事,并且花费最少的代价。如果找不到你所需要的插件,那就自己动手创造一个Grunt插件,然后将其发布到npm上吧。
先看看入门文档http://www.gruntjs.net/getting-started吧。
可用的Grunt插件
你所需要的大多数task都已经作为Grunt插件被开发了出来,并且每天都有更多的插件诞生。插件列表页面列出了完整的清单。
Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器。
提前感受一下 Grunt 吧!
安装 grunt 虽然很简单,更多涉及到如何运行项目。看看下面的演示,这是为项目案例运行 grunt 后的输出。
---------------------------------
用grunt搭建自动化的web前端开发环境实战教程
1. 前言
各位web前端开发人员,如果你现在还不知道grunt或者听说过、但是不会熟练使用grunt,那你就真的out了。Gulp未来有可能替代grunt,但是现在来说市场占有率还是不如grunt。
2. 安装nodejs
Grunt和所有grunt插件都是基于nodejs来运行的。
现在windows安装nodeJS直接下载即可:https://nodejs.org/en/ 根据需要下载,下载完成后直接下一步下一步完成,就具有nodeJS环境了
安装了nodejs之后,可以在你的控制台中输入“node -v”来查看nodejs的版本。
注意:
一,grunt依赖于nodejs的v0.8.0及以上版本;
二,奇数版本号的版本被认为是不稳定的开发版,不过从官网上下载下来的应该都是偶数的稳定版。
三,windows下升级nodejs 仅仅需要安装最新的msi,注意需要与原来文件夹保持一致,会自动删除后创建(360卫士会弹出两次阻止框需要选择允许执行)。
3. 安装grunt-CLI
注意,如果你的电脑不联网,以下操作你都做不了,先保证电脑联网。
“CLI”被翻译为“命令行”。要想使用grunt,首先必须将grunt-cli安装到全局环境中,使用nodejs的“npm install…”进行安装。
打开控制台(windows系统下请使用管理员权限打开),输入:npm install grunt-cli -g (卸载旧版本命令:npm uninstall grunt -g)
mac os 系统、部分linux系统中,在这句话的前面加上“sudo ”指令。
命令行会出现一个转动的小横线,表示正在联网加载。加载的时间看你网速的快慢,不过这个软件比较小,一般加载时间不会很长,稍一会儿,就加载完了。你会看到以下界面。
- abbrev@1.0.7 node_modules\grunt-cli\node_modules\nopt\node_modules\abbrev
C:\Users\Administrator\AppData\Roaming\npm
`-- grunt-cli@1.2.0
+-- findup-sync@0.3.0
| `-- glob@5.0.15
| +-- inflight@1.0.6
| | `-- wrappy@1.0.2
| +-- inherits@2.0.3
| +-- minimatch@3.0.3
| | `-- brace-expansion@1.1.6
| | +-- balanced-match@0.4.2
| | `-- concat-map@0.0.1
| +-- once@1.4.0
| `-- path-is-absolute@1.0.1
+-- grunt-known-options@1.1.0
+-- nopt@3.0.6
| `-- abbrev@1.0.9
`-- resolve@1.1.7
验证grunt-cli是否安装完成并生效,在命令行中输入grunt,回车。
grunt-cli: The grunt command line interface (v1.2.0)
......
如果出现上面提示,说明grunt-cli安装成功了。
安装 grunt-init(可选)
npm install grunt-init -g
可选安装,grunt-init是个脚手架工具,它可以帮你完成项目的自动化创建,包括项目的目录结构,每个目录里的文件等。
4. 创建一个简单的网站
创建一个简单的测试网站来演示grunt的安装、使用。
在电脑的D盘下面创建“grunt_test”文件夹,里面建了三个空文件夹build、src、test,两个空文档Gruntfile.js、package.json。
Gruntfile.js //项目自动化工作流配置文件,重要(注意 Gruntfile.js 文件的首字母大写,后缀名不能是隐藏的.txt)
package.json //项目自动化所依赖的相关插件。
package.json官方文件地址:http://gruntjs.com/getting-started#package.json
{
"name": "my-project-name",
"version": "0.1.0",
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-nodeunit": "~0.4.1",
"grunt-contrib-uglify": "~0.5.0"
}
}
name为项目名称,version为版本,devDependencies是“开发依赖项”,即依赖于哪些插件来开发,格式为插件名:版本。
根据项目情况修改为下面内容:
{
"name": "grunt_test",
"version": "1.0.0",
"devDependencies": {
}
}
5. 安装grunt
Grunt没有具体的作用,但是它能把有具体作用的一个一个插件组合起来,形成一个整体效应。
grunt不是全局安装需要在控制台进入到具体目录下。进入 D:\grunt_test目录下。然后输入以下命令:npm install grunt --save-dev
“--save-dev”的意思是,为在当前目录安装grunt的同时,把grunt保存为这个目录的开发依赖项。
package.json的devDependencies会自动增加"grunt": "^1.0.1"。
grunt_test目录下多了一个“node_modules”文件夹,里面会生成很多子文件夹,这里就是存储grunt源文件的地方。
D:\grunt_test>npm install grunt --save-dev
npm WARN prefer global coffee-script@1.10.0 should be installed with -g
grunt_test@1.0.0 D:\grunt_test
`-- grunt@1.0.1
+-- coffee-script@1.10.0
+-- dateformat@1.0.12
.......
npm WARN grunt_test@1.0.0 No description
npm WARN grunt_test@1.0.0 No repository field.
npm WARN grunt_test@1.0.0 No license field.
在控制台运行“grunt”命令。如果你得到一个warning提示,那说明grunt已经起作用了。
D:\grunt_test>grunt
Warning: Task "default" not found. Use --force to continue.
Aborted due to warnings.
经过以上三步,说明grunt已经在这个目录下成功安装,Warning警告是因为没有配置Gruntfile.js导致的。
6. 配置Gruntfile.js
Gruntfile.js官方文件地址:http://gruntjs.com/getting-started#an-example-gruntfile
module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); // Default task(s). grunt.registerTask('default', ['uglify']); };
根据项目情况修改为:
module.exports = function(grunt) { //项目配置 grunt.initConfig({ //获取package.json信息 pkg: grunt.file.readJSON('package.json') }); // 在输入grunt命令时需要做什么任务,注意先后顺序 grunt.registerTask('default', []); };
将上面内容放到Gruntfile.js保存。
上面配置说明package.json中的内容不光是用来占位置的,还可以在其他地方获取。
再运行一下grunt命令结果为绿色的 Done.说明配置成功。
7. Grunt插件介绍
官网的插件列表 http://www.gruntjs.net/plugins
此插件列表是自动生成的,数据来自npm模块数据库。 官方维护的 "contrib" 插件都被标上星号图标。第三方提供的插件,不带contrib和星号图标。
2016.11.19时有5692个插件了,列表前几个插件,下载量最多,也是大家都在用的插件。
插件
最后更新时间
Grunt 版本
下载量
最近 30 天
contrib-clean 1001579 清空文件、文件夹
contrib-watch 988565 实时监控文件变化、调用相应的任务重新执行
contrib-copy 897190 复制文件、文件夹
contrib-jshint 882830 javascript语法错误检查
contrib-uglify 857367 压缩javascript代码
contrib-concat 689029 合并多个文件的代码到一个文件中
contrib-cssmin 513869 压缩css代码
contrib-less 432259 把less文件编译成css
karma 408769 前端自动化测试工具
contrib-connect 397416 启动一个连接的Web服务器
......
grunt集全世界web前端开发的智慧于一身,比你想想的更加强大,插件库能应对你在web前端开发遇到的任何事情。
8. 使用uglify插件(压缩javascript代码)
Uglify插件的功能就是压缩javascript代码。几乎每一个javascript类库或者框架,都有一个 **.min.js 压缩版。
要安装一个插件,你首先要进入这个插件在grunt官网的说明文档页面。我们在grunt官网插件列表页面,找到“contrib-uglify”点击进入。
https://www.npmjs.com/package/grunt-contrib-uglify
安装uglify插件的方式,和安装grunt是一样的。
npm install grunt-contrib-uglify --save-dev
先运行上面命令。安装完成之后,可以看到package.json中“devDependencies”节点的变化,以及“node_modules”文件夹里的变化。
在现有的“src”文件夹中新建一个“test.js”,并随便写一些代码,来测试压缩javascript代码。
在Gruntfile.js中配置:
对uglify的配置有两项。
“options”中规定允许生成的压缩文件带banner,即在生成的压缩文件第一行加一句话说明。注意,其中使用到了pkg获取package.json的内容。
“build”中配置了源文件和目标文件。即规定了要压缩谁?压缩之后会生成谁?注意,我们这里将目标文件的文件名通过pkg的name和version来命名。
module.exports = function(grunt) { //项目配置 grunt.initConfig({ //获取package.json信息 pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %>-<%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/test.js', dest: 'build/<%= pkg.name %>-<%= pkg.version %>.min.js' } } }); //加载uglify插件任务 grunt.loadNpmTasks('grunt-contrib-uglify'); // 在输入grunt命令时需要做什么任务,注意先后顺序,在grunt命令执行时,立即执行uglify插件 grunt.registerTask('default', ['uglify']); };
在控制台中运行grunt命令,将输入如下信息(注:需要先运行上面的 npm install grunt-contrib-uglify --save-dev命令):
D:\grunt_test>grunt
Running "uglify:build" (uglify) task
>> 1 file created.
Done.
到build目录下查看是否生成了一个压缩后的js文件:grunt_test-1.0.0.min.js,打开内容可以看到第一行注释/*! grunt_test-1.0.0 2016-11-19 */
以上是uglify插件的详细安装、配置说明。Javascript使用uglify压缩,css可使用cssmin插件压缩,方法一样的,其他插件也类似。
9. 使用jshint插件(检查javascript语法错误)
jshint插件的安装和配置跟uglify一样,命令为:npm install grunt-contrib-jshint --save-dev
和uglify的配置一样,分为“options”和“build”两个部分。“build”中描述了jshint要检查哪些js文档的语法。 “options”中描述了要通过怎么的规则检查语法,这些规则的描述文件就保存在网站根目录下的一个叫做“.jshintrc”的文件中。
.jshintrc文件中代码的格式也要遵守严格的json语法,否则无效。搜索“jshint 配置”关键字就可以看到常用配置:
https://my.oschina.net/u/923974/blog/306695
{
"curly": true, // true: Require {} for every new block or scope
"eqeqeq": true, // true: Require triple equals (===) for comparison
"immed": true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
"latedef": true, // true: Require variables/functions to be defined before being used
"newcap": true, // true: Require capitalization of all constructor functions e.g. `new F()`
"noarg": true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
"sub": true, // true: Prohibit use of empty blocks
"undef": true, // true: Require all non-global variables to be declared (prevents global leaks)
"boss": true, // true: Require all defined variables be used
"eqnull": true, // true: Requires all functions run in ES5 Strict Mode
"es3": true, // {int} Max number of formal params allowed per function
"node": true, // {int} Max depth of nested blocks (within functions)
"-W117": true // {int} Max number statements per function
}
插件文档里面也有例子:
{
"curly": true,
"eqnull": true,
"eqeqeq": true,
"undef": true,
"globals": {
"jQuery": true
}
}
在网站的根目录下面添加.jshintrc文件,并把上面内容放到文件里。
注:在windows上不能直接创建文件名以“.”开头的文件,可以在后面加上一个.,或者用命令行:echo > .jshintrc 方式创建。
加载插件没有先后顺序:grunt.loadNpmTasks('grunt-contrib-jshint');
配置grunt命令启动时,要执行的任务,这里注意先后顺序。先检查语法通过了再合并才有意义,所以jshint在uglify之前。
配置改为:grunt.registerTask('default', ['jshint','uglify']);
module.exports = function(grunt) { //项目配置 grunt.initConfig({ //获取package.json信息 pkg: grunt.file.readJSON('package.json'), //uglify 插件配置信息 uglify: { options: { banner: '/*! <%= pkg.name %>-<%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/test.js', dest: 'build/<%= pkg.name %>-<%= pkg.version %>.min.js' } }, jshint: { options: { jshintrc: '.jshintrc' }, build: ['Gruntfile.js','src/*.js'] } }); //加载uglify插件 grunt.loadNpmTasks('grunt-contrib-uglify'); //加载jshint插件 grunt.loadNpmTasks('grunt-contrib-jshint'); // 在输入grunt命令时需要做什么任务,注意先后顺序,在grunt命令执行时,立即执行jshint,uglify插件 grunt.registerTask('default', ['jshint','uglify']); };
再执行grunt命令测试
Running "jshint:build" (jshint) task
Gruntfile.js
2 | //
^ This character may get silently deleted by one or more browsers.
出现上面错误是因为中文注释文件编码ansi的问题,文件编码改成UTF8则可以解决。
Running "jshint:build" (jshint) task
>> 2 files lint free.
Running "uglify:build" (uglify) task
>> 1 file created.
Done.
出现上面内容说明执行成功。
10. 使用csslint插件(检查css语法错误)
检查css文件的语法错误要使用csslint插件,其安装配置方法和jshint几乎一模一样。只不过csslint依赖于一个叫做“.csslintrc”的文件作为语法检验的规则。
https://www.npmjs.com/package/grunt-contrib-csslint
npm install grunt-contrib-csslint --save-dev
grunt.loadNpmTasks('grunt-contrib-csslint');
csslint: {
options: {
csslintrc: '.csslintrc'
},
strict: {
options: {
import: 2
},
src: ['path/to/**/*.css']
},
lax: {
options: {
import: false
},
src: ['path/to/**/*.css']
}
}
“.csslintrc”文件语法检验的规则
{
"qualified-headings": true,
"unique-headings": true,
"known-properties": false
}
11. 使用watch插件(真正实现自动化)
上面的插件,每次执行插件功能,都得执行一遍“grunt”命令,这样的操作非常繁琐,通过watch插件解决这个问题。
安装watch插件:npm install grunt-contrib-watch --save-dev,grunt.loadNpmTasks('grunt-contrib-watch');
配置watch将监控哪些文件的变化,以及这些文件一旦变化,要立即执行哪些插件功能。
watch将监控src文件夹下所有js文件和css文件的变化,一旦变化,则立即执行jshint和uglify两个插件功能。
module.exports = function(grunt) { //项目配置 grunt.initConfig({ //获取package.json信息 pkg: grunt.file.readJSON('package.json'), //uglify 插件配置信息 uglify: { options: { banner: '/*! <%= pkg.name %>-<%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/test.js', dest: 'build/<%= pkg.name %>-<%= pkg.version %>.min.js' } }, jshint: { options: { jshintrc: '.jshintrc' }, build: ['Gruntfile.js','src/*.js'] }, watch: { build: { files: [ 'src/*.js' ], tasks:['jshint','uglify'], options: { spawn: false } } } }); //加载uglify插件 grunt.loadNpmTasks('grunt-contrib-uglify'); //加载jshint插件 grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-watch'); // 在输入grunt命令时需要做什么任务,注意先后顺序,在grunt命令执行时,立即执行jshint,uglify插件 grunt.registerTask('default', ['jshint','uglify','watch']); };
运行grunt命令,控制台提示watch已经开始监听。停止监听按ctrl+ c即可。
既然在监听,我们试一试看监听有没有效。我们将 test.js 代码中去掉一个分号,看它能否自动检查出来这个错误。
结果显示,watch检查到了test.js文件的变化,而且通过执行jshint提示了语法错误。
更重要的是,它现在还在监听、并未停止。说明它正在等着你去修改错误,重新监听检查。
检测到文件变化执行了jshint和uglify,执行完毕之后重新进行监听。从而实现了自动化。
D:\grunt_test>grunt
Running "jshint:build" (jshint) task
>> 2 files lint free.
Running "uglify:build" (uglify) task
>> 1 file created.
Running "watch" task
Waiting...
>> File "src\test.js" changed.
Running "jshint:build" (jshint) task
src/test.js
8 | var b = "bbb"
^ Missing semicolon.
>> 1 error in 2 files
Warning: Task "jshint:build" failed.
Running "watch" task
Waiting...
>> File "src\test.js" changed.
Running "jshint:build" (jshint) task
>> 2 files lint free.
Running "uglify:build" (uglify) task
>> 1 file created.
Running "watch" task
Completed in 0.094s at Sat Nov 19 2016 06:35:31 GMT+0800 (中国标准时间) - Waitin
g...
^C终止批处理操作吗(Y/N)? y
D:\grunt_test>
停止监听按ctrl+ c即可。
12. 配置中的“build”
各个插件的配置时,都是用了“build”这一名称作为一个配置项。而实际不一定要用build。
这里可以用任何字符串代替“build”(但要符合js语法规则)。甚至,你可以把“build”指向的内容分开来写,把数组拆分成多个变量。这样对多人协同开发很友好。
13. 批量安装插件,同步开发安装插件
在上传代码到开发库的时候,不会把“node_modules”中的内容也上传(内容很多也比较大),其他一起开发的人,怎么得到这些grunt插件和工具呢?
解决办法是把package.json上传上去,而package.json中的“devDependencies”就记录了这个系统的开发依赖项,然后通过nodejs的npm即可批量安装。
实验方法:在D盘下面新建一个目录“grunt_test_1”,然后把“grunt_test”中的package.json拷过去。在打开命令行跳转到“grunt_test_1”,执行“npm install”命令,结果在“grunt_test_1”生成了“node_modules”文件夹,里面安装好了package.json中“devDependencies”配置的插件。而且,版本都是一致的。(跟java用maven管理jar包有点类似)
package.json
{ "name": "grunt_test", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.1", "grunt-contrib-csslint": "^2.0.0", "grunt-contrib-jshint": "^1.0.0", "grunt-contrib-uglify": "^2.0.0", "grunt-contrib-watch": "^1.0.0" } }
14. 系统文件结构
使用grunt来搭建web前端开发环境文档目录和之前可能不一样。手动写的代码文件,不是最终输出的文件。还需要经过grunt各种插件的检验、合并、压缩才能最终输出给用户。
例如“src”文件夹里面存储的是原始的代码文件,“dist”文件夹里面存储的是最终生成的代码文件,“demo”里面存储的是一些测试页面。
各个系统的文件组织形式不一样,建议大家去github上参考一下jquery、 bootstrap这些著名开源项目的文档结构。
jquery输出的虽然是简单的一个js文件,但是它的开发目录结构是很复杂的。