0% found this document useful (0 votes)
13 views

Javascript Frameworks For Modern Web Dev 1st Edition Tim Ambler download

The document provides information about various JavaScript frameworks for modern web development, including Bower, Grunt, Yeoman, and others. It includes links to download the book and additional resources related to JavaScript frameworks. The content is structured into chapters that cover installation, configuration, and usage of different frameworks and tools.

Uploaded by

quecyhiack
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

Javascript Frameworks For Modern Web Dev 1st Edition Tim Ambler download

The document provides information about various JavaScript frameworks for modern web development, including Bower, Grunt, Yeoman, and others. It includes links to download the book and additional resources related to JavaScript frameworks. The content is structured into chapters that cover installation, configuration, and usage of different frameworks and tools.

Uploaded by

quecyhiack
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 78

Javascript Frameworks For Modern Web Dev 1st

Edition Tim Ambler download

https://ebookbell.com/product/javascript-frameworks-for-modern-
web-dev-1st-edition-tim-ambler-50195406

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

Javascript Frameworks For Modern Web Dev Tim Ambler Nicholas Cloud
Auth

https://ebookbell.com/product/javascript-frameworks-for-modern-web-
dev-tim-ambler-nicholas-cloud-auth-5233896

Javascript Frameworks For Modern Web Development 2nd Edition 2nd


Edition Sufyan Bin Uzayr

https://ebookbell.com/product/javascript-frameworks-for-modern-web-
development-2nd-edition-2nd-edition-sufyan-bin-uzayr-50195408

Javascript Simple Guide For Concepts Libraries Frameworks Tools Joseph

https://ebookbell.com/product/javascript-simple-guide-for-concepts-
libraries-frameworks-tools-joseph-232143592

Beginning Phonegap Mobile Web Framework For Javascript And Html5 1st
Edition Rohit Ghatol

https://ebookbell.com/product/beginning-phonegap-mobile-web-framework-
for-javascript-and-html5-1st-edition-rohit-ghatol-2581586
Beginning Phonegap Mobile Web Framework For Javascript And Html5 Rohit
Ghatol

https://ebookbell.com/product/beginning-phonegap-mobile-web-framework-
for-javascript-and-html5-rohit-ghatol-2620924

Sencha Touch 10 Mobile Javascript Framework Build Web Applications For


Apple Ios And Google Android Touchscreen Devices With This First Html5
Mobile Framework 1st Edition Narasimha Rao

https://ebookbell.com/product/sencha-touch-10-mobile-javascript-
framework-build-web-applications-for-apple-ios-and-google-android-
touchscreen-devices-with-this-first-html5-mobile-framework-1st-
edition-narasimha-rao-4107484

Making Multiplayer Online Games A Game Development Workbook For Any


Phaser Javascript Gaming Framework Stephen Gose

https://ebookbell.com/product/making-multiplayer-online-games-a-game-
development-workbook-for-any-phaser-javascript-gaming-framework-
stephen-gose-51878366

Professional Javascript Frameworks Prototype Yui Ext Js Dojo And


Mootools Leslie M Orchard Scott Koon Et Al

https://ebookbell.com/product/professional-javascript-frameworks-
prototype-yui-ext-js-dojo-and-mootools-leslie-m-orchard-scott-koon-et-
al-4106364

Professional Javascript Frameworks Prototypeyui Extjs Dojo And


Mootools Wrox Programmer To Programmer Leslie M Orchard

https://ebookbell.com/product/professional-javascript-frameworks-
prototypeyui-extjs-dojo-and-mootools-wrox-programmer-to-programmer-
leslie-m-orchard-1629886
I
Fa Ma Kn Re Grun nclu
ye ch oc q t, de
, Q , ko uir Ye s B
, A Mo ut eJ om o
sy ng , A S,B a we
nc o ng ro n, r,
.js ose ul w PM
, U , ar se 2
nd K n JS, rif ,
er ex, Kr y,
sco B ak
re, ook en
an she ,
d L lf,
od
as
h

www.it-ebooks.info
JavaScript Frameworks
for Modern Web Dev

Tim Ambler
Nicholas Cloud

www.it-ebooks.info
JavaScript Frameworks for Modern Web Dev
Copyright © 2015 by Tim Ambler and Nicholas Cloud
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed. Exempted from this legal reservation are brief excerpts in connection with
reviews or scholarly analysis or material supplied specifically for the purpose of being entered and executed
on a computer system, for exclusive use by the purchaser of the work. Duplication of this publication or
parts thereof is permitted only under the provisions of the Copyright Law of the Publisher’s location, in its
current version, and permission for use must always be obtained from Springer. Permissions for use may be
obtained through RightsLink at the Copyright Clearance Center. Violations are liable to prosecution under
the respective Copyright Law.
ISBN-13 (pbk): 978-1-4842-0663-8
ISBN-13 (electronic): 978-1-4842-0662-1
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol
with every occurrence of a trademarked name, logo, or image we use the names, logos, and images only
in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are
not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director: Welmoed Spahr
Lead Editor: Louise Corrigan
Technical Reviewer: Robin Hawkes
Editorial Board: Steve Anglin, Mark Beckner, Gary Cornell, Louise Corrigan, James DeWolf,
Jonathan Gennick, Robert Hutchinson, Michelle Lowman, James Markham, Matthew Moodie,
Jeffrey Pepper, Douglas Pundick, Ben Renow-Clarke, Gwenan Spearing, Matt Wade, Steve Weiss
Coordinating Editor: Kevin Walter
Copy Editor: Bill McManus
Compositor: SPi Global
Indexer: SPi Global
Artist: SPi Global
Cover Designer: Crest
Distributed to the book trade worldwide by Springer Science+Business Media New York,
233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail
[email protected], or visit www.springeronline.com. Apress Media, LLC is a California LLC
and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc).
SSBM Finance Inc is a Delaware corporation.
For information on translations, please e-mail [email protected], or visit www.apress.com.
Apress and friends of ED books may be purchased in bulk for academic, corporate, or promotional use.
eBook versions and licenses are also available for most titles. For more information, reference our Special
Bulk Sales–eBook Licensing web page at www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this text is available to
readers at www.apress.com/. For detailed information about how to locate your book’s source code, go to
www.apress.com/source-code/.

www.it-ebooks.info
There was a young lady named Laura,
Who was a beautiful señora.
Her love and assurance
Was a frequent occurrence
Which allowed me to write this book for yah.
—Tim

Dedicated to Brittany who supported me and gave me space


during the long hours that writing demands.
—Nicholas

www.it-ebooks.info
Contents at a Glance

About the Authors���������������������������������������������������������������������������������������������������xix


About the Technical Reviewer��������������������������������������������������������������������������������xxi
Acknowledgments������������������������������������������������������������������������������������������������xxiii
Introduction�����������������������������������������������������������������������������������������������������������xxv


■Chapter 1: Bower��������������������������������������������������������������������������������������������������� 1

■Chapter 2: Grunt�������������������������������������������������������������������������������������������������� 11

■Chapter 3: Yeoman���������������������������������������������������������������������������������������������� 37

■Chapter 4: PM2���������������������������������������������������������������������������������������������������� 53

■Chapter 5: RequireJS������������������������������������������������������������������������������������������� 73

■Chapter 6: Browserify���������������������������������������������������������������������������������������� 101

■Chapter 7: Knockout������������������������������������������������������������������������������������������ 121

■Chapter 8: AngularJS���������������������������������������������������������������������������������������� 155

■Chapter 9: Kraken���������������������������������������������������������������������������������������������� 191

■Chapter 10: Mach���������������������������������������������������������������������������������������������� 251

■Chapter 11: Mongoose��������������������������������������������������������������������������������������� 297

■Chapter 12: Knex and Bookshelf����������������������������������������������������������������������� 345

■Chapter 13: Faye������������������������������������������������������������������������������������������������ 381

www.it-ebooks.info
■ Contents at a Glance


■Chapter 14: Q����������������������������������������������������������������������������������������������������� 395

■Chapter 15: Async.js����������������������������������������������������������������������������������������� 425

■Chapter 16: Underscore and Lodash����������������������������������������������������������������� 447

Index��������������������������������������������������������������������������������������������������������������������� 477

vi

www.it-ebooks.info
Contents

About the Authors���������������������������������������������������������������������������������������������������xix


About the Technical Reviewer��������������������������������������������������������������������������������xxi
Acknowledgments������������������������������������������������������������������������������������������������xxiii
Introduction�����������������������������������������������������������������������������������������������������������xxv


■Chapter 1: Bower��������������������������������������������������������������������������������������������������� 1
Getting Started����������������������������������������������������������������������������������������������������������������� 2
Configuring Bower������������������������������������������������������������������������������������������������������������ 2
The Manifest�������������������������������������������������������������������������������������������������������������������� 2
Creating a New Manifest������������������������������������������������������������������������������������������������������������������������ 3

Finding, Adding, and Removing Bower Packages������������������������������������������������������������ 3


Finding Packages����������������������������������������������������������������������������������������������������������������������������������� 3
Adding Packages������������������������������������������������������������������������������������������������������������������������������������ 4
Removing Packages������������������������������������������������������������������������������������������������������������������������������� 5

Semantic Versioning��������������������������������������������������������������������������������������������������������� 6
Managing the Dependency Chain������������������������������������������������������������������������������������� 7
Creating Bower Packages������������������������������������������������������������������������������������������������ 8
Choose a Valid Name������������������������������������������������������������������������������������������������������������������������������ 8
Use Semver Git Tags������������������������������������������������������������������������������������������������������������������������������� 8
Publish Your Package to the Registry����������������������������������������������������������������������������������������������������� 9

Summary�������������������������������������������������������������������������������������������������������������������������� 9

vii

www.it-ebooks.info
■ Contents


■Chapter 2: Grunt�������������������������������������������������������������������������������������������������� 11
Installing Grunt��������������������������������������������������������������������������������������������������������������� 12
How Grunt Works������������������������������������������������������������������������������������������������������������ 12
Gruntfile.js�������������������������������������������������������������������������������������������������������������������������������������������� 12
Tasks���������������������������������������������������������������������������������������������������������������������������������������������������� 14
Plugins�������������������������������������������������������������������������������������������������������������������������������������������������� 14
Configuration���������������������������������������������������������������������������������������������������������������������������������������� 15

Adding Grunt to Your Project������������������������������������������������������������������������������������������ 15


Maintaining a Sane Grunt Structure����������������������������������������������������������������������������������������������������� 15

Working with Tasks�������������������������������������������������������������������������������������������������������� 18


Managing Configuration����������������������������������������������������������������������������������������������������������������������� 18
Task Descriptions��������������������������������������������������������������������������������������������������������������������������������� 18
Asynchronous Tasks����������������������������������������������������������������������������������������������������������������������������� 19
Task Dependencies������������������������������������������������������������������������������������������������������������������������������� 20
Multi-Tasks������������������������������������������������������������������������������������������������������������������������������������������� 20
Multi-Task Options�������������������������������������������������������������������������������������������������������������������������������� 22
Configuration Templates����������������������������������������������������������������������������������������������������������������������� 23
Command-Line Options������������������������������������������������������������������������������������������������������������������������ 24
Providing Feedback������������������������������������������������������������������������������������������������������������������������������ 24
Handling Errors������������������������������������������������������������������������������������������������������������������������������������� 25

Interacting with the File System������������������������������������������������������������������������������������ 25


Source-Destination Mappings�������������������������������������������������������������������������������������������������������������� 26
Watching for File Changes�������������������������������������������������������������������������������������������������������������������� 28

Creating Plugins������������������������������������������������������������������������������������������������������������� 32
Getting Started������������������������������������������������������������������������������������������������������������������������������������� 32
Creating the Task���������������������������������������������������������������������������������������������������������������������������������� 32
Publishing to npm��������������������������������������������������������������������������������������������������������������������������������� 35

Summary������������������������������������������������������������������������������������������������������������������������ 36
Related Resources��������������������������������������������������������������������������������������������������������� 36

viii

www.it-ebooks.info
■ Contents


■Chapter 3: Yeoman���������������������������������������������������������������������������������������������� 37
Installing Yeoman����������������������������������������������������������������������������������������������������������� 38
Creating Your First Project���������������������������������������������������������������������������������������������� 38
Subcommands�������������������������������������������������������������������������������������������������������������������������������������� 41

Creating Your First Generator����������������������������������������������������������������������������������������� 42


Yeoman Generators are Node Modules������������������������������������������������������������������������������������������������ 42
Sub-Generators������������������������������������������������������������������������������������������������������������������������������������ 43
Defining Secondary Commands����������������������������������������������������������������������������������������������������������� 49
Composability��������������������������������������������������������������������������������������������������������������������������������������� 51

Summary������������������������������������������������������������������������������������������������������������������������ 52
Related Resources��������������������������������������������������������������������������������������������������������� 52

■Chapter 4: PM2���������������������������������������������������������������������������������������������������� 53
Installation���������������������������������������������������������������������������������������������������������������������� 53
Working with Processes������������������������������������������������������������������������������������������������� 54
Recovering from Errors������������������������������������������������������������������������������������������������������������������������ 56
Responding to File Changes����������������������������������������������������������������������������������������������������������������� 58

Monitoring Logs������������������������������������������������������������������������������������������������������������� 58
Monitoring Resource Usage������������������������������������������������������������������������������������������� 60
Monitoring Local Resources����������������������������������������������������������������������������������������������������������������� 60
Monitoring Remote Resources������������������������������������������������������������������������������������������������������������� 61
Advanced Process Management������������������������������������������������������������������������������������ 63
JSON Application Declarations������������������������������������������������������������������������������������������������������������� 63

Load-Balancing Across Multiple Processors������������������������������������������������������������������ 68


Zero-Downtime Deployments��������������������������������������������������������������������������������������������������������������� 70

Summary������������������������������������������������������������������������������������������������������������������������ 72
Related Resources��������������������������������������������������������������������������������������������������������� 72

ix

www.it-ebooks.info
■ Contents


■Chapter 5: RequireJS������������������������������������������������������������������������������������������� 73
Running the Examples���������������������������������������������������������������������������������������������������� 74
Working with RequireJS������������������������������������������������������������������������������������������������� 74
Installation�������������������������������������������������������������������������������������������������������������������������������������������� 75
Configuration���������������������������������������������������������������������������������������������������������������������������������������� 75
Application Modules and Dependencies����������������������������������������������������������������������������������������������� 78
Paths and Aliases��������������������������������������������������������������������������������������������������������������������������������� 81
Shims���������������������������������������������������������������������������������������������������������������������������������������������������� 84
Loader Plugins�������������������������������������������������������������������������������������������������������������������������������������� 88
Cache Busting��������������������������������������������������������������������������������������������������������������������������������������� 94

RequireJS Optimizer������������������������������������������������������������������������������������������������������� 96
Configuring r.js������������������������������������������������������������������������������������������������������������������������������������� 96
Running the r.js Command������������������������������������������������������������������������������������������������������������������� 97

