您好,登录后才能下订单哦!
原文地址:http://www.smashingmagazine.com/2013/10/29/get-up-running-grunt/
这篇文章中,我们将介绍如何在项目使用Grunt让你的网站更快。我们简要分析下grunt能够做什么,如何创建和使用各种插件完成各种繁重的任务。我们将看看如何构建一个简单的表单验证器,使用Sass预处理器,如何使用grunt-cssc和CssMin结合压缩我们的CSS,如何使用HTMLHint确保我们的HTML书写正确,以及如何快速地构建我们的压缩资源,最后,也会看看使用UglifyJS减小我们JavaScript的大小和确保我们的网站使用尽可能少的带宽。
Grunt.js是一个JavaScript任务构建器,他可以帮助你执行重复性任务,比如压缩,编译,单元测试等。
开始使用Grunt
大多数开发人员都一致认为,JavaScript开发的速度和节奏在过去的几年里已经相当惊人。不管是Backbone.js和Ember.js的框架还是JS Bin社区,这种语言的发展变化不仅提高我们网站的用户体验还有构建方式。
当使用JavaScript,你可能需要定期执行多个任务。虽然这在大多项目中都存在,但切实是一个耗时的和重复的工作方式。在这样一个活跃的社区,假设有工具都可以实现自动化,加快这个过程。此时就出现了Grunt。
什么是Grunt
建立在Node.js之上,Grunt是一个基于命令行的工具,用于加快工作流程,减少所需的准备工作。将作业打包到任务中,可以自动编译。基本上,你可以使用Grunt的大部分任务来帮你处理,通常需要手工配置和运行。
虽然早期版本附带了JSHint和Uglyify插件,但最近的版本(0.4版本)依赖于插件来完成所有的工作。
都有什么样的任务呢?这有一个详细的列表。我只想说,Grunt可以处理大部你想处理的事情,从压缩到加载JavaScript。他也可以用于与JavaScript无关的一系列任务,比如说将Sass和LESS编译成CSS。我们甚至使用blink当构建失败时通知我们。
为什么要使用Grunt
最爽的事情之一就是Grunt让团队做到一致性。如果你的工作是协作型的,你将要知道在代码中不一致性多么令人烦恼的。Grunt工作使用团队具有统一的命令,从而确保团队中的每个人都使用相同的标准来编写代码。毕竟,因为在团队中如何编写代码这样的小问题引起项目失败更让人感到沮丧.
Grunt也有一个令人难以置信的活跃社区,开发人员会在社区中定期发布新插件。进入的门槛相对较低,因为广泛的工具和自动执行的任务可以使用。
安装
使用Grunt的首要事情就是安装Node.js。(如果你对Node.js一无所知,别担心,它只是为Grunt能够运行而安装)。
一旦安装好了Node.js,你可以终端命令中输入:
npm install -g grunt-cli
为了确保Grunt已经正确安装,你可以运行下面的命令:
grunt --version
接下来在你项目的根目中创建一个package.json和一个Gruntfile.js文件。
创建package.json文件
该JSON文件使我们能跟踪和安装我们所有开发依赖项。然后,对项目工作的人会拥有当前开发依赖性,最终有助于保持开发环境的同步。
在你项目根目录下创建一个文件,并且包含下面的信息:
{ "name" : "SampleGrunt", "version" : "0.1.0", "author" : "Brandon Random", "private" : true, "devDependencies" : { "grunt" : "~0.4.0" } }
完成后,运行如下命令:
npm install
告诉npm所需的依赖关系,然后把它们安装在node_modules目录中。这个时候,你的项目的根目录下会新增加一个node_modules的目录:
创建Gruntfile.js文件
Gruntfile.js本质上是一个包装后函数,参数是grunt。
module.exports =function(grunt){ grunt.initConfig({ pkg: grunt.file.readJSON('package.json') }); grunt.registerTask('default',[]); };
现在可以在项目根根目录下运行Grunt命令。但是在这个阶段你这样做,你将会看到以下的警告信息:
grunt > Task "default" not found. Use --force to continue.
得到这样的信息是因为我们除了Grunt之外没有指定任何任务和依赖。所以,我们必须得制定。但首先,让我们看看如何扩展package.json文件。
扩展package.json文件
最好是通过Node.js来处理,它可以找到安装包并将他们一次性安装,而且只基于包文件的内容。为了安装所有的依赖项,只需要在文件中添加下面的内容:
{ "name": "SampleGrunt", "version": "0.1.0", "author": "Mike Cunsolo", "private": true, "devDependencies": { "grunt": "~0.4.0", "grunt-contrib-cssmin": "*", "grunt-contrib-sass": "*", "grunt-contrib-uglify": "*", "grunt-contrib-watch": "*", "grunt-cssc": "*", "grunt-htmlhint": "*", "matchdep": "*" } }
输入以下命令:
npm install
在Grunt中加载npm任务
现在任务包已安装好了,他们已经加载到Grunt中。使用matchdep我们可以使用一行代码加载所有的任务。这是很好的一点,因为现在依赖关系的列表都只包括了包文件。 在Gruntfile.js的顶部grunt.initConfig上面粘贴下面的一段代码:
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
没有matchdep,我们需要为每个依赖关系写grunt.loadNpmTasks('grunt-task-name'), matchdep提高了增加和安装其他插件的速度。插件加载到Grunt中,我们有可能会指定选项。首先是HTML文件(index.html),包含下面的内容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"> <title>Enter your first name</title> <link rel="stylesheet" href="build/css/master.css"> </head> <body> <label for="firstname">Enter your first name</label> <input id="firstname" name="firstname" type="text"> <p id="namevalidation" class="validation"></p> <script type="text/javascript" src="build/js/base.min.js"></script> </body> </html>
使用HTMLHint验证
在grunt.initConfig中添加这样的配置:
htmlhint: { build: { options: { 'tag-pair': true, 'tagname-lowercase': true, 'attr-lowercase': true, 'attr-value-double-quotes': true, 'doctype-first': true, 'spec-char-escape': true, 'id-unique': true, 'head-script-disabled': true, 'style-disabled': true }, 'src': ['index.html'] } }
一个插件的配置通常是这样的:插件的名称(不带grunt-contrib-/grunt-前缀),然后是选择的一个或更多的目标(可以用于创建自定义插件的文件),一个options对象和这个文件作用效果。现在你在终端运行grunt htmlhint,它会查看源文件,并确保我们的HTML没有错误!然而,一小时手动输入这个命令数次,会让你的工作很快变得乏味。
每次保存文件自动化运行任务
watch任务是一个可以根据被保存的文件运行独特的任务。在grunt.initConfig加入下面的代码:
watch: { html: { files: ['index.html'], tasks: ['htmlhint'] } }
现在,在终端中运行grunt watch。给index.html中添加一个注释,就会发现当保存文件是,验证的任务会自动执行。这对开发者来说是一个很好的工具,因为当你写代码时watch会默默的执行,如果没有通过相应的测试,就会报错(还会告诉你错误的原因是什么)。
注意 grunt watch会继续运行除非你手动停止(Mac上使用control + C)
尽可能让JavaScript文件小
让我们创建一个JavaScript文件来验证一个用户名。尽可能简单,将检查的只是非字母字符。我们也会利用JavaScript的strict模式,它阻止我们写有效但质量差的JavaScript。把下面的代码粘贴到assets/js/base.js:
function Validator() { "use strict"; } Validator.prototype.checkName = function(name) { "use strict"; return (/[^a-z]/i.test(name) === false); }; window.addEventListener('load', function(){ "use strict"; document.getElementById('firstname').addEventListener('blur', function(){ var _this = this; var validator = new Validator(); var validation = document.getElementById('namevalidation'); if (validator.checkName(_this.value) === true) { validation.innerHTML = 'Looks good! :)'; validation.className = "validation yep"; _this.className = "yep"; } else { validation.innerHTML = 'Looks bad! :('; validation.className = "validation nope"; _this.className = "nope"; } }); });
我们使用UglifyJS来压缩这个文件,在grunt.initConfig中加入下面代码:
uglify: { build: { files: { 'build/js/base.min.js': ['assets/js/base.js'] } } }
UglifyJS压缩源文件中所有的变量和函数名,让文件尽可能少的占用空间,然后去掉空白和注释——非常适合用于生产的JavaScript。接着,我们需要为我们的Uglify的JavaScript创建一个watch任务。将下面的代码添加到watch配置中:
watch: { js: { files: ['assets/js/base.js'], tasks: ['uglify'] } }
从Sass源文件创建CSS
Sass用来处理CSS是令人难以置信的有用,特别是在一个团队。通常在源文件中写更少的代码,因为Sass可以使用函数和变量产生大的CSS代码块。如何使用Sass本身有点超出了本文的范围,所以,在这个阶段你还不习惯和学习一个预处理器,你可以跳过这一节。我们将介绍一个非常简单的用例,使用具有变量和混合的SCSS,这非常类似于CSS!
Grunt的Sass插件需要sass gem。你将需要在你的系统上安装Ruby(Mac 上已经预装了)。你可以在你的终端使用下面的命令检查你的系统是否安装了Ruby:
ruby -v
通过命令安装Sass
gem install sass
根据您的配置,你可以需要通过sudo命令来运行这个命令——例如sudo gem install sass——这个时候终端会要求你输入你的电脑登录密码。当Sass安装好后,创建一个新的目录叫作assets,并在里面创建另一个叫sass目录。在这个目录中创建一个新的文件名master.scss,并将下面的代码粘贴进行:
@mixin prefix($property, $value, $prefixes: webkit moz ms o spec) { @each $p in $prefixes { @if $p == spec { #{$property}: $value; } @else { -#{$p}-#{$property}: $value; } } } $input_field: #999; $input_focus: #559ab9; $validation_passed: #8aba56; $validation_failed: #ba5656; $bg_colour: #f4f4f4; $box_colour: #fff; $border_style: 1px solid; $border_radius: 4px; html { background: $bg_colour; } body { width: 720px; padding: 40px; margin: 80px auto; background: $box_colour; box-shadow: 0 1px 3px rgba(0, 0, 0, .1); border-radius: $border_radius; font-family: sans-serif; } input[type="text"] { @include prefix(appearance, none, webkit moz); @include prefix(transition, border .3s ease); border-radius: $border_radius; border: $border_style $input_field; width: 220px; } input[type="text"]:focus { border-color: $input_focus; outline: 0; } label, input[type="text"], .validation { line-height: 1; font-size: 1em; padding: 10px; display: inline; margin-right: 20px; } input.yep { border-color: $validation_passed; } input.nope { border-color: $validation_failed; } p.yep { color: $validation_passed; } p.nope { color: $validation_failed; }
你将发现SCSS扩展起来比传统的Sass更像CSS。这个样式表中使用了Sass的两个特性:混合(mixins)和变量(variables)。Mixins就像一个函数,可以将一些参数传递给它,用来构造CSS块,然后重用。
变量是特别有用的十六进制颜色,我们可以是构建一个调色板,可以在一个地方改变,非常快的调整整个方面设计。Mixin可以用于前缀等规则上,例如appearance和transition等属性,它可以减少写很多重复性代码。
在处理大型样式表时,当一个团队的其他成员想要更新一个样式,什么方法可以减少行数使用文件易于阅读。
除了Sass,Grunt-cssc和CSS规则结合在一起,确保生成的CSS有最和的重复代码。在中大型项目是有很多风格是重复的,这显得非常的有用。然而,输出的文件并不总是总小的。这样就出现了cssmin任务。它不仅可以去掉代码中的空格,而且琮可以将颜色转换成最短值(因此,white将转换成#fff)。在Gruntfile.js中加入下面的任务:
cssc: { build: { options: { consolidateViaDeclarations: true, consolidateViaSelectors: true, consolidateMediaQueries: true }, files: { 'build/css/master.css': 'build/css/master.css' } } }, cssmin: { build: { src: 'build/css/master.css', dest: 'build/css/master.css' } }, sass: { build: { files: { 'build/css/master.css': 'assets/sass/master.scss' } } }
现在,我们有一些在适当的地方处理样式表,这些任务也应该自动运行。build目录是Grunt自动创建的,用来放置脚本,CSS和(如果这是一个完整的网站)压缩图像。这意味着assets目录是用于放置开发的文件,里面文件内容有可能有大量的注释或很多文件,然而build目录,是用来放置用于生产环境所需的文件,里面只留下了心样能优化后的文件。
我们将定义一组新的任务来处理CSS。在gruntfile.js中添加下面的代码,下面是默认的task:
grunt.registerTask('buildcss', ['sass', 'cssc', 'cssmin']);
现在,当运行grunt buildcss,所有CSS任务将一个接一个执行。这远比运行grunt sass,接着grunt cssc,接着grunt cssmin更快。我们可以通过配置watch做所有更新,自动运行。
watch: { css: { files: ['assets/sass/**/*.scss'], tasks: ['buildcss'] } }
这路径你看起来有点奇怪。基本上,它会依次检查assets/sass目录下所有目录中的.scss文件,它充行我们创建尽可能多的Sass文件,而无需在gruntfile.js中添加路径。添加这个之后,gruntfile.js将会像下面这样:
module.exports = function(grunt){ "use strict"; require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks); grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), cssc: { build: { options: { consolidateViaDeclarations: true, consolidateViaSelectors: true, consolidateMediaQueries: true }, files: { 'build/css/master.css': 'build/css/master.css' } } }, cssmin: { build: { src: 'build/css/master.css', dest: 'build/css/master.css' } }, sass: { build: { files: { 'build/css/master.css': 'assets/sass/master.scss' } } }, watch: { html: { files: ['index.html'], tasks: ['htmlhint'] }, js: { files: ['assets/js/base.js'], tasks: ['uglify'] }, css: { files: ['assets/sass/**/*.scss'], tasks: ['buildcss'] } }, htmlhint: { build: { options: { 'tag-pair': true, // Force tags to have a closing pair 'tagname-lowercase': true, // Force tags to be lowercase 'attr-lowercase': true, // Force attribute names to be lowercase e.g. <div id="header"> is invalid 'attr-value-double-quotes': true, // Force attributes to have double quotes rather than single 'doctype-first': true, // Force the DOCTYPE declaration to come first in the document 'spec-char-escape': true, // Force special characters to be escaped 'id-unique': true, // Prevent using the same ID multiple times in a document 'head-script-disabled': true, // Prevent script tags being loaded in the for performance reasons 'style-disabled': true // Prevent style tags. CSS should be loaded through }, src: ['index.html'] } }, uglify: { build: { files: { 'build/js/base.min.js': ['assets/js/base.js'] } } } }); grunt.registerTask('default', []); grunt.registerTask('buildcss', ['sass', 'cssc', 'cssmin']); };
我们现在有一个静态的HTML页面,一个放了Sass和JavaScript资源的assets目录,以及一个放了整理的CSS和JavaScript文件在build目录中,以及一个package.json和gruntfile.js文件。
现在,你应该有一个很坚实的基础,可以进一步探讨Grunt。正如前面所提到的,一个令人难以置信的活跃的开发者社区在不断的提供前端插件。我的建议是,请到插件库查阅这300多个插件。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。