Summary������������������������������������������������������������������������������������������������������������������������ 99

■Chapter 6: Browserify���������������������������������������������������������������������������������������� 101
The AMD API vs. CommonJS���������������������������������������������������������������������������������������� 102
Installing Browserify���������������������������������������������������������������������������������������������������� 102
Creating Your First Bundle�������������������������������������������������������������������������������������������� 103
Visualizing the Dependency Tree���������������������������������������������������������������������������������� 104
Creating New Bundles As Changes Occur�������������������������������������������������������������������� 105
Watching for File Changes with Grunt������������������������������������������������������������������������������������������������ 106
Watching for File Changes with Watchify������������������������������������������������������������������������������������������� 106

Using Multiple Bundles������������������������������������������������������������������������������������������������ 108


The Node Way��������������������������������������������������������������������������������������������������������������� 111
Module Resolution and the NODE_PATH Environment Variable���������������������������������������������������������� 111
Dependency Management������������������������������������������������������������������������������������������������������������������ 114

Defining Browser-Specific Modules����������������������������������������������������������������������������� 115

www.it-ebooks.info
■ Contents

Extending Browserify with Transforms������������������������������������������������������������������������� 116


brfs����������������������������������������������������������������������������������������������������������������������������������������������������� 116
folderify���������������������������������������������������������������������������������������������������������������������������������������������� 117
bulkify������������������������������������������������������������������������������������������������������������������������������������������������� 118
Browserify-Shim��������������������������������������������������������������������������������������������������������������������������������� 119

Summary���������������������������������������������������������������������������������������������������������������������� 120
Related Resources������������������������������������������������������������������������������������������������������� 120

■Chapter 7: Knockout������������������������������������������������������������������������������������������ 121
Views, Models, and View Models��������������������������������������������������������������������������������� 122
The Recipe List����������������������������������������������������������������������������������������������������������������������������������� 124
Recipe Details������������������������������������������������������������������������������������������������������������������������������������� 127

Binding View Models to the DOM��������������������������������������������������������������������������������� 129


View Models and Forms����������������������������������������������������������������������������������������������� 131
Switching to “Edit” Mode������������������������������������������������������������������������������������������������������������������� 131
Changing the Recipe Title������������������������������������������������������������������������������������������������������������������� 134
Updating Recipe Servings and Cooking Time������������������������������������������������������������������������������������� 135
Adding and Removing Ingredients������������������������������������������������������������������������������������������������������ 138
Instructions����������������������������������������������������������������������������������������������������������������������������������������� 142
Citation����������������������������������������������������������������������������������������������������������������������������������������������� 144

Custom Components���������������������������������������������������������������������������������������������������� 144


The Input List View Model������������������������������������������������������������������������������������������������������������������ 145
The Input List Template���������������������������������������������������������������������������������������������������������������������� 146
Registering the Input List Tag������������������������������������������������������������������������������������������������������������� 148

Subscribables: Cheap Messaging�������������������������������������������������������������������������������� 150


Summary���������������������������������������������������������������������������������������������������������������������� 152
Related Resources������������������������������������������������������������������������������������������������������� 153

xi

www.it-ebooks.info
■ Contents


■Chapter 8: AngularJS���������������������������������������������������������������������������������������� 155
A Declarative Approach to Building Web Applications�������������������������������������������������� 155
The Imperative Approach�������������������������������������������������������������������������������������������������������������������� 155
The Declarative Approach������������������������������������������������������������������������������������������������������������������� 157

Modules: A Foundation for Building Loosely Coupled Applications������������������������������ 158


Specifying a Bootstrap Module����������������������������������������������������������������������������������������������������������� 159

Directives: An Abstraction Layer for the DOM��������������������������������������������������������������� 160


Taking Control�������������������������������������������������������������������������������������������������������������� 163
Scopes and Prototypal Inheritance����������������������������������������������������������������������������������������������������� 163
Manipulating Scope with Controllers������������������������������������������������������������������������������������������������� 165

Loose Coupling Through Services and Dependency Injection�������������������������������������� 168


Dependency Injection������������������������������������������������������������������������������������������������������������������������� 168
Thin Controllers and Fat Services������������������������������������������������������������������������������������������������������� 169

Creating Routes������������������������������������������������������������������������������������������������������������ 173


Route Parameters������������������������������������������������������������������������������������������������������������������������������� 175
Route Resolutions������������������������������������������������������������������������������������������������������������������������������� 176

Creating Complex Forms���������������������������������������������������������������������������������������������� 178


Validation�������������������������������������������������������������������������������������������������������������������������������������������� 178
Conditional Logic�������������������������������������������������������������������������������������������������������������������������������� 183
Repeatable Sections��������������������������������������������������������������������������������������������������������������������������� 185
Summary���������������������������������������������������������������������������������������������������������������������� 188
Related Resources������������������������������������������������������������������������������������������������������� 189

■Chapter 9: Kraken���������������������������������������������������������������������������������������������� 191
Environment-Aware Configuration������������������������������������������������������������������������������� 192
Shortstop Handlers����������������������������������������������������������������������������������������������������������������������������� 196

Configuration-Based Middleware Registration������������������������������������������������������������ 200


Event Notifications������������������������������������������������������������������������������������������������������������������������������ 203

xii

www.it-ebooks.info
■ Contents

Structured Route Registration�������������������������������������������������������������������������������������� 203


Index Configuration���������������������������������������������������������������������������������������������������������������������������� 204
Directory Configuration����������������������������������������������������������������������������������������������������������������������� 205
Routes Configuration�������������������������������������������������������������������������������������������������������������������������� 207

Dust Templates������������������������������������������������������������������������������������������������������������� 208


Context and References��������������������������������������������������������������������������������������������������������������������� 209
Sections���������������������������������������������������������������������������������������������������������������������������������������������� 212
Iteration���������������������������������������������������������������������������������������������������������������������������������������������� 212
Conditionality�������������������������������������������������������������������������������������������������������������������������������������� 213
Partials����������������������������������������������������������������������������������������������������������������������������������������������� 214
Blocks������������������������������������������������������������������������������������������������������������������������������������������������� 215
Filters�������������������������������������������������������������������������������������������������������������������������������������������������� 216
Context Helpers���������������������������������������������������������������������������������������������������������������������������������� 218
Dust Helpers��������������������������������������������������������������������������������������������������������������������������������������� 225
Let’s Get Kraken��������������������������������������������������������������������������������������������������������������������������������� 230

Summary���������������������������������������������������������������������������������������������������������������������� 250
Related Resources������������������������������������������������������������������������������������������������������� 250

■Chapter 10: Mach���������������������������������������������������������������������������������������������� 251
Chapter Examples�������������������������������������������������������������������������������������������������������� 251
Installation�������������������������������������������������������������������������������������������������������������������� 252
Mach, the Web Server�������������������������������������������������������������������������������������������������� 252
HTTP Routes��������������������������������������������������������������������������������������������������������������������������������������� 254
Making Connections��������������������������������������������������������������������������������������������������������������������������� 260
Common Middleware�������������������������������������������������������������������������������������������������������������������������� 262
These Are Not the Routes You’re Looking for������������������������������������������������������������������������������������� 280
The Hosts with the Most��������������������������������������������������������������������������������������������������������������������� 282
Custom Middleware���������������������������������������������������������������������������������������������������������������������������� 287

Mach, the HTTP Client�������������������������������������������������������������������������������������������������� 289


Mach, the HTTP Proxy�������������������������������������������������������������������������������������������������� 291
Summary���������������������������������������������������������������������������������������������������������������������� 295

xiii

www.it-ebooks.info
■ Contents


■Chapter 11: Mongoose��������������������������������������������������������������������������������������� 297
Basic MongoDB Concepts�������������������������������������������������������������������������������������������� 297
A Simple Mongoose Example��������������������������������������������������������������������������������������� 300
Creating a Mongoose Schema for JSON Data������������������������������������������������������������������������������������ 301
Importing Data with Mongoose���������������������������������������������������������������������������������������������������������� 302
Querying Data with Mongoose����������������������������������������������������������������������������������������������������������� 305

Working with Schemas������������������������������������������������������������������������������������������������ 307


Data Types������������������������������������������������������������������������������������������������������������������������������������������ 307
Nested Schemas��������������������������������������������������������������������������������������������������������������������������������� 308
Default Property Values���������������������������������������������������������������������������������������������������������������������� 309
Required Properties���������������������������������������������������������������������������������������������������������������������������� 310
Secondary Indexes����������������������������������������������������������������������������������������������������������������������������� 310
Schema Validation������������������������������������������������������������������������������������������������������������������������������ 311
Schema References���������������������������������������������������������������������������������������������������������������������������� 314
Schema Middleware��������������������������������������������������������������������������������������������������������������������������� 318

Working with Models and Documents�������������������������������������������������������������������������� 321


Document Instance Methods�������������������������������������������������������������������������������������������������������������� 323
Document Virtuals������������������������������������������������������������������������������������������������������������������������������ 325
Static Model Methods������������������������������������������������������������������������������������������������������������������������� 327

Working with Queries��������������������������������������������������������������������������������������������������� 329


Model.find( )���������������������������������������������������������������������������������������������������������������������������������������� 329
Finding Documents with Query Operators������������������������������������������������������������������������������������������ 336
Summary���������������������������������������������������������������������������������������������������������������������� 343

■Chapter 12: Knex and Bookshelf����������������������������������������������������������������������� 345
Knex����������������������������������������������������������������������������������������������������������������������������� 346
Installing the Command-Line Utility��������������������������������������������������������������������������������������������������� 346
Adding Knex to Your Project��������������������������������������������������������������������������������������������������������������� 346
Configuring Knex�������������������������������������������������������������������������������������������������������������������������������� 347
The SQL Query Builder������������������������������������������������������������������������������������������������������������������������ 347
Migration Scripts�������������������������������������������������������������������������������������������������������������������������������� 355
Seed Scripts��������������������������������������������������������������������������������������������������������������������������������������� 360
xiv

www.it-ebooks.info
■ Contents

Bookshelf��������������������������������������������������������������������������������������������������������������������� 361
What Is an Object-Relational Mapper?����������������������������������������������������������������������������������������������� 361
Creating Your First Bookshelf Model��������������������������������������������������������������������������������������������������� 362
Relationships�������������������������������������������������������������������������������������������������������������������������������������� 370

Summary���������������������������������������������������������������������������������������������������������������������� 379
Related Resources������������������������������������������������������������������������������������������������������� 379

■Chapter 13: Faye������������������������������������������������������������������������������������������������ 381
HTTP, Bayeux, and WebSockets������������������������������������������������������������������������������������ 381
WebSockets���������������������������������������������������������������������������������������������������������������������������������������� 383
The Bayeux Protocol��������������������������������������������������������������������������������������������������������������������������� 384

Getting Started with Faye��������������������������������������������������������������������������������������������� 385


PubSub Messaging������������������������������������������������������������������������������������������������������� 387
Wildcard Channels������������������������������������������������������������������������������������������������������������������������������ 388

Summary���������������������������������������������������������������������������������������������������������������������� 393
Related Resources������������������������������������������������������������������������������������������������������� 394

■Chapter 14: Q����������������������������������������������������������������������������������������������������� 395
Timing Is Everything����������������������������������������������������������������������������������������������������� 395
Promises vs. Callbacks������������������������������������������������������������������������������������������������ 399
The Promise of Q���������������������������������������������������������������������������������������������������������� 401
Deferreds and Promises��������������������������������������������������������������������������������������������������������������������� 401
Values and Errors������������������������������������������������������������������������������������������������������������������������������� 406
Reporting Progress����������������������������������������������������������������������������������������������������������������������������� 412
Everything Ends���������������������������������������������������������������������������������������������������������������������������������� 415

Flow Control with Q������������������������������������������������������������������������������������������������������ 418


Sequential Flow���������������������������������������������������������������������������������������������������������������������������������� 418
Parallel Flow��������������������������������������������������������������������������������������������������������������������������������������� 420
Pipeline Flow�������������������������������������������������������������������������������������������������������������������������������������� 421

Summary���������������������������������������������������������������������������������������������������������������������� 423
Related Resources������������������������������������������������������������������������������������������������������� 423

xv

www.it-ebooks.info
■ Contents


■Chapter 15: Async.js����������������������������������������������������������������������������������������� 425
Sequential Flow������������������������������������������������������������������������������������������������������������ 426
Parallel Flow����������������������������������������������������������������������������������������������������������������� 428
Pipeline Flow���������������������������������������������������������������������������������������������������������������� 430
Reusing a Pipeline������������������������������������������������������������������������������������������������������������������������������ 433

Loop Flow��������������������������������������������������������������������������������������������������������������������� 435


Looping While Some Condition Remains True������������������������������������������������������������������������������������ 435
Looping Until Some Condition Becomes False����������������������������������������������������������������������������������� 437
Retry Loops����������������������������������������������������������������������������������������������������������������������������������������� 439
Infinite Loops�������������������������������������������������������������������������������������������������������������������������������������� 441

Batch Flow������������������������������������������������������������������������������������������������������������������� 442


Asynchronous Queue�������������������������������������������������������������������������������������������������������������������������� 442

Summary���������������������������������������������������������������������������������������������������������������������� 446

■Chapter 16: Underscore and Lodash����������������������������������������������������������������� 447
Installation and Usage�������������������������������������������������������������������������������������������������� 449
Aggregation and Indexing�������������������������������������������������������������������������������������������� 449
countBy( )�������������������������������������������������������������������������������������������������������������������������������������������� 449
groupBy( )�������������������������������������������������������������������������������������������������������������������������������������������� 451
indexBy( )�������������������������������������������������������������������������������������������������������������������������������������������� 452

Being Choosy���������������������������������������������������������������������������������������������������������������� 453


Selecting Data from Collections��������������������������������������������������������������������������������������������������������� 453
Selecting Data from Objects��������������������������������������������������������������������������������������������������������������� 456

Chaining����������������������������������������������������������������������������������������������������������������������� 460
Function Timing������������������������������������������������������������������������������������������������������������ 463
defer( )������������������������������������������������������������������������������������������������������������������������������������������������ 463
debounce( )����������������������������������������������������������������������������������������������������������������������������������������� 465
throttle( )��������������������������������������������������������������������������������������������������������������������������������������������� 466

xvi

www.it-ebooks.info
■ Contents

Templates��������������������������������������������������������������������������������������������������������������������� 468
Loops and Other Arbitrary JavaScript in Templates���������������������������������������������������������������������������� 470
Living Without Gator Tags������������������������������������������������������������������������������������������������������������������� 472
Accessing the Data Object Within a Template������������������������������������������������������������������������������������ 473
Default Template Data������������������������������������������������������������������������������������������������������������������������ 474

Summary���������������������������������������������������������������������������������������������������������������������� 475
Related Resources������������������������������������������������������������������������������������������������������� 476

Index��������������������������������������������������������������������������������������������������������������������� 477

xvii

www.it-ebooks.info
About the Authors

Tim Ambler is a software engineer from Nashville, Tennessee. His passion


for programming follows in the footsteps of his father, who introduced him
to computers at a young age with a Commodore 64. Tim is the author of
several popular open source projects, one of which (whenLive) has been
featured by GitHub’s staff. An occasional conference speaker and frequent
writer, Tim has been referenced multiple times in online publications such
as JavaScript Weekly and Node Weekly. He currently lives in the 12 South
area with his wife, Laura, and two cats. You can follow him on Twitter at
@tkambler.

Nicholas Cloud is a software developer who lives in the very humid city of
St. Louis. For over a decade he has forged his skills into a successful career.
He has developed web applications, web services, and desktop software on
diverse platforms with JavaScript, C#, and PHP. A strong proponent of open
source software, Nicholas contributes to userland projects and has written
several of his own open source libraries libraries. He speaks at a variety of
user groups and conferences and writes books, technical articles, and blog
posts in his spare time. He opines on Twitter at @nicholascloud.

xix

www.it-ebooks.info
About the Technical Reviewer

Robin Hawkes lives to learn and thrives on combining design and


code to solve problems. He’s the author of Foundation HTML5 Canvas
(Apress, 2011), which is all about making games with JavaScript. He’s
also the one-man band behind ViziCities, a WebGL-powered 3D city
visualization platform. In a previous life Robin worked in worldwide
developer relations at both Mozilla and Pusher.

xxi

www.it-ebooks.info
Acknowledgments

This book would not have been possible without the encouragement and support of a number of people:
Nicholas Cloud, my friend and co-author, without whom this book would be much more limited
in scope and depth. His knowledge, experience, and steadfast dedication to this project have been
immeasurably helpful. Thank you.
Louise Corrigan, Kevin Walter, Christine Ricketts, Melissa Maldonado, and the rest of the staff at Apress
who supported us throughout the course of this project. I am grateful for the invitation that was extended to
embark upon this journey and for the ongoing support that you have provided.
Robin Hawkes, our technical reviewer. The examples and source code included with this book have
greatly benefited from his keen insight and sharp eye.
James Coglan, the creator of Faye. Thank you for taking the time to share your technical expertise
and feedback.
My friends and colleagues Greg Jones, Jeff Crump, Seth Steele, Jon Zumbrun, and Brian Hiatt. I am
grateful for your feedback and encouragement.
—Tim
Acknowledgements are slippery things. I have so many debts, and so little space to repay.
First, the debt to my co-author Tim who reached out and invited me on this journey. We’ve never met
in person but worked remotely as co-workers for about half a year—enough time for each of us to leave an
impression on each other across the miles. For his trust, encouragement, and constant effort I am grateful.
Second, my debt to the staff at Apress who guided us through the publishing process: Kevin, Louise,
Christine, and Melissa. Their patience and careful guidance spared you, the reader, from no small amount of
cringes, and kept me on my toes during the entire writing process. They are all sharp professionals with whom
I hope to work again some day.
Third, I am indebted to Robin for his excellent technical reviews; for reading and executing more code
samples than a developer should ever be tasked with groking.
Finally, I cannot repay the subject-matter expertise I gleaned from Michael Jackson (@mjackson) while
researching Mach, and Ryan Niemeyer (@RPNiemeyer) while researching Knockout—I can only pay it forward
to you, the reader.
—Nicholas

xxiii

www.it-ebooks.info
Introduction

They tell me we’re living in an information age, but none of it seems to be the information
I need or brings me closer to what I want to know. In fact (I’m becoming more and more
convinced) all this electronic wizardry only adds to our confusion, delivering inside scoops
and verdicts about events that have hardly begun: a torrent of chatter moving at the speed
of light, making it nearly impossible for any of the important things to be heard.
—Matthew Flaming, The Kingdom of Ohio

The notion that “technology moves quickly” is a well-worn aphorism, and with good reason: technology
does move quickly. But at this moment, JavaScript in particular is moving very quickly indeed—much like
that “torrent of chatter moving at the speed of light” that Matthew Flaming refers to in The Kingdom of Ohio.
The language is in the midst of what many have called a renaissance, brought about by the rapidly increasing
sophistication of browser-based applications and the rising popularity of JavaScript on the server, thanks to
Node.js.
An almost feverish pace of innovation is occurring within the JavaScript community that, while
endlessly fascinating to follow, also presents some unique challenges of its own. JavaScript’s ecosystem of
libraries, frameworks, and utilities has grown dramatically. Where once a small number of solutions for any
given problem existed, many can now be found… and the options continue to grow by the day. As a result,
developers find themselves faced with the increasingly difficult task of choosing the appropriate tools from
among many seemingly good options.
If you’ve ever found yourself wondering why JavaScript seems to be attracting so much attention lately,
as we have, it’s worth stopping for a moment to consider the fact that JavaScript, a language that was created
by one person in ten days, now serves as the foundation upon which much of the Web as we know it sits.
A language that was originally created to solve relatively simple problems is now being applied in new
and innovative ways that were not originally foreseen. What’s more, JavaScript is a beautifully expressive
language, but it’s not without its share of rough edges and potential pitfalls. While flexible, efficient, and
ubiquitous, JavaScript concepts such as the event loop and prototypal inheritance can prove particularly
challenging for those coming to the language for the first time.
For these and many other reasons, the development community at large is still coming to terms with
how best to apply the unique features that JavaScript brings to the table. We’ve no doubt only scratched
the surface of what the language and the community behind it are capable of. For those with an insatiable
appetite for knowledge and a desire to create, now is the perfect time to be a JavaScript developer.
We have written Pro JavaScript Frameworks for Modern Web Dev to serve as your guide to a wide
range of popular JavaScript tools that solve difficult problems at both ends of the development stack: in
the browser and on the server. The tutorials and downloadable code examples contained within this book
illustrate the usage of tools that manage dependencies, structure code in a modular fashion, automate
repetitive build tasks, create specialized servers, structure client side applications, facilitate horizontal
scaling, perform event logging, and interacting with disparate data stores.
The libraries and frameworks covered include Bower, Grunt, Yeoman, PM2, RequireJS, Browserify,
Knockout, AngularJS, Kraken, Mach, Mongoose, Knex, Bookshelf, Faye, Q, Async.js, Underscore, and Lodash.

xxv

www.it-ebooks.info
■ Introduction

In writing Pro JavaScript Frameworks for Modern Web Dev, our goal was to create a filter for the
“torrent of chatter” that often seems to surround JavaScript, and in so doing, to allow what we believe are
some important things to be heard. We hope the information contained within these pages proves as useful
to you as it has to us.

Who This Book Is For


This book is intended for web developers who are already confident with JavaScript, but also frustrated with
the sheer number of solutions that exist for seemingly every problem. This book helps lift the fog, providing
the reader with an in-depth guide to specific libraries and frameworks that well-known organizations are
using right now with great success. Topics pertaining to both client-side and server-side development
are covered. As a result, readers will gain the most benefit from this book if they already have at least an
intermediate familiarity with both the web browser Document Object Model (DOM), common client-side
libraries like jQuery, and Node.js.

How This Book Is Structured


This book covers a wide selection of JavaScript tools that are applicable throughout the entire development
process, from a project’s first commit to its first release and beyond. To that end, the chapters have been
grouped into the following parts.

Part 1: Development Tools


Bower
Dependency management is hardly a new idea - well-known examples include Node’s npm, Python’s pip,
and PHP’s composer. A practice that has only recently begun to see widespread adoption, however, is the
application of this concept to the management of front-end web assets - the JavaScript libraries, stylesheets,
fonts, icons, and images that serve as the building blocks of modern web applications. In this chapter, we’ll
discover several ways in which Bower - a popular tool within this field - can improve your development
process by providing you with a mechanism for organizing these dependencies within your application.

Grunt
Larry Wall, the creator of Perl, describes the three virtues of a great programmer as: laziness, impatience,
and hubris. In this chapter, we’ll focus on a tool that will help you strengthen the virtue of laziness - Grunt.
This popular task runner provides developers with a framework for creating command-line utilities
that automative repetitive build tasks such as running tests, concatenating files, compiling SASS / LESS
stylesheets, checking for JavaScript errors, and more. After reading this chapter, you’ll know how to use several
popular Grunt plugins, as well as how to go about creating and sharing your own plugins with the community.

xxvi

www.it-ebooks.info
■ Introduction

Yeoman
Yeoman provides JavaScript developers with a mechanism for creating reusable templates (“generators”)
that describe the overall structure of a project (initially required dependencies, Grunt tasks, etc…) in a way
that can be easily re-used over and over. Broad community support also allows you to take advantage of a
wide variety of pre-existing templates. In this chapter, we’ll walk through the process of installing Yeoman
and using several popular pre-existing generators. Finally, we’ll take a look at how we can create and share
our own templates with the community.

PM2
In this chapter, we will close out our discussion of development tools by taking a look at PM2, a command-line
utility that simplifies many of the tasks associated with running Node applications, monitoring their status,
and efficiently scaling them to meet increasing demand.

Part 2: Module Loaders


RequireJS and Browserify
JavaScript’s lacks a native method for loading external dependencies in the browser—a frustrating oversight
for developers. Fortunately, the community has stepped in to fill this gap with two very different and
competing standards: the Asynchronous Module Definition (AMD) API and CommonJS. We’ll dive into the
details of both and take a look at widely-used implementations of each: RequireJS and Browserify. Each
have their merits, which we’ll discuss in detail, but both can have a profoundly positive impact on the way in
which you go about structuring your applications.

Part 3: Client-Side Frameworks


Knockout and AngularJS
In recent years, web developers have witnessed a sharp rise in popularity of so-called “single-page apps.”
Such applications exhibit behavior once available only on the desktop, but at the expense of increased code
complexity within the browser. In this section, we’ll dive into two widely-used front-end frameworks that
help minimize that complexity by providing proven patterns for solving frequently-encountered problems:
Knockout and AngularJS. Knockout focuses on the relationship between view and data, but otherwise leaves
the application architecture and plumbing to the developer’s discretion. AngularJS takes a more prescriptive
approach, covering the view, application routing, data transfer, and module design.

Part 4: Server-Side Frameworks


Kraken and Mach
Client-side applications aren’t very useful without a server with which to interact. In this section, we’ll take
a look at two popular frameworks that support developers in the creation of back-end applications: Kraken
and Mach.
Mach is more than just a simple web server: it is HTTP for the web. Mach can both serve and retrieve
content via an intuitive, extensible HTTP stack. The Mach interface remains the same whether servicing
web page requests in a Node.js application, fetching JSON data with a Mach AJAX request in the browser,
or rewriting and proxying requests to another web stack entirely. In many ways Mach is the Swiss army knife
of HTTP.

xxvii

www.it-ebooks.info
■ Introduction

Part 5: Managing Database Interaction


Mongoose, Knex, and Bookshelf
At the core of every application lies the most important component of any development stack - the data
that our users seek. In this section, we’ll become familiar with two libraries that help simplify some of the
complexity that’s often experienced when interacting with popular storage platforms such as MongoDB,
MySQL, PostgreSQL, and SQLite. After reading this section, you’ll be comfortable defining schemas,
associations, lifecycle “hooks”, and more.

Part 6: Communication
Faye
In this section, you’ll be introduced to Faye, a Node.js library that provides developers with a robust and
easy-to-use platform for building products that rely on real-time communication between servers and all
major browsers.Much of Faye’s popularity stems from the project’s goal of working everywhere the Web
works. Faye accomplishes this by providing seamless fallback support for a number of communication
protocols.

Part 7: Managing Control Flow


Q and Async.js
The asynchronous nature of JavaScript provides developers with a significant degree of flexibility - as
opposed to forcing developers to execute their code in a linear fashion, JavaScript allows developers to
orchestrate multiple actions simultaneously. Unfortunately, along with this flexibility comes a significant
degree of additional complexity - what many developers refer to as “callback hell” or the “pyramid of
doom.” In this section, we’ll examine two popular libraries that will aid you in taming the complexities of
asynchronous control flow: Q and Async.js.

Part 8: Further Useful Libraries


A number of wonderfully useful libraries exist that this book would be remiss not to cover, but for which
additional parts are not necessarily warranted. This part will cover such libraries.

Underscore and Lo-Dash


Underscore (and its successor, Lo-Dash) is an incredibly useful collection of functions that simplifies many
frequently used patterns that can be tedious to implement otherwise. This brief chapter will bring these
libraries to your attention, along with some of the more popular extensions that can also be included to
enhance their usefulness even further. Examples are included that that highlight some of the most frequently
used portions of these libraries.

xxviii

www.it-ebooks.info
■ Introduction

Downloading the Code


Each chapter in this book contains many examples, the source code for which may be downloaded from
http://www.apress.com/9781484206638 in zipped form.
Subdirectories within each chapter’s zip file contain source code (often executable) that corresponds
to specific example listings in each chapter. The first line in each chapter listing will be a source code
comment identifying the specific file path where the source code lives. If you were to encounter
Listing 0-1 in Chapter 10 (covering Mach), for example, the actual source code file would be located in
mach/example-000/no-such-file.js, relative to where the mach.zip file was extracted.

Listing 0-1. Not a Real Example


// example-000/no-such-file.js
console.log('this is not a real example');

Most examples are run with the Node.js runtime, which may be obtained from https://nodejs.org.
Chapters with additional prerequisites will explain the necessary procedures for downloading and
installing the examples. (For example, MongoDB is necessary to run examples in Chapter 11, which covers
Mongoose.)
Any additional steps necessary for running code examples (e.g., executing curl requests) or interacting
with a running example (e.g., opening a web browser and navigating to a specific URL) are explained
alongside each listing.

xxix

www.it-ebooks.info
Chapter 1

Bower

Great things are done by a series of small things brought together.


—Vincent Van Gogh

The concept of package management, also known as dependency management, is not new. Utilities within
this category provide developers with a mechanism for managing the various third-party libraries that a
project relies on. Widely used examples include
• npm: The package manager for Node.js
• Composer: A tool for dependency management in PHP
• pip: The PyPA recommended tool for installing Python packages
• NuGet: The package manager for the Microsoft development platform including .NET
While package management is hardly a new idea, a practice that has only recently begun to see
widespread adoption is the application of this concept to the management of front-end web assets—the
JavaScript libraries, stylesheets, fonts, icons, and images that serve as the building blocks of modern web
applications. The need for such structure has become evident as the foundations on which modern web
applications are built have grown in complexity. Web applications that once relied on a small selection of
broadly defined, “one size fits all” third-party libraries (e.g., jQuery) now find themselves using the work
of many more smaller libraries, each with a tightly defined purpose. Benefits of this approach include
smaller modules that are easier to test, as well as an enhanced degree of flexibility on the part of the
parent application, which can more easily extend third-party libraries or replace them altogether when
necessary.
This chapter is designed to get you up and running quickly with Bower, the front-end package manager
whose roots lie in open source initiatives at Twitter. Topics covered include
• Installing and configuring Bower
• Adding Bower to a project
• Finding, adding, and removing packages
• Semantic Versioning
• Managing the dependency chain
• Creating Bower packages

www.it-ebooks.info
Chapter 1 ■ Bower

Getting Started
All interaction with Bower occurs through a command-line utility that can be installed via npm. If you do not
already have Bower installed, you should install it before you continue, as shown in Listing 1-1.

Listing 1-1. Installing the bower Command-Line Utility via npm


$ npm install -g bower
$ bower --version
1.3.12

■■Note Node’s package manager (npm) allows users to install packages in one of two contexts: locally
or globally. In this example, bower is installed within the global context, which is typically reserved for
command-line utilities.

Configuring Bower
Bower is configured on a per-project basis through a single (optional) JSON file that exists in your project’s
root folder, .bowerrc. For the purposes of this introduction, we’ll only look at the most frequently changed
setting within this file (see Listing 1-2).

Listing 1-2. The .bowerrc File from This Chapter’s Sample Project
// example-bootstrap/.bowerrc

{
"directory": "./public/bower_components"
}

By default, Bower will store your project’s dependencies in the bower_components folder. You will likely
want to change this location, and the directory setting allows you to do so.

The Manifest
Bower provides developers with a single point of entry from which third-party libraries can be found, added,
upgraded, and removed. As these actions occur, Bower updates a JSON file referred to as the “manifest”
with an up-to-date list of the project’s dependencies. The Bower manifest for this chapter’s sample project is
shown in Listing 1-3. In this example, Bower is aware of a single dependency, the Bootstrap CSS framework.

Listing 1-3. Bower Manifest for This Chapter’s Sample Project


// example-bootstrap/bower.json

{
"name": "example-bootstrap",
"version": "1.0.0",
"homepage": "https://github.com/username/project",

www.it-ebooks.info
Chapter 1 ■ Bower

"authors": [
"John Doe <[email protected]>"
],
"dependencies": {
"bootstrap": "3.2.0"
}
}

If we were to accidentally delete all of our project’s dependencies by removing the public/bower_
components folder, we could easily restore our project to its previous state by issuing a single command, as
shown next. Doing so would cause Bower to compare its manifest with our project’s current file structure,
determine what dependencies are missing, and restore them.

$ bower install

As a result of this behavior, we have the option of ignoring our project’s /public/bower_components
folder within version control. By committing only Bower’s manifest, and not the dependencies themselves,
our project’s source code can be kept in a cleaner state, containing only files that pertain directly to our
own work.

■■Note Opinions differ as to whether or not keeping your project’s dependencies out of version control is
a good idea. On the one hand, doing so results in a cleaner repository. On the other hand, this also opens the
door to potential problems should you (or the Bower registry, or GitHub, etc.) encounter connection issues.
The general consensus seems to be that if you are working on a “deployable” project (i.e., an application,
not a module), committing your dependencies is the preferred approach. Otherwise, keeping your project’s
dependencies out of version control is probably a good idea.

Creating a New Manifest


When you begin to use Bower within a project for the first time, it’s typically best to allow Bower to create a
new manifest for you, as shown next. Afterward, you can modify it further if necessary.

$ bower init

Finding, Adding, and Removing Bower Packages


Bower’s command-line utility provides a number of useful commands for locating, installing, and removing
packages. Let’s take a look at how these commands can help simplify the process of managing a project’s
external dependencies.

Finding Packages
One of the primary ways in which Bower can improve your development workflow is by providing you with a
centralized registry from which third-party libraries can be found. To search the Bower registry, simply pass
the search argument to Bower, followed by a keyword to search for, as shown in Listing 1-4. In this example,
only a short excerpt from the returned list of search results is shown.

www.it-ebooks.info
Chapter 1 ■ Bower

Listing 1-4. Searching Bower for jQuery


$ bower search jquery

Search results:

jquery git://github.com/jquery/jquery.git
jquery-ui git://github.com/components/jqueryui
jquery.cookie git://github.com/carhartl/jquery-cookie.git
jquery-placeholder git://github.com/mathiasbynens/jquery-placeholder.git

Adding Packages
Each search result includes the name under which the package was registered, along with the URL of the
GitHub repository at which it can be accessed directly. Once we have located the desired package, we can
add it to our project as shown in Listing 1-5.

Listing 1-5. Adding jQuery to Our Project


$ bower install jquery --save
bower jquery#* cached git://github.com/jquery/jquery.git#2.1.3
bower jquery#* validate 2.1.3 against git://github.com/jquery/jquery.git#*
bower jquery#>= 1.9.1 cached git://github.com/jquery/jquery.git#2.1.3
bower jquery#>= 1.9.1 validate 2.1.3 against git://github.com/jquery/jquery.git#>= 1.9.1
bower jquery#>= 1.9.1 cached git://github.com/jquery/jquery.git#2.1.3
bower jquery#>= 1.9.1 validate 2.1.3 against git://github.com/jquery/jquery.git#>= 1.9.1
bower jquery#>= 1.9.1 install jquery#2.1.3

jquery#2.1.3 public/bower_components/jquery

■■Note Bower does not host any of the files associated with the packages contained within its registry; it
defers to GitHub for that responsibility. While it is possible to host packages at any URL, the majority of public
packages are found on GitHub.

Take note of the fact that in Listing 1-5, we pass the --save option to Bower’s install command. By
default, the install command will add the requested package to a project without updating its manifest.
By passing the --save option, we instruct Bower to permanently store this package within its list of
dependencies.
Listing 1-6 shows the HTML from this chapter’s sample project. After adding jQuery to our project via
Bower, we can load it via a script tag as we would any other library.

www.it-ebooks.info
Chapter 1 ■ Bower

Listing 1-6. HTML from Our Sample Project That References the jQuery Package Just Added
// example-jquery/public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bower Example</title>
</head>
<body>
<div id="container"></div>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#container').html('<p>Hello, world!</p>');
});
</script>
</body>
</html>

Development Dependencies
By default, any packages that Bower installs are considered to be “production” dependencies, but this
behavior can be overridden by passing the --save-dev option. Doing so will flag any installed packages as
“development” dependencies. Such packages are intended for development purposes only, not for the final
users of a project.
Once we are ready to deploy our application to a production environment, we can instruct Bower to
install only the production dependencies, as shown next, resulting in a leaner build that does not contain
extraneous files of no interest to the end user.

$ bower install --production

Removing Packages
The process of removing Bower packages is straightforward. As in previous examples, we pass the --save
argument to update Bower’s manifest to reflect this change:

$ bower uninstall jquery --save

www.it-ebooks.info
Chapter 1 ■ Bower

Semantic Versioning
If you were to install jQuery (as shown in Listing 1-5) and then look at the contents of your project’s Bower
manifest, you would see something that resembles Listing 1-7.

Listing 1-7. Semantic Version (Semver) Number


"dependencies": {
"jquery": "~2.1.3"
}

The version number 2.1.3 that we see in Listing 1-7 (ignore the ~ character for a moment) is what is
known as a semantic version number (semver for short). Semantic versioning is a standard that describes
a common format that developers can use to assign version numbers to their projects. The format is
illustrated here:

Version X.Y.Z (Major.Minor.Patch)

The semantic versioning format dictates that developers create clearly defined (either by
documentation or by clear, self-documenting code) APIs that provide users with a single point of entry into a
library. New projects that are just getting off the ground typically begin at version 0.0.0 and work their way up
incrementally as new releases are created. A project with a version number below 1.0.0 is considered to be
under heavy development and, as such, is allowed to make sweeping changes to its API without altering its
major version number. A project with a version number at or above 1.0.0, however, is guided by the following
set of rules that determines how version numbers should be changed:
• A project’s major version number should change when updates occur that result in
breaking changes with how users have interacted with a project’s API in previous
versions.
• A project’s minor version number should change when new features are added to a
project in a way that is backward-compatible (i.e., the existing API is not broken).
• A project’s patch version number should change when backward-compatible bug
fixes are introduced.
These rules provide developers with insight into the extent of changes that have occurred between any
two versions. Such insight will prove useful as our Bower manifest grows and we begin adding more and
more dependencies to our project.

■■Note The ~ character shown in Listing 1-7 tells Bower that whenever the install command is run, it is
allowed to automatically install future versions of jQuery that are “relatively close to” version 2.1.3. If the use of
the phrases “relatively close to” and “automatically install” within the same sentence makes your skin crawl,
you’re not alone. Best practices suggest that you avoid the “~X.Y.Z” format when referencing dependencies
with Bower. Instead, you are better off specifying the exact version of the dependency that you wish to include
within your project. As future updates are released, you can then manually review them and make your own
decisions regarding if and when to update. Subsequent examples within this chapter will follow this advice.

www.it-ebooks.info
Chapter 1 ■ Bower

Managing the Dependency Chain


One of the primary benefits that developers gain as a result of using Bower is the ease with which updates to
a project’s entire dependency chain can be monitored and integrated. To illustrate this point, let’s take a look
at the list of dependencies contained within this chapter’s sample project (see Listing 1-8).

Listing 1-8. Installing and Listing the Various Bower Packages Required by Our Sample Project
$ bower install
bower bootstrap#3.2.0 cached git://github.com/twbs/bootstrap.git#3.2.0
bower bootstrap#3.2.0 validate 3.2.0 against git://github.com/twbs/bootstrap.git#3.2.0
bower jquery#>= 1.9.0 cached git://github.com/jquery/jquery.git#2.1.3
bower jquery#>= 1.9.0 validate 2.1.3 against git://github.com/jquery/jquery.git#>= 1.9.0
bower bootstrap#3.2.0 install bootstrap#3.2.0
bower jquery#>= 1.9.0 install jquery#2.1.3

bootstrap#3.2.0 public/bower_components/bootstrap
└── jquery#2.1.3

jquery#2.1.3 public/bower_components/jquery

$ bower list
bower check-new Checking for new versions of the project dependencies..
example-bootstrap#1.0.0 /opt/example-bootstrap
└─┬ bootstrap#3.2.0 (latest is 3.3.2)
└── jquery#2.1.3

Thanks to Bower, we now have a simple graph that describes the external dependencies that our project
relies on, as well as the relationships between them. We can see that we have a Bootstrap dependency,
which in turn has its own dependency on jQuery. Bower also prints the specific version of each component
that is currently installed.

■■Note Many third-party libraries are not entirely self-contained—they have dependencies of their own.
Bootstrap (with its reliance on jQuery) is one such example. When adding such a package, Bower is smart
enough to recognize these additional dependencies and will proactively add them to your project if they don’t
already exist. It is important to note, however, that unlike more sophisticated package managers (e.g., npm),
Bower stores all of its packages within a flat folder structure, which means you will occasionally run into version
conflicts, if you’re not careful.

In Listing 1-8, Bower has informed us that a version of Bootstrap (3.3.2) newer than the version currently
relied upon by our project (3.2.0) is available. We can update this dependency by modifying our project’s
manifest to refer to this newer version and rerunning the install command, as shown in Listing 1-9.

www.it-ebooks.info
Chapter 1 ■ Bower

Listing 1-9. Installing Bower Packages After Having Updated the Version of jQuery Our Project Relies On
$ bower install
bower bootstrap#3.3.2 cached git://github.com/twbs/bootstrap.git#3.3.2
bower bootstrap#3.3.2 validate 3.3.2 against git://github.com/twbs/bootstrap.git#3.3.2
bower bootstrap#3.3.2 install bootstrap#3.3.2

bootstrap#3.3.2 public/bower_components/bootstrap
└── jquery#2.1.3

Creating Bower Packages


Until now, our focus has been on integrating Bower into our own projects. We’ve initialized Bower within
our project and discovered how we can go about finding, adding, and removing packages. At a certain point,
however, you’ll hopefully find yourself wanting to share your own packages with others. To do so, you’ll need
to ensure that you follow a few simple guidelines, starting with choosing a valid name.

Choose a Valid Name


You’ll need to settle on a name for your package that is unique throughout Bower’s public registry. Use
Bower’s search command to find out if your desired name is available. Additional requirements include
• The name should be in “slug” format; for example, my-unique-project.
• The name should be all lowercase.
• Only alphanumeric characters, dots, and dashes are allowed.
• The name should begin and end with an alphabetic character.
• Consecutive dots and dashes are not allowed.
• After settling on a name, update the contents of your project’s bower.json file
accordingly.

Use Semver Git Tags


Earlier in the chapter, we took a look at the concept of semantic versioning, a common standard for
assigning meaningful version numbers to projects. You’ll want to ensure that you follow this standard, as this
will allow the consumers of your package to track and integrate your future changes.
If the package you want to share is just getting started, an appropriate version number would be
0.0.0. As you commit future changes and create new releases, you can increment this value as appropriate,
depending on the extent of your updates. When you determine that your project has reached its first “stable”
milestone, update your version number to 1.0.0 to reflect that status.
Every version number of your project should have a corresponding tag on GitHub. It is this relationship
between GitHub tags and the versions of your package that allows consumers to reference specific versions
within their projects.
Assuming you’ve already committed your code to GitHub, see Listing 1-10 for an example of how you
might go about creating your first tag.

www.it-ebooks.info
Chapter 1 ■ Bower

Listing 1-10. Creating Your First Semver Git Tag


$ git tag -a 0.0.1 -m "First release."
$ git push origin 0.0.1

Publish Your Package to the Registry


Now that we’ve chosen an appropriate name for our package and assigned a version number (along with a
corresponding tag on GitHub), it’s time to publish our package to the public Bower registry:

$ bower register my-package-name https://github.com/username/my-package-name.git

■■Note Bear in mind that Bower is intended to serve as a centralized registry for libraries and components
that other developers can use within their own projects. It is not intended to serve as a distribution mechanism
for entire applications.

Summary
Bower is a simple command-line utility that eases some of the tedious tasks associated with managing
front-end assets. Unlike well-known package managers from other platforms (e.g., Node’s npm), Bower
was not designed to handle the specific needs of any one platform or language; instead, it favors a rather
generic approach to the concept of package management. The developers who created Bower intentionally
set out to create a very simple tool for managing a wide variety of front-end assets—not just code, but also
stylesheets, fonts, images, and other, unforeseen future dependencies.
Developers working on trivial web applications with few external dependencies may find little value
in the benefits that Bower brings to the table. That said, trivial web applications have a tendency to quickly
evolve into complex web applications, and as that process occurs, developers often come to appreciate
Bower’s benefits.
Regardless of how complex (or simple) you consider your project to be, we would encourage you to
consider integrating Bower into your workflow sooner rather than later. As bitter experience has taught
us—the project itself. Err on the side of too little structure, and you risk creating an ever-increasing burden
of “technical debt” for which you must eventually pay a price. The process of striking a delicate balance
between these undesired alternatives is as much an art as it is a science. It is also a process that is never fully
learned, but must continuously be adapted as the tools of our trade change.

www.it-ebooks.info
Chapter 2

Grunt

I’m lazy. But it’s the lazy people who invented the wheel and the bicycle because they didn’t
like walking or carrying things.
—Lech Walesa, former president of Poland

In his book Programming Perl, Larry Wall (the well-known creator of the language) puts forth the idea that
all successful programmers share three important characteristics: laziness, impatience, and hubris. At first
glance, these traits all sound quite negative, but dig a little deeper, and you’ll find the hidden meaning in his
statement:
Laziness: Lazy programmers hate to repeat themselves. As a result, they tend to
put a lot of effort into creating useful tools that perform repetitive tasks for them.
They also tend to document those tools well, to spare themselves the trouble of
answering questions about them later.
Impatience: Impatient programmers have learned to expect much from their
tools. This expectation teaches them to create software that doesn’t just react to
the needs of its users, but that actually attempts to anticipate those needs.
Hubris: Good programmers take great pride in their work. It is this pride that
compels them to write software that others won’t want to criticize—the type of
work that we should all be striving for.
In this chapter, we’ll focus on the first of these three characteristics, laziness, along with Grunt, a
popular JavaScript “task runner” that supports developers in nurturing this trait by providing them with a
toolkit for automating the repetitive build tasks that often accompany software development, such as:
• Script and stylesheet compilation and minification
• Testing
• Linting
• Database migrations
• Deployments

11

www.it-ebooks.info
Chapter 2 ■ Grunt

In other words, Grunt helps developers who strive to work smarter, not harder. If that idea appeals to
you, read on. After you have finished this chapter, you will be well on your way toward mastering Grunt.
You’ll learn how to do the following in this chapter:
• Create configurable tasks that automate the repetitive aspects of software
development that accompany nearly every project
• Interact with the file system using simple yet powerful abstractions provided
by Grunt
• Publish Grunt plugins from which other developers can benefit and to which they
can contribute
• Take advantage of Grunt’s preexisting library of community-supported plugins, of
which over 4,400 examples exist at the time of writing

Installing Grunt
Before continuing, you should ensure that you have installed Grunt’s command-line utility. Available as an
npm package, the installation process is shown in Listing 2-1.

Listing 2-1. Installing the grunt Command-Line Utility via npm


$ npm install -g grunt-cli
$ grunt --version
grunt-cli v0.1.13

How Grunt Works


Grunt provides developers with a toolkit for creating command-line utilities that perform repetitive project
tasks. Examples of such tasks include the minification of JavaScript code and the compilation of Sass
stylesheets, but there’s no limit to how Grunt can be put to work. Grunt can be used to create simple tasks
that address the specific needs of a single project—tasks that you don’t intend to share or reuse—but Grunt’s
true power derives from its ability to package tasks as reusable plugins that can then be published, shared,
used, and improved upon by others. At the time of this writing, over 4,400 such plugins exist.
Four core components make Grunt tick, which we will now cover.

Gruntfile.js
At Grunt’s core lies the Gruntfile, a Node module saved as Gruntfile.js (see Listing 2-2) at the root of
your project. It’s within this file that we can load Grunt plugins, create our own custom tasks, and configure
them according to the needs of our project. Each time Grunt is run, its first order of business is to retrieve its
marching orders from this module.

12

www.it-ebooks.info
Chapter 2 ■ Grunt

Listing 2-2. Sample Gruntfile


// example-starter/Gruntfile.js

module.exports = function(grunt) {

/**
* Configure the various tasks and plugins that we'll be using
*/
grunt.initConfig({
/* Grunt's 'file' API provides developers with helpful abstractions for
interacting with the file system. We'll take a look at these in greater
detail later in the chapter. */
'pkg': grunt.file.readJSON('package.json'),
'uglify': {
'development': {
'files': {
'build/app.min.js': ['src/app.js', 'src/lib.js']
}
}
}
});

/**
* Grunt plugins exist as Node packages, published via npm. Here, we load the
* 'grunt-contrib-uglify' plugin, which provides a task for merging and minifying
* a project's source code in preparation for deployment.
*/
grunt.loadNpmTasks('grunt-contrib-uglify');

/**
* Here we create a Grunt task named 'default' that does nothing more than call
* the 'uglify' task. In other words, this task will serve as an alias to
* 'uglify'. Creating a task named 'default' tells Grunt what to do when it is
* run from the command line without any arguments. In this example, our 'default'
* task calls a single, separate task, but we could just as easily have called
* multiple tasks (to be run in sequence) by adding multiple entries to the array
* that is passed.
*/
grunt.registerTask('default', ['uglify']);

/**
* Here we create a custom task that prints a message to the console (followed by
* a line break) using one of Grunt's built-in methods for providing user feedback.
* We'll look at these in greater detail later in the chapter.
*/
grunt.registerTask('hello-world', function() {
grunt.log.writeln('Hello, world.');
});

};

13

www.it-ebooks.info
Chapter 2 ■ Grunt

Tasks
Tasks are the basic building blocks of Grunt and are nothing more than functions that are registered with
assigned names via Grunt’s registerTask() method. In Listing 2-2, a simple hello-world task is shown that
prints a message to the console. This task can be called from the command line as shown in Listing 2-3.

Listing 2-3. Running the hello-world Task Shown in Listing 2-2


$ grunt hello-world
Running "hello-world" task
Hello, world.

Done, without errors.

Multiple Grunt tasks can also be run in sequence with a single command, as shown in Listing 2-4.
Each task will be run in the order in which it was passed.

Listing 2-4. Running Multiple Grunt Tasks in Sequence


$ grunt hello-world uglify
Running "hello-world" task
Hello, world.

Running "uglify:development" (uglify) task


>> 1 file created.

Done, without errors.

The hello-world task that we’ve just seen serves as an example of a basic, stand-alone Grunt task. Such
tasks can be used to implement simple actions specific to the needs of a single project that you don’t intend
to re-use or share. Most of the time, however, you will find yourself interacting not with stand-alone tasks,
but instead with tasks that have been packaged as Grunt plugins and published to npm so that others can
reuse them and contribute to them.

Plugins
A Grunt plugin is a collection of configurable tasks (published as an npm package) that can be reused across
multiple projects. Thousands of such plugins exist. In Listing 2-2, Grunt’s loadNpmTasks() method is used to
load the grunt-contrib-uglify Node module, a Grunt plugin that merges a project’s JavaScript code into a
single, minified file that is suitable for deployment.

■■Note A list of all available Grunt plugins can be found at http://gruntjs.com/plugins. Plugins whose
names are prefixed with contrib- are officially maintained by the developers behind Grunt.

14

www.it-ebooks.info
Chapter 2 ■ Grunt

Configuration
Grunt is known for emphasizing “configuration over code”: the creation of tasks and plugins whose
functionality is tailored by configuration that is specified within each project. It is this separation of code
from configuration that allows developers to create plugins that are easily reusable by others. Later in the
chapter, we’ll take a look at the various ways in which Grunt plugins and tasks can be configured.

Adding Grunt to Your Project


Earlier in the chapter, we installed Grunt’s command-line utility by installing the grunt-cli npm package
as a global module. We should now have access to the grunt utility from the command line, but we still
need to add a local grunt dependency to each project we intend to use it with. The command to be called
from within the root folder of your project is shown next. This example assumes that npm has already been
initialized within the project and that a package.json file already exists.

$ npm install grunt --save-dev

Our project’s package.json file should now contain a grunt entry similar to that shown in Listing 2-5.

Listing 2-5. Our Project’s Updated package.json File


// example-tasks/package.json

{
"name": "example-tasks",
"version": "1.0.0",
"devDependencies": {
"grunt": "0.4.5"
}
}

The final step toward integrating Grunt with our project is the creation of a Gruntfile (see Listing 2-6),
which should be saved within the root folder of the project. Within our Gruntfile, a single method is called,
loadTasks(), which is discussed in the upcoming section.

Listing 2-6. Contents of Our Project’s Gruntfile


// example-tasks/Gruntfile.js

module.exports = function(grunt) {
grunt.loadTasks('tasks');
};

Maintaining a Sane Grunt Structure


We hope that by the time you have finished this chapter, you will have found Grunt to be a worthwhile tool
for automating many of the repetitive, tedious tasks that you encounter during the course of your daily
workflow. That said, we’d be lying if we told you that our initial reaction to Grunt was positive. In fact,
we were quite turned off by the tool at first. To help explain why, let’s take a look at the Gruntfile that is
prominently displayed within Grunt’s official documentation (see Listing 2-7).

15

www.it-ebooks.info
Chapter 2 ■ Grunt

Listing 2-7. Example Gruntfile Provided by Grunt’s Official Documentation


module.exports = function(grunt) {

grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';'
},
dist: {
src: ['src/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '/*! <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
},
qunit: {
files: ['test/**/*.html']
},
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
// options here to override JSHint defaults
globals: {
jQuery: true,
console: true,
module: true,
document: true
}
}
},
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint', 'qunit']
}
});

16

www.it-ebooks.info
Chapter 2 ■ Grunt

grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');

grunt.registerTask('test', ['jshint', 'qunit']);

grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);

};

The Gruntfile shown in Listing 2-7 is for a relatively simple project. We already find this example to be
slightly unwieldy, but within larger projects we have seen this file balloon to many times this size. The result
is an unreadable and difficult-to-maintain mess. Experienced developers would never write their code in a
way that combines functionality from across unrelated areas into a single, monolithic file, so why should we
approach our task runner any differently?
The secret to maintaining a sane Grunt structure lies with Grunt’s loadTasks() function, as shown in
Listing 2-6. In this example, the tasks argument refers to a tasks folder relative to our project’s Gruntfile.
Once this method is called, Grunt will load and execute each Node module it finds within this folder,
passing along a reference to the grunt object each time. This behavior provides us with the opportunity to
organize our project’s Grunt configuration as a series of separate modules, each responsible for loading and
configuring a single task or plugin. An example of one of these smaller modules is shown in Listing 2-8. This
task can be executed by running grunt uglify from the command line.

Listing 2-8. Example Module (uglify.js) Within Our New tasks Folder
// example-tasks/tasks/uglify.js

module.exports = function(grunt) {

grunt.loadNpmTasks('grunt-contrib-uglify');

grunt.config('uglify', {
'options': {
'banner': '/*! <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
'dist': {
'files': {
'dist/app.min.js': ['src/index.js']
}
}
});

};

17

www.it-ebooks.info
Chapter 2 ■ Grunt

Working with Tasks


As previously mentioned, tasks serve as the foundation on which Grunt is built—everything begins here.
A Grunt plugin, as you’ll soon discover, is nothing more than one or more tasks that have been packaged into
a Node module and published via npm. We’ve already seen a few examples that demonstrate the creation of
basic Grunt tasks, so let’s take a look at some additional features that can help us get the most out of them.

Managing Configuration
Grunt’s config() method serves as both a “getter” and a “setter” for configuration. In Listing 2-9, we see how
a basic Grunt task can access its configuration through the use of this method.

Listing 2-9. Managing Configuration Within a Basic Grunt Task


module.exports = function(grunt) {

grunt.config('basic-task', {
'message': 'Hello, world.'
});

grunt.registerTask('basic-task', function() {
grunt.log.writeln(grunt.config('basic-task.message'));
});

};

■■Note In Listing 2-9, “dot notation” is used for accessing nested configuration values. In the same way,
dot notation can be used to set nested configuration values. If at any point Grunt encounters a path within the
configuration object that does not exist, Grunt will create a new, empty object without throwing an error.

Task Descriptions
Over time, projects have a tendency to grow in complexity. With this additional complexity often comes
new Grunt tasks. As new tasks are added, it’s often easy to lose track of what tasks are available, what they
do, and how they are called. Fortunately, Grunt provides us with a way to address this problem by assigning
descriptions to our tasks, as shown in Listing 2-10.

Listing 2-10. Assigning a Description to a Grunt Task


// example-task-description/Gruntfile.js

module.exports = function(grunt) {

grunt.config('basic-task', {
'message': 'Hello, world.'
});

18

www.it-ebooks.info
Chapter 2 ■ Grunt

grunt.registerTask('basic-task', 'This is an example task.', function() {


grunt.log.writeln(grunt.config('basic-task.message'));
});

grunt.registerTask('default', 'This is the default task.', ['basic-task']);

};

By passing an additional argument to the registerTask() method, Grunt allows us to provide a


description for the task being created. Grunt helpfully provides this information when help is requested from
the command line, as shown in Listing 2-11, which includes an excerpt of the information Grunt provides.

Listing 2-11. Requesting Help from the Command Line


$ grunt --help
...
Available tasks
basic-task This is an example task.
default This is the default task.
...

Asynchronous Tasks
By default, Grunt tasks are expected to run synchronously. As soon as a task’s function returns, it
is considered finished. There will be times, however, when you find yourself interacting with other
asynchronous methods within a task, which must first complete before your task can hand control back over
to Grunt. The solution to this problem is shown in Listing 2-12. Within a task, a call to the async() method
will notify Grunt that it executes asynchronously. The method will return a callback function to be called
when our task has completed. Until this is done, Grunt will hold the execution of any additional tasks.

Listing 2-12. Asynchronous Grunt Task


// example-async/tasks/list-files.js

var glob = require('glob');

module.exports = function(grunt) {

grunt.registerTask('list-files', function() {

/**
* Grunt will wait until we call the `done()` function to indicate that our
* asynchronous task is complete.
*/
var done = this.async();

19

www.it-ebooks.info
Chapter 2 ■ Grunt

glob('*', function(err, files) {


if (err) {
grunt.fail.fatal(err);
}
grunt.log.writeln(files);
done();
});

});

};

Task Dependencies
Complicated Grunt workflows are best thought of as a series of steps that work together to produce a final
result. In such situations, it can often be helpful to specify that a task requires one or more separate tasks to
precede it, as shown in Listing 2-13.

Listing 2-13. Declaring a Task Dependency


// example-task-dependency/tasks/step-two.js

module.exports = function(grunt) {
grunt.registerTask('step-two', function() {
grunt.task.requires('step-one');
});
};

In this example, the step-two task requires that the step-one task run first before it can proceed. Any
attempt to call step-two directly will result in an error, as shown in Listing 2-14.

Listing 2-14. Grunt Reporting an Error When a Task Is Called Before Any Tasks on Which
It Depends Have Run
$ grunt step-two
Running "step-two" task
Warning: Required task "step-one" must be run first. Use --force to continue.

Aborted due to warnings.

Multi-Tasks
In addition to basic tasks, Grunt offers support for what it calls “multi-tasks.” Multi-tasks are easily the most
complicated aspect of Grunt, so if you find yourself confused at first, you’re not alone. After reviewing a few
examples, however, their purpose should start to come into focus—at which point you’ll be well on your way
toward mastering Grunt.
Before we go any further, let’s take a look at a brief example (see Listing 2-15) that shows a Grunt
multi-task, along with its configuration.

20

www.it-ebooks.info
Chapter 2 ■ Grunt

Listing 2-15. Grunt Multi-Task


// example-list-animals/tasks/list-animals.js

module.exports = function(grunt) {

/**
* Our multi-task's configuration object. In this example, 'mammals'
* and 'birds' each represent what Grunt refers to as a 'target.'
*/
grunt.config('list-animals', {
'mammals': {
'animals': ['Cat', 'Zebra', 'Koala', 'Kangaroo']
},
'birds': {
'animals': ['Penguin', 'Sparrow', 'Eagle', 'Parrot']
}
});

grunt.registerMultiTask('list-animals', function() {
grunt.log.writeln('Target:', this.target);
grunt.log.writeln('Data:', this.data);
});

};

Multi-tasks are extremely flexible, in that they are designed to support multiple configurations (referred
to as “targets”) within a single project. The multi-task shown in Listing 2-15 has two targets: mammals and
birds. This task can be run against a specific target as shown in Listing 2-16.

Listing 2-16. Running the Grunt Multi-Task Shown in Listing 2-15 Against a Specific Target
$ grunt list-animals:mammals
Running "list-animals:mammals" (list-animals) task
Target: mammals
Data: { animals: [ 'Cat', 'Zebra', 'Koala', 'Kangaroo' ] }

Done, without errors.

Multi-tasks can also be called without any arguments, in which case they are executed multiple times,
once for each available target. Listing 2-17 shows the result of calling this task without specifying a target.

Listing 2-17. Running the Multi-Task Shown in Listing 2-15 Without Specifying a Target
$ grunt list-animals
Running "list-animals:mammals" (list-animals) task
Target: mammals
Data: { animals: [ 'Cat', 'Zebra', 'Koala', 'Kangaroo' ] }

Running "list-animals:birds" (list-animals) task


Target: birds
Data: { animals: [ 'Penguin', 'Sparrow', 'Eagle', 'Parrot' ] }

21

www.it-ebooks.info
Chapter 2 ■ Grunt

In this example, our multi-task ran twice, once for each available target (mammals and birds). Notice
in Listing 2-15 that within our multi-task we referenced two properties: this.target and this.data. These
properties allow our multi-task to fetch information about the target that it is currently running against.

Multi-Task Options
Within a multi-task’s configuration object, any values stored under the options key (see Listing 2-18) receive
special treatment.

Listing 2-18. Grunt Multi-Task with Configuration Options


// example-list-animals-options/tasks/list-animals.js

module.exports = function(grunt) {

grunt.config('list-animals', {
'options': {
'format': 'array'
},
'mammals': {
'options': {
'format': 'json'
},
'animals': ['Cat', 'Zebra', 'Koala', 'Kangaroo']
},
'birds': {
'animals': ['Penguin', 'Sparrow', 'Eagle', 'Parrot']
}
});

grunt.registerMultiTask('list-animals', function() {

var options = this.options();

switch (options.format) {
case 'array':
grunt.log.writeln(this.data.animals);
break;
case 'json':
grunt.log.writeln(JSON.stringify(this.data.animals));
break;
default:
grunt.fail.fatal('Unknown format: ' + options.format);
break;
}

});

};

22

www.it-ebooks.info
Chapter 2 ■ Grunt

Multi-task options provide developers with a mechanism for defining global options for a task, which
can then be overridden at the target level. In this example, a global format in which to list animals ('array')
is defined at the task level. The mammals target has chosen to override this value ('json'), while the birds
task has not. As a result, mammals will be displayed as JSON, while birds will be shown as an array due to its
inheritance of the global option.
The vast majority of Grunt plugins that you will encounter are configurable as multi-tasks. The flexibility
afforded by this approach allows you to apply the same task differently under different circumstances. A
frequently encountered scenario involves the creation of separate targets for each build environment. For
example, when compiling an application, you may want to modify the behavior of a task based on whether
you are compiling for a local development environment or in preparation for release to production.

Configuration Templates
Grunt configuration objects support the embedding of template strings, which can then be used to reference
other configuration values. The template format favored by Grunt follows that of the Lodash and Underscore
utility libraries, which are covered in further detail in a later chapter. For an example of how this feature can
be put to use, see Listing 2-19 and Listing 2-20.

Listing 2-19. Sample Gruntfile That Stores the Contents of Its Project’s package.json
File Under the pkg Key Within Grunt’s Configuration Object
// example-templates/Gruntfile.js

module.exports = function(grunt) {
grunt.initConfig({
'pkg': grunt.file.readJSON('package.json')
});
grunt.loadTasks('tasks');
grunt.registerTask('default', ['test']);
};

Listing 2-20. A Subsequently Loaded Task with Its Own Configuration That Is Able to Reference
Other Configuration Values Through the Use of Templates
// example-templates/tasks/test.js

module.exports = function(grunt) {
grunt.config('test', {
'banner': '<%= pkg.name %>-<%= pkg.version %>'
});
grunt.registerTask('test', function() {
grunt.log.writeln(grunt.config('test.banner'));
});
};
Listing 2-19 shows a sample Gruntfile that loads the contents of the project’s package.json file using
one of several built-in methods for interacting with the file system that are discussed in further detail later
in the chapter. The contents of this file are then stored under the pkg key of Grunt’s configuration object. In
Listing 2-20, we see a task that is able to directly reference this information through the use of configuration
templates.

23

www.it-ebooks.info
Chapter 2 ■ Grunt

Command-Line Options
Additional options can be passed to Grunt using the following format:

$ grunt count --count=5

The example shown in Listing 2-21 demonstrates how a Grunt task can access this information via the
grunt.option() method. The result of calling this task is shown in Listing 2-22.

Listing 2-21. Simple Grunt Task That Counts to the Specified Number
// example-options/tasks/count.js

module.exports = function(grunt) {

grunt.registerTask('count', function() {
var limit = parseInt(grunt.option('limit'), 10);
if (isNaN(limit)) grunt.fail.fatal('A limit must be provided (e.g. --limit=10)');
console.log('Counting to: %s', limit);
for (var i = 1; i <= limit; i++) console.log(i);
});

};

Listing 2-22. Result of Calling the Task Shown in Listing 2-21


$ grunt count --limit=5
Running "count" task
Counting to: 5
1
2
3
4
5

Done, without errors.

Providing Feedback
Grunt provides a number of built-in methods for providing feedback to users during the execution of tasks,
a few of which you have already seen used throughout this chapter. While we won’t list all of them here,
several useful examples can be found in Table 2-1.

24

www.it-ebooks.info
Chapter 2 ■ Grunt

Table 2-1. Useful Grunt Methods for Displaying Feedback to the User

Method Description
grunt.log.write() Prints a message to the console
grunt.log.writeln() Prints a message to the console, followed by a newline character
grunt.log.oklns() Prints a success message to the console, followed by a newline character
grunt.log.error() Prints an error message to the console, followed by a newline character
grunt.log.subhead() Prints a bold message to the console, following by a newline character
grunt.log.debug() Prints a message to the console only if the --debug flag was passed

Handling Errors
During the course of task execution, errors can occur. When they do, it’s important to know how to
appropriately handle them. When faced with an error, developers should make use of Grunt’s error API,
which is easy to use, as it provides just two methods, shown in Table 2-2.

Table 2-2. Methods Available via Grunt’s error API

Method Description
grunt.fail.warn() Displays a warning and aborts Grunt immediately. Tasks will continue to run
if the --force option is passed.
grunt.fail.fatal() Displays a warning and aborts Grunt immediately.

Interacting with the File System


As a build tool, it comes as no surprise that the majority of Grunt’s plugins interact with the file system in one
way or another. Given its importance, Grunt provides helpful abstractions that allow developers to interact
with the file system with a minimal amount of boilerplate code.
While we won’t list all of them here, Table 2-3 shows several of the most frequently used methods within
Grunt’s file API.

Table 2-3. Useful Grunt Methods for Interacting with the File System

Method Description
grunt.file.read() Reads and returns file’s contents
grunt.file.readJSON() Reads a file’s contents, parsing the data as JSON, and returns the result
grunt.file.write() Writes the specified contents to a file, creating intermediate directories, if necessary
grunt.file.copy() Copies a source file to a destination path, creating intermediate directories, if
necessary
grunt.file.delete() Deletes the specified file path; deletes files and folders recursively
grunt.file.mkdir() Creates a directory, along with any missing intermediate directories
grunt.file.recurse() Recurses into a directory, executing a callback for every file that is found

25

www.it-ebooks.info
Chapter 2 ■ Grunt

Source-Destination Mappings
Many Grunt tasks that interact with the file system rely heavily on the concept of source-destination mappings,
a format that describes a set of files to be processed and a corresponding destination for each. Such mappings
can be tedious to construct, but thankfully Grunt provides helpful shortcuts that address this need.
Imagine for a moment that you are working on a project with a public folder located at its root. Within
this folder are the files to be served over the Web once the project is deployed, as shown in Listing 2-23.

Listing 2-23. Contents of an Imaginary Project’s public Folder


// example-iterate1

.
└── public
└── images
├── cat1.jpg
├── cat2.jpg
└── cat3.png

As you can see, our project has an images folder containing three files. Knowing this, let’s take a look at
a few ways in which Grunt can help us iterate through these files.
In Listing 2-24, we find a Grunt multi-task similar to those we’ve recently been introduced to. The key
difference here is the presence of an src key within our task’s configuration. Grunt gives special attention
to multi-task configurations that contain this key, as we’ll soon see. When the src key is present, Grunt
provides a this.files property within our task that provides an array containing paths to every matching
file that is found via the node-glob module. The output from this task is shown in Listing 2-25.

Listing 2-24. Grunt Multi-Task with a Configuration Object Containing an src Key
// example-iterate1/tasks/list-files.js

module.exports = function(grunt) {

grunt.config('list-files', {
'images': {
'src': ['public/**/*.jpg', 'public/**/*.png']
}
});

grunt.registerMultiTask('list-files', function() {
this.files.forEach(function(files) {
grunt.log.writeln('Source:', files.src);
});
});

};

26

www.it-ebooks.info
Random documents with unrelated
content Scribd suggests to you:
humanity, and they are mere things and animals. Keep your
eye upon it, throttle it, kill it, stab it, do everything you can to
wound it—to impede its progress. Remember, before trusting
them to do anything for yourself, prepare to do it yourself.
Don’t turn over your business to anybody else. No man
deserves anything unless he is man enough to make an effort
to lift himself from oppression.’
“Then there was an interruption on account of some
storm-clouds. Everybody started to go away. Mr. Parsons
suggested that they adjourn over to Zepf’s Hall. Fielden said
no, the people were trying to get information, and he would
go on. And he went on: ‘Is it not a fact that we have no
choice as to our existence, for we can’t dictate what our labor
is worth? He that has to obey the will of another is a slave.
Can we do anything except by the strong arm of resistance?
The Socialists are not going to declare war, but I tell you war
has been declared upon us; and I ask you to get hold of
anything that will help to resist the onslaught of the enemy
and the usurper. The skirmish lines have met. People have
been shot. Men, women and children have not been spared by
the capitalists and minions of private capital. It has no mercy
—so ought you. You are called upon to defend yourselves,
your lives, your future. What matters it whether you kill
yourselves with work to get a little relief, or die on the battle-
field resisting the enemy? What is the difference? Any animal,
however loathsome, will resist when stepped upon. Are men
less than snails or worms? I have some resistance in me; I
know that you have, too. You have been robbed, and you will
be starved into a worse condition.’
“That is all I have. At that time some one alongside of me
asked if the police were coming. I was facing northeast,
looked down the street, and saw a file of police about the
middle of Randolph Street. At once I put my paper in my
pocket and ran right over to the northwest corner of Randolph
and Desplaines. Just when I reached the sidewalk, the front
rank of the police got to the southwest corner of Randolph
and Desplaines. I stood there until some of the police
marched by, and the first thing I knew I heard an explosion;
and the next thing there was a volley of fifteen or twenty or
thirty shots, and I thought it was about time to leave, so I
skinned down Randolph Street. While I was running I heard a
great lot of shots, and somebody tumbled right in front of me,
but I didn’t stop to see whether he was hurt. I didn’t see who
shot first. As to the temper of the crowd, it was just an
ordinary meeting.”

On cross-examination Mr. English said:


“It was a peaceable and quiet meeting for an out-door
meeting. I didn’t see any turbulence. I was there all the time.
I thought the speeches they made that night were a little
milder than I had heard them make for years. They were all
set speeches, about the same thing. I didn’t hear any of them
say or advise that they were going to use force that night.
Before I went to the meeting my instructions from the Tribune
office were to take only the most incendiary part of the
speeches. I think when Mr. Parsons spoke about the Cincinnati
meeting he said he had been at Cincinnati and seen the
procession. I heard the announcement to the crowd to
disperse, distinctly. I did not hear Mr. Fielden say: ‘There come
the bloodhounds now; you do your duty and I’ll do mine.’ I
heard nothing of that import at all.”

M. M. Thompson testified:
“I am at present employed in the dry-goods business of
Marshall Field & Co. Prior to the 4th of May last I was running
a grocery store at 108 South Desplaines. I was at the
Haymarket Square on the evening of May 4th. I walked west
on Randolph Street about half past seven o’clock, and
somebody handed me a circular headed ‘Revenge,’ and signed
‘Your Brothers.’ About twenty-five minutes to eight I got to the
corner of Desplaines and Randolph. I met Mr. Brazleton of the
Inter-Ocean. We talked about fifteen minutes. I asked the
time. It was ten minutes of eight. Brazleton pointed out to me
Mr. Schwab, who came rushing along Desplaines Street in a
great hurry. I then went over to the east side of Desplaines
Street. I walked up Desplaines Street near the corner of Lake,
and came back again to the alley back of Crane Bros’. and
stood just back of that alley. Then I saw Spies get up on the
wagon and he asked for Parsons. Parsons didn’t respond. He
then got down, and Schwab and Spies walked into that alley
at Crane Bros’., near which the wagon was situated. The first
word I heard between Schwab and Spies was ‘pistols;’ the
next word was ‘police.’ I think I heard ‘police’ twice, or ‘pistols’
twice. I then walked just a little nearer the edge of the alley,
and just then Spies said: ‘Do you think one is enough, or
hadn’t we better go and get more?’ I could hear no answer to
that. They then walked out of the alley and south on
Desplaines Street, and west on the north side of Randolph to
Halsted, and cut across the street and went over to the
southwest corner; they were there about three minutes, came
out of that crowd again and came back. On the way back, as
they neared Union Street, I heard the word ‘police’ again. Just
then I went past them, and Schwab said: ‘Now, if they come,
we will give it to them.’ Spies replied he thought they were
afraid to bother with them. They came on, and before they
got up near the wagon they met a third party, and they
bunched right together there, south of the alley, and appeared
to get right in a huddle; and there was something passed
between Spies and the third man—what it was I could not
say. This here (indicating picture of Schnaubelt, heretofore
identified) is, I think, the third man; I think his beard was a
little longer than in this picture; this is the picture of the third
man. I saw the third man on the wagon afterwards. Whatever
it was that Spies gave him, he stuck it in his pocket on the
right-hand side. Spies got up on the wagon, and I think that
third man got up right after him. I noticed him afterwards
sitting on the wagon, and that he kept his hands in his
pockets. I stayed there until Mr. Fielden commenced to speak;
then I left.

On cross-examination Thompson said:


“My grocery store was closed by the Sheriff under an
execution. I worked for Marshall Field before. I had never
seen any of the defendants, to my knowledge, before that
night, in my life. When I saw Spies and Schwab go into the
alley, there was a crowd there. I was standing right near the
alley, or alongside north of it, up against the building. I
couldn’t see down the alley unless I turned my face to it. The
first time I had ever seen Spies was when he got up on the
wagon. Spies got out of the wagon and went into Crane’s alley
with Schwab. I was right around the corner of the alley within
three feet probably at the farthest, and I moved down to
within half a foot. I did not look down the alley, only when
they came out of the alley I did look. The conversation
between Spies and Schwab was in English. I don’t understand
German. I didn’t hear any words between ‘police’ and ‘pistols.’
They were in there probably two or three minutes. When I
drew up within a foot of the alley, I heard: ‘Do you think one
enough, or had we better go for more?’ Going up Randolph
Street, I heard some words spoken in German between them,
but not in the conversation at the alley. I cannot say that I
knew Mr. Schwab’s voice at that time. I only knew Mr. Spies’
voice from what I heard him ask on the wagon. Spies was the
one who used the words ‘pistols’ and ‘police.’ I did not see him
when he said it. I could not see him without putting my head
around the corner. They went out of my sight when they went
into the alley. The whole conversation was done in three
minutes, I should judge. The first remark that I heard was
about a minute and a half after they went into the alley and
went out of sight. When they came out and walked south on
Desplaines I followed them within a few feet. It was then
about a quarter past eight. They walked west on Randolph
Street to Halsted, and I trailed after them all the time, part of
the time beside them, part of the time ahead, and past them,
but all the time close to them. When they came to Halsted
there were a few people there, not much of a crowd. I was
still tagging after them with no other object than looking for
the meeting, to find where the audience was assembled. I
don’t know whether they saw me; there was nothing
whatever to prevent their seeing me. When they were going
west I couldn’t hear a word of what they did say. The street
lamps were lighted. When they got down on Halsted there
was a crowd, of about twenty-five people. They were right in
the thickest of the crowd, and I stood on the sidewalk, about
ten feet from them. I didn’t hear either of them say a word.
Then they went back east on Randolph Street. I was about six
feet behind them. They said nothing. There was nobody else
following them besides me. I couldn’t hear what they said
until they came to Union Street. Then I got past them. It was
light at the time; they could see me. Near Union Street
Schwab said: ‘Now, if they come, we will give it to them,’ and
Spies said he did not think they would bother them, because
they were afraid. This conversation was carried on in the
English language. I was behind them when I heard the first of
it, but they kind of slackened, and I got by them. I was
making my gait quicker to get by them. Schwab finished his
remark when I got about three feet by them. Schwab made
his remark in an ordinary tone of street conversation, loud
enough for me to hear. I heard no more conversation between
Schwab and Spies. I testified before the Coroner’s jury. I
testified to this conversation at Union Street. If I didn’t, it was
an oversight on my part, or it was because nobody asked me
any question, but I say that I did say that before the
Coroner’s inquest.
“Coming back, I stopped on the northwest corner of
Randolph and Desplaines. I was then about ten or fifteen feet
ahead of Spies and Schwab. They came up. I can’t say that
they were talking. They went right through the street, moving
diagonally to the wagon. I staid at the corner. I did not go
after them until they got onto the wagon. That was the last
time that I saw Schwab. I saw Spies when he got up to make
a speech. Oh, no, that wasn’t the last time that I saw Schwab
that night. That was the last time that I saw him until they
were out of sight and the third man met them. When they
started from the corner northeast across the street, I stood at
the corner just to let them cross the street. Then I started
after them. They did not get out of my sight. I didn’t catch up
with them at all. When I got within eight or ten feet of them
they were standing on the sidewalk. They stopped right there,
about five feet south of the south line of Crane’s alley. There
wasn’t probably more than half a dozen people on the east
side of the street. There were a good many people on the
West Side. It was then about twenty or twenty-five minutes
past eight. When I got up within eight or ten feet of them and
they stopped, I stopped too, and looked at them. They were
in plain view of me. I don’t think they did see me, though they
could see me if they looked up. I think there are some electric
lights near there, on the Lyceum building. I was between
them and the electric light. When they stopped there, the next
thing was that they met that third man. I had never seen that
third man before. I have seen this picture of Schnaubelt
before; I think Mr. Furthmann showed it to me about a week
ago. That third party came from the east. He must have been
standing up against the house, and he walked west to the
front of the sidewalk. Schnaubelt was not facing me; he had
his back to me. They did not go into the alley. One had his
back south, one east, and Spies had his back north. I didn’t
hear what they were talking about. I was on the sidewalk
near the curb-stone, partly south, not directly south of them.
Spies stood directly to the north, which would bring his back
to me. I don’t know but what he did see me. They stood there
about thirty seconds. I didn’t hear a word. Spies handed that
third man something, who put it into his pocket, and Spies got
up on the wagon and made a speech. I did not see Schwab
on the wagon. Spies got right up on the wagon and
commenced to speak, but one or two minutes elapsed in the
time.”

August Huen, a printer in the employ of Wehrer &


Klein, set up the German part of the circular headed
“Attention, Workingmen!” and testified that the last
line read, “Workingmen, arm yourselves and appear
in full force.” Mr. Fischer wrote it. On cross-
examination, he testified that an hour after the form
had been given to the pressman the last line was
taken out.
Hugh Hume, a reporter for the Inter-Ocean,
testified:
“I saw Mr. Fielden and other defendants in the sweat-box—
that is, the cells down-stairs—at the Central Station, about
midnight, between the 5th and 6th of May last. I had a
conversation with Spies. He said he had been at the
Haymarket meeting. He had gone up there to refute the
statements of the capitalistic press in regard to what he had
said at McCormick’s. Up at McCormick’s he had been talking to
a lot of people whom he could not influence—all good
Catholics. During his speech on the Haymarket, some people
had shown a disposition to hang McCormick. He had told
them not to make any threats of that kind. He had said,
‘When you want to do a thing of that kind, don’t talk so much
about it, but go out and do it.’ He then said to me that the
people had reached a condition where they were willing to do
any violence, and he had advocated violence of that kind. It
was necessary to bring about the revolution that the Socialists
wanted. He said he had advocated the use of dynamite. I
asked him if he was in favor of killing police officers with
dynamite. He hesitated a little, and then said the police
represented the capitalists and were enemies of theirs, and
when you have an enemy he has got to be removed. That is
the gist of what he said. Spies said he didn’t know anything
about the bomb being exploded until afterwards. He had
heard a noise that resembled the sound of a cannon, and
thought the police were firing over the heads of the people to
frighten them. He said he considered all laws as things you
could get along without; they were inimical to the best
interests of the people and of the social growth. He did not
think that dynamite was in his office when he left it, and had
an idea that the police put that dynamite there to get a case
on him.
“I had a little talk with Mr. Fielden. He was suffering
somewhat from his wound. When I asked him how the
Haymarket affair accorded with his ideas of Socialism, he said,
‘You are on dangerous ground now. There is an argument,
though, that we have, that is to the effect that if you cannot
do a thing peaceably, it has got to be done by force.’
Something to that effect; I don’t remember the language.
Fielden said, as to the number of Socialists in Chicago, that
there were a number of groups here, containing 250 men.
Those were recognized Socialists, but they had people from all
over the city, from nearly every wholesale house; but those
people are afraid to come out yet, only awaiting an
opportunity. He spoke about the decision of the Supreme
Court prohibiting military companies from marching around
with arms. He was inclined to think that the decision was not
right.
“I had a short interview with Schwab. All he had to say
was that Socialism was right, even with the blood shed at the
Haymarket.”

On cross-examination Mr. Hume said that Spies


saw him write down answers to the questions and
knew that he wanted the interview for publication.
Harry L. Gilmer proved a strong witness and
testified as follows:
“I am a painter by trade. Reside at 50 North Ann Street.
On the evening of May 4 last, I was at the Haymarket meeting
on Desplaines Street. I got there about a quarter to ten
o’clock. In going home, when I got to the corner of Randolph
and Desplaines Streets, I saw a crowd over there, and went
up to where the speaking was going on, on the east side of
Desplaines Street. I saw the wagon; did not pay particular
attention to the speaking. I stood near the lamp-post on the
corner of Crane Bros’. alley, between the lamp-post and the
wagon, and up near the east end of the wagon for a few
minutes. The gentleman here (pointing to Fielden) was
speaking when I came there. I staid around there a few
minutes, was looking for a party whom I expected to find
there, and stepped back into the alley between Crane Bros’.
building and the building immediately south of it. The alley
was south of the wagon. I was standing in the alley looking
around for a few minutes; noticed parties in conversation,
right across the alley, on the south side of the alley.
Somebody in front of me on the edge of the sidewalk said,
‘Here comes the police.’ There was a sort of rush to see the
police come up. There was a man came from the wagon down
to the parties that were standing on the south side of the
alley. He lit a match and touched it off, something or another
—the fuse commenced to fizzle, and he give a couple of steps
forward, and tossed it over into the street. He was standing in
this direction (illustrating). The man that lit the match on this
side of him, and two or three of them stood together, and he
turned around with it in his hand, took two or three steps that
way, and tossed it that way, over into the street. I knew the
man by sight who threw that fizzing thing into the street. I
have seen him several times at meetings at one place and
another in the city. I do not know his name. He was a man
about five feet ten inches high, somewhat full-chested, and
had a light sandy beard, not very long. He was full-faced, his
eyes set somewhat back in his head. Judging from his
appearance, he would probably weigh 180 pounds. My
impression is his hat was dark brown or black; I don’t know
whether it was a soft hat, a felt hat or a stiff hat. This here
(indicating photograph of Schnaubelt heretofore identified) is
the man that threw the bomb out of the alley. There were four
or five standing together in the group. This here (pointing to
Spies) is the man who came from the wagon toward the
group.
“I did not see the police myself, there were so many
people between me and them. I don’t recollect any
declaration from any of the police officers about this person—
nothing distinctly, anyway. That man over there (pointing at
defendant Fischer) was one of the parties. After the bomb
was thrown these parties immediately left through the alley. I
stood there. The firing commenced immediately afterwards,
and my attention was attracted by the firing, and I paid more
attention to that than anything else.”

On cross-examination Gilmer testified to having


resided formerly in Des Moines, Iowa, Fort Dodge,
Iowa, Kansas City, Mo., and in various localities in
Chicago. He then proceeded as follows:
“I know the Coroner’s jury was investigating the matter. I
saw an account of the investigation of the grand jury in the
paper. I first told a man by the name of Allen and another
party whom I don’t know, and a reporter of the Times, that I
saw the match lighted, and saw the man who threw the
bomb. I think that it was two or three days after the 4th of
May. A number of people were talking the matter over on the
west side of the City Hall, on La Salle Street, and I made the
remark that I believed if I ever saw the party who threw the
bomb I could identify him. They didn’t ask me why I made
that remark. I don’t think they asked me any questions, what
I knew about the matter. The reporter afterwards told me he
had heard the remark. I think that was on the 6th of May. On
May 5th, I was working on the corner of Twentieth Street and
Wabash Avenue. On the 6th of May I went down to 88 La
Salle Street to collect a bill. I went across the street, and
there had the conversation with the reporter and the others.
That night I had a note left at my room for me to come down
to the Central Station. The name of James Bonfield was
signed to the note. I went to the Central Station and had a
conversation with Mr. Bonfield the next day; I couldn’t tell
exactly whether on the 6th or the 7th. I made my statement
to Mr. Bonfield. I never appeared before a Coroner’s jury; was
never subpoenaed to appear before any Coroner’s jury that
examined any of the dead policemen. I was at the Haymarket
meeting about fifteen minutes from the time I got there to the
explosion of the bomb. I was looking for a person who had
told me he was going to the meeting. I kept looking through
the crowd to see if I could find him. Fielden was speaking
then. I don’t remember anything of his speech, except that he
made use of the word McCormick. Before I went down-town I
had read in the paper that there had been a riot at
McCormick’s the day before, and that the police had shot
some men. I was in the neighborhood of where Fielden talked
for about fifteen minutes. I don’t remember anything about
the connection in which Fielden spoke of McCormick. I was
looking for a gentleman by the name of Richard Roe, and
didn’t pay any attention to what Fielden said. When I stepped
into the alley I think I was on the north side of the alley,
about eight feet from the corner of Crane’s building. That
group of men was right across the alley on the south side.
The lamp was burning on the corner of the alley at that time,
and it shone right down. I could see the persons in that party
distinctly; could see their countenances; they could see
myself. They were also about eight or nine feet from the
mouth of the alley. I could hear them talk. They spoke
German. I didn’t understand them. Before the man came from
the wagon I stepped across the alley and was standing on the
north side of the alley, perhaps three or four feet to the east
of that group, so that I was standing about twelve or fourteen
feet from the mouth of Crane’s alley. I did not say that I saw
the wagon from that point. I could just see the hind end of
the wagon from where I stood when I went through the alley.
I think there was a tail-board. The edges of the box of the
wagon were perhaps ten inches high. I don’t know whether
there were side-boards on that wagon or not; I could not say
positively as to the width of the side-boards on the wagon.
They might have been higher than ten inches. I am sure there
was a box of some kind on the wagon. My impression is it was
a wagon about twelve or thirteen feet long, with low side-
boards on. I didn’t see anybody get off of the wagon after I
went in the alley. I did not say Mr. Spies got down off the
wagon. I said he came from towards the wagon. I saw him
standing on the sidewalk before I went in the alley. I did not
say I saw Spies in the wagon at all. Mr. Spies is the man that
came down in the alley and lighted the bomb, to the best of
my recollection. When I saw him standing on the sidewalk he
was talking with somebody. I would be inclined to think it was
this gentleman here (indicating Schwab). I could not say for
sure. I think it was a dark-complexioned man. My impression
is it might be him. I have very little doubt but Fischer is the
man I saw in the group. I am very nearly as positive that
Fischer is the man as I am that the picture is the picture of
the man who threw the bomb. I am sure Fischer is the man. I
think I saw Mr. Parsons there that night talking to some ladies.
I had been down to the Palmer House that evening to see
some gentlemen from Des Moines that I understood were in
the city. One of them was Judge Cole, another was ex-Gov.
Samuel Merrill. I didn’t find either of them there. I went to the
meeting, as I thought I would meet Mr. Roe, and we would go
home together. That was the only business I had with Mr. Roe.
It would have been eight or nine blocks from the Haymarket
to where I lived.
“I did not run at the time of the shooting. I did not move
at all. I stood right at the mouth of the alley. After it was all
over I backed out the alley, took a car and went home. There
were no bullets coming in around my locality in the alley. On
the street-car on my way home I didn’t talk with anybody
about the occurrence. There were quite a number of people in
the car talking about the Haymarket occurrence, and there
was considerable excitement in the car on account of it. The
next morning I went down on the Wabash Avenue car to the
corner of Twentieth Street and Wabash Avenue.
“I heard people speak about the Haymarket affair in the
restaurant, on Madison Street, where I took my breakfast. I
did not say to them anything about my seeing the match
lighted and the bomb thrown. I bought the News on the car. I
think I was working for Frank Crandle that day; to the best of
my recollection, there was only one man working with me on
the job. We worked alongside of each other some time. Talked
about different things, about our business. I did not say to
him that I saw the bomb thrown, nor that I saw the man light
the match that lit the bomb. I told him I had been at the
Haymarket and spoke of the Haymarket riot, and I think I said
there were a number killed or wounded. In the evening I went
home on the Wabash Avenue car. People were speaking about
the Haymarket meeting in the car. I didn’t tell them I knew
anything about it. I think I got home about half past six. I had
no conversation with the landlady. After my supper, my
impression is I went to Mr. Roe’s house. He was not at home.
I stayed there about fifteen minutes talking with Mrs. Roe.
Her daughter, about twelve or thirteen years old, was present
during the conversation. We talked about the Haymarket
meeting. I told her I was there. She said she would not let Mr.
Roe go to the meeting. I did not tell her nor anybody on that
occasion that I saw the bomb lighted and thrown. Since noon
adjournment I had no talk with James Bonfield.”
“Were not you just now walking back and forth in the
corridor with him?”
“I did not have no—“
“Didn’t you walk back and forth?”
“Yes, sir.”
“You were talking to him?”
“Yes, sir.”
“When I was at Central Station, I think, both Inspector
Bonfield and Lieut. Kipley were present when I made the
statement that I could recognize the man, if I ever saw him
again, who threw the bomb. Afterwards I told all the details to
Mr. Grinnell. I explained matters more to him than to anybody
else. I would not be positive that I told Mr. Bonfield I saw the
man light the match. I gave a description of the man that I
saw throw the bomb. I think the man had a black or blue sack
coat on. I think he had black eyes, and somewhat light
whiskers. The bomb went in a westerly direction. I have seen
Mr. Spies the last year and a half, and knew him by sight, not
by name. I heard him speak at public meetings, seen him very
frequently, but never knew his name. I heard him once on
Market Street, a year ago last spring. I did not inquire who it
was that spoke. I knew from hearing him and reading the
papers that Spies was one of the speakers. I frequently heard
the name of August Spies. At the time I had the conversation
with Bonfield I described to him as well as I could the man
that struck the match and lighted the fuse. It was either
Bonfield or one of the officers in the Central Station. They
were all together. I was twice over at police headquarters.
This picture here (photograph of Schnaubelt) was shown to
me first some time last week, at the State’s Attorney’s office. I
was in the city during the time the Coroner’s jury was
examining into the cause of the death of different policemen,
and at the time the grand jury was examining into this case.
The officers knew my name and address. They never called
on me to go before the grand jury or the Coroner’s jury.
“The man who threw the bomb was about five feet and
eight, ten or nine inches high. I don’t think he was a man over
six feet tall. The first time I told Mr. Grinnell of my experience
at the Haymarket was when I made my second visit to the
Central Station, on Sunday after the Haymarket meeting. I
think at that time I only told Mr. Grinnell that I could identify
the person that threw the bomb, if I saw him. I think I told
him at that time that I saw one man strike a match and light
the fuse, and another man throw the bomb. Mr. Fischer was
brought in while we had the conversation at the Central
Station. I looked at him. I said nothing about his being the
man that struck the match. I knew him by sight. I identified
him as being one of the men who composed the group in the
alley.
“I received some money two or three times when I have
been over here from Mr. James Bonfield—ten or fifteen cents,
sometimes a quarter. At the conversation at Central Station I
was not told that I was wanted as a witness before the grand
jury. I saw the picture of Rudolph Schnaubelt about six weeks
ago, when Mr. Grinnell sent for me. I did not tell any person at
any time, except the officers that I mentioned, that I saw the
act of lighting the bomb accomplished. Neither Mr. Grinnell
nor Bonfield, nor any other officer, told me to keep silent in
regard to the matter.
“I am six feet three in height. I could pretty near see right
over the head of the fellow who threw the bomb. When I gave
a description of the man who came from the wagon and
lighted the match that lit the fuse they did not bring out Mr.
Spies for me to look at. Spies had kind of dark clothes on that
night. His hat was black or brown. My impression is it was a
limber-rimmed hat. I first told Mr. Grinnell one day last week
that this is the man that struck the match, when I saw him
sitting here in court. I think Mr. Fischer had on a blue sack-
coat that night. I think he had a black necktie. If Schnaubelt
had any necktie that night it was a very light one. Spies had a
turn-down collar that night and not any necktie. I think the
upper buttons of Mr. Schnaubelt’s coat were buttoned. I think
Spies had one or two buttons of his coat buttoned up when he
came from the wagon into the alley.”

Martin Quinn was recalled and testified to finding,


at Engel’s house, a machine for making bombs.
“Engel said it had been left there by some man about four
or five months previous to that time. Mrs. Engel gave a
description of the man who left the machine down at the
basement door, as a man with long black whiskers and pretty
tall. Mr. Engel said he thought he knew the man, and he
thought the machine was made for the purpose of making
bombs. There had been a meeting at Turner Hall, where this
man had made a speech about the manufacture of bombs,
and the next thing was, this machine was brought over, and
Engel had said to him he wouldn’t allow him to make any
bombs in his basement; so the man went away. Engel didn’t
know where he was.”

John Bonfield was recalled and testified to being at


the Central Station when Officer Quinn brought Engel
and the machine there. Bonfield, being asked by
State’s Attorney Grinnell to explain the purpose of the
apparatus, said:
“This is a blast furnace in miniature—a home-made one.
This upright part could be lined with fire-clay. This shoulder,
some two and a half inches from the bottom, could be filled in
around with clay, leaving the holes open. This, in a blasting
furnace, would be known as a tweer. It is filled up to a
considerable height with clay to protect it from the hot fire
inside, and the pressure of air is applied through those pipes,
one or both of them, as may be necessary. When the fire is
extinguished or removed, the debris or slag that comes from
the metal, and the ashes and cinders from the material used
for fuel, can be taken out through the trap at the bottom. The
spout is for the purpose of passing out the melted metal. It is
stopped with a plug of clay, and when the plug is removed the
metal is poured through that tube.”

Louis Mahlendorf
testified as follows:
“I am a tinner by trade, at
292 Milwaukee Avenue, since
two years. I know the
defendant Engel since about
eight years. I made this
machine (referring to blasting-
machine) for Engel over a year
ago. I cut off the iron and
formed it up. Another
gentleman, a kind of heavy-set
man with long beard, was with
him when he ordered it. Mr.
Engel waited for it. He took it
away with him.”
ENGEL’S BLAST FURNACE.
From a Photograph.
Hermann Schuettler, a
detective connected with
the East Chicago Avenue Station, gave the facts with
reference to his arrest of Lingg, and his search of the
room on Sedgwick Street, with Officers Stift,
Loewenstein and Whalen:
“We searched a trunk and found a round lead bomb in a
stocking. The trunk was in the southeast room. In another
stocking I found a large navy revolver. Both revolver and
bomb were loaded. I turned them over to Capt. Schaack. We
found a ladle and some tools, a cold chisel and other articles.
This here (indicating) is the trunk I found in the room. The
letters ‘L. L.’ were on it at the time. I recollect a round
porcelain-lined blue cup made out of china that I found, and I
believe a file. In the closet underneath the baseboard we
found a lot of torn-off plaster. The lathing was sawed so you
could get your hand between the floor and the bottom of the
laths underneath. I saw those lead pipes (indicating) lying
between the house Lingg lived in and the next house to it, in
a small gangway. On the way to the Chicago Avenue Station I
asked Lingg why he wanted to kill me. He said: ‘Personally, I
have nothing against you, but if I had killed you and your
partner I would have been satisfied. I would have killed
myself if I had got away with you and your partner.”

On cross-examination witness stated that he had


had no search warrant for going through Lingg’s
trunk.
Jacob Loewenstein, another detective connected
with the same station, testified to assisting Schuettler
in arresting Lingg and that after they had vanquished
him Lingg said several times: “Shoot me right here,
before I will go with you. Kill me!” Witness further
stated:
“I was with Officers Whalen, Stift, Schuettler, Cushman and
McCormick, at Lingg’s room, on May 7, between ten and
eleven o’clock. Nobody was in the house. The door was
locked. Finally we pushed in the door and went in. In a little
bed-room in the southeast corner of the house there was a
bed and a wash-stand and a trunk, and a little shelf up in the
corner with some bottles on it. In the closet there were some
shells, and some loaded cartridges, and on the floor some
metal and some lead. Those here (indicating box containing
shells) are the shells I found in the closet of Lingg’s room. I
found those bolts (indicating) in the wash-stand. This metal
here (indicating) I found in a dinner-box with some loaded
dynamite bombs in the trunk. There were four bombs in this
box (indicating), gas-pipe bombs. The two in the bottom were
loaded. When I first opened the trunk this cover (indicating)
dropped down, and with this Remington rifle (indicating),
which was loaded, fell down. I found a lot of papers and
books in the top of the trunk. In a gray stocking I found this
round dynamite bomb, loaded (indicating). I found two pieces
of solder in that dinner-box. I found a blast hammer and one
smaller hammer, a couple of iron bits and drills, a two-quart
pail, with a little substance looking like saw-dust in the bottom
of it, which I found out to be dynamite. I found a little tin
quart basin under the bed with a little piece of fuse in it. In
the bottom of the trunk I found two or three pieces of fuse. In
the closet we tore off the baseboard, which had been freshly
nailed down—the nails were projecting out a little bit—and
found the plaster was torn out all the way around on the
baseboard, and there were holes there.”

Joseph B. Casagrande, telephone operator at the


East Chicago Avenue Station, but on duty at the
Larrabee Street Station on the night of May 4, and
John K. Soller, a police officer at the last-named
station, testified to a call for a patrol wagon and its
leaving at 10:40 o’clock for Desplaines and Randolph
Streets with a full load of officers.
John B. Murphy, a physician and surgeon, was
called to the Desplaines Street Station after the
Haymarket explosion and remained until three o’clock
in the morning. He was a surgeon at the Cook County
Hospital, and when he left the station he proceeded
direct to that institution. At the station Dr. Murphy
said that he first dressed Barrett, who was
complaining and crying with severe pain.
“He had a very large wound in his side, large enough to
admit two fingers right into his liver, and severely bleeding. I
could not reach with my finger the piece of shell that caused
the injury. It was a lacerated wound, much larger than could
be made by an ordinary pistol bullet. I tampened the liver
with gauze to prevent his bleeding to death at the station, and
I went on to other officers in that way until I dressed in all
between twenty-six and thirty at the station. When we got
through with that, at three o’clock, Dr. Lee remained at the
station while I went to the hospital to take care of those
injured most severely, who were to be sent to the hospital.
Officers Muller, Whitney, Keller, Barrett, Flavin and Redden are
the principal men that I ordered him to send first to the
hospital.”

Dr. Murphy then gave a list of the men and


specified the particular character of their wounds.
E. G. Epler, a physician and surgeon practicing at
No. 505 South Canal Street, testified to having
dressed a wound of Fielden between eleven and
twelve at night on May 4.
“The wound was on the left side of the left knee joint, the
bullet having passed in underneath the skin and passed out
again five inches from the point of entry. He said he was
crawling on the pavement trying to get away from the crowd
when he received the injury, and the bullet glanced off from
the pavement and struck him in that position.”

Michael Hoffman, a detective connected with the


Larrabee Street Station, gave evidence as to finding
nine round bombs and four long ones.
“These two bombs (indicating) I found at the corner of
Clyde and Clybourn Avenue, near Ogden’s Grove, under the
sidewalk. They were empty. I found another one there which
was loaded, and which I gave to Capt. Schaack. Gustav
Lehman, who was a witness in this case, was with me when I
found them. I got two coils of fuse, a can of dynamite and a
box of caps at the same time. I found these two pieces of
gas-pipe (indicating) at 509 North Halsted Street, under the
house of John Thielen, who was arrested, with two cigar-
boxes full of dynamite and two boxes of cartridges, one rifle,
one revolver. The revolver and one box of cartridges were
buried under the floor of the coal-shed, and two bombs which
were loaded, the dynamite and rifle and other box of
cartridges were buried under the house in the ground. The
can of dynamite which Lehman pointed out to me, and which
I found near Ogden’s Grove, held about a gallon. This can and
the box of caps were on the stone of the pavement; the
bombs were buried in the ground.”
At this stage of the proceedings I was myself put
on the stand. My testimony, as taken by the
stenographers, was as follows:
“I am police captain of the Fifth Precinct. My headquarters
are at East Chicago Avenue Station. I have charge of two
other stations besides. Have been connected with the force
for eighteen years. Have been captain one year. I have seen
Spies, Schwab, Neebe and Fischer. Had no personal
acquaintance with them. The defendants Engel and Lingg
were arrested and confined in my station. Lingg was arrested
on May 14th; Engel about the 18th. I had my first
conversation with Lingg about this case about three o’clock on
the afternoon of May 14th. Lingg told me his name, and that
he had lived at 442 Sedgwick Street. He had been out of work
for about four weeks. I asked him whether he was at the
meeting held in the basement of 54 West Lake Street on
Monday night, and he said, ‘Yes.’ On Tuesday night, May 4th,
he said, he was at home—not all the evening. He and Seliger
had been on Larrabee Street, quite a ways north; had had
several glasses of beer, and from there he went home. He said
he had made some bombs to use them himself. He said he
had reason for being down on the police; they had clubbed
him out at McCormick’s. He said he was down on capitalists,
and found fault with the police for taking the part of the
capitalists. If the capitalists turned out the militia and the
police force with their Gatling guns, they couldn’t do anything
with revolvers, and therefore they had adopted these bombs
and dynamite. He said he had learned to make bombs in
scientific books of warfare published by Most, of New York. He
had got his dynamite on Lake Street, somewhere near
Dearborn, and had bought some fuse and caps, and told me
what he paid for it. He had not used up all his dynamite. He
said he had made bombs of gas-pipe, and also of metal and
lead mixed. He found the gas-pipe on the street sometimes.
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like