Yeoman 是 Google 的團隊和外部貢獻者團隊合做開發的,他的目標是經過 Grunt(一個用於開發任務自動化的命令行工具)和 Bower(一個HTML、CSS、Javascript 和圖片等前端資源的包管理器)的包裝爲開發者建立一個易用的工做流。javascript
Yeoman 的目的不只是要爲新項目創建工做流,同時仍是爲了解決前端開發所面臨的諸多嚴重問題,例如零散的依賴關係。css
Yeoman 主要有三部分組成:yo
(腳手架工具)、grunt
(構建工具)、bower
(包管理器)。這三個工具是分別獨立開發的,可是須要配合使用,來實現咱們高效的工做流模式。html
下面這幅圖很形象的代表了他們三者之間的協做關係。前端
Yeoman 特性:java
快速建立骨架應用程序
。使用可自定義的模板(例如:HTML五、Boilerplate、Twitter Bootstrap 等)、AMD(經過 RequireJS)以及其餘工具輕鬆地建立新項目的骨架。自動編譯 CoffeeScrip 和 Compass
。在作出變動的時候,Yeoman 的 LiveReload 監視進程會自動編譯源文件,並刷新瀏覽器,而不須要你手動執行。自動完善你的腳本
。全部腳本都會自動針對 JSHint 運行,從而確保它們遵循語言的最佳實踐。內建的預覽服務器
。你不須要啓動本身的 HTTP 服務器。內建的服務器用一條命令就能夠啓動。很是棒的圖像優化
。使用 OptPNG 和 JPEGTran 對全部圖像作了優化。生成 AppCache 清單
。Yeoman 會爲你生成應用程序緩存的清單,你只須要構建項目就好。「殺手級」的構建過程
。你所作的工做不只被精簡到最少,讓你更加專一,爲你節省大量工做。集成的包管理
。Yeoman 讓你能夠經過命令行輕鬆地查找新的包,安裝並保持更新,而不須要你打開瀏覽器。對 ES6 模塊語法的支持
。你可使用最新的 ECMAScript 6 模塊語法來編寫模塊。這仍是一種實驗性的特性,它會被轉換成 ES5,從而你能夠在全部流行的瀏覽器中使用編寫的代碼。PhantomJS 單元測試
。你能夠經過 PhantomJS 輕鬆地運行單元測試。當你建立新的應用程序的時候,它還會爲你自動建立測試內容的骨架。一份完整的新手上路指南在這裏能夠找到,可是對於那些但願快速上手操練的傢伙,請肯定你已經安裝了 Node.js, Git。Ruby 和 Compass 是可選的(若是你想要使用Compass)。node
Node.js 版本要求爲 v0.10.x+,npm 版本要求爲 v2.1.0+,運行下面命令 檢查版本:jquery
$ node --version && npm --version
也能夠檢查 Git 版本:git
$ git --version
確保 Node 安裝以後,安裝 Yeoman 工具集:angularjs
$ npm install --global yo bower grunt-cli
運行下面命令檢查是否安裝成功:github
$ yo --version && bower --version && grunt --version 1.4.5 1.3.12 grunt-cli v0.1.13
Yeoman 生成器使用 npm 命令,如今可用的生成器數量已經超過了 1000+個生成器,這其中不少都是由開源社區編寫的。
你能夠安裝 web 應用的生成器
$ npm install -g generator-webapp
也能夠安裝 generator-angular 生成器:
$ npm install --global generator-angular
建立一個目錄用於做爲工程目錄:
$ mkdir mytodo && cd mytodo
你能夠查看全部的生成器:
$ yo ? 'Allo june! What would you like to do? Run a generator Angular Karma Webapp Mocha ────────────── Update your generators (Move up and down to reveal more choices)
運行 Angular 生成器,會提示你是否使用 Sass 和引入 Bootstrap,以及加載哪些 Angular 模塊:
$ yo angular _-----_ | | .--------------------------. |--(o)--| | Welcome to Yeoman, | `---------´ | ladies and gentlemen! | ( _´U`_ ) '--------------------------' /___A___\ | ~ | __'.___.'__ ´ ` |° ´ Y ` Out of the box I include Bootstrap and some AngularJS recommended modules. ? Would you like to use Sass (with Compass)? No ? Would you like to include Bootstrap? Yes ? Which modules would you like to include? angular-animate.js, angular-cookies.js, angular-resource.js, angular-route.js, angular-sanitize.js, angular-touch.js
選擇須要下載的模塊,而後回車。過一段時間以後,生成的目錄結構以下:
mytodo ├── Gruntfile.js ├── app │ ├── 404.html │ ├── favicon.ico │ ├── images │ │ └── yeoman.png │ ├── index.html │ ├── robots.txt │ ├── scripts │ │ ├── app.js │ │ └── controllers │ ├── styles │ │ └── main.css │ └── views │ ├── about.html │ └── main.html ├── bower.json ├── bower_components ├── package.json └── test ├── karma.conf.js └── spec └── controllers
示例中的全部 js 代碼都使用了嚴格模式,有關嚴格模式的內容能夠參考 http://www.waylau.com/javascript-use-strict-mode/
運行下面命令啓動服務:
$ grunt serve
瀏覽器訪問 ,你會看到:
打開 scripts/controllers/main.js ,代碼修改成:
'use strict'; angular.module('webApp').controller('MainCtrl', function ($scope) { $scope.todos = ['Item 1', 'Item 2', 'Item 3']; });
修改 views/main.html,將 todos 中的項目以 input 標籤形式輸出:
<div class="container"> <h2>My todos</h2> <p class="form-group" ng-repeat="todo in todos"> <input type="text" ng-model="todo" class="form-control"> </p> </div>
頁面會顯示以下:
首先,添加一個輸入框和添加按鈕,將 views/main.html 修改成:
<div class="container"> <h2>My todos</h2> <!-- Todos input --> <form role="form" ng-submit="addTodo()"> <div class="row"> <div class="input-group"> <input type="text" ng-model="todo" placeholder="What needs to be done?" class="form-control"> <span class="input-group-btn"> <input type="submit" class="btn btn-primary" value="Add"> </span> </div> </div> </form> <p></p> <!-- Todos list --> <p class="form-group" ng-repeat="todo in todos"> <input type="text" ng-model="todo" class="form-control"> </p> </div>
這時候,頁面內容以下:
修改 main.js 添加 addTodo() 事件:
'use strict'; angular.module('webApp') .controller('MainCtrl', function ($scope) { $scope.todos = ['Item 1', 'Item 2', 'Item 3']; $scope.addTodo = function () { $scope.todos.push($scope.todo); $scope.todo = ''; }; });
這樣,就完成了添加 todo 項的功能。
先在列表中每個 todo 項目的邊上加上一個移除按鈕,修改 views/main.html 中 Todos list
註釋部分的代碼爲:
<!-- Todos list --> <p class="input-group" ng-repeat="todo in todos"> <input type="text" ng-model="todo" class="form-control"> <span class="input-group-btn"> <button class="btn btn-danger" ng-click="removeTodo($index)" aria-label="Remove">X</button> </span> </p>
修改 main.js 添加 removeTodo($index)
事件:
'use strict'; angular.module('webApp') .controller('MainCtrl', function ($scope) { $scope.todos = ['Item 1', 'Item 2', 'Item 3']; $scope.addTodo = function () { $scope.todos.push($scope.todo); $scope.todo = ''; }; $scope.removeTodo = function (index) { $scope.todos.splice(index, 1); }; });
如今,刪除按鈕可以響應刪除事件了。雖然咱們能夠添加和移除 Todo 事項,可是這些記錄都不能永久地保存。一旦頁面被刷新了,更改的記錄都會不見了,又恢復到 main.js 中設置的todo 數組的值。
另外,上面添加 Todo 項時,若是重複添加相同的記錄,則後臺會報錯,這是由於腳本中沒有作校驗。
接下來,咱們安裝並引入 AngularUI Sortable 模塊,使得 Todo 事項能夠排序。這裏,咱們須要使用 bower 安裝 angular-ui-sortable 和 jquery-ui:
$ bower install --save angular-ui-sortable jquery-ui
添加參數 --save
能夠更新 bower.json 文件中關於 angular-ui-sortable 和 jquery-ui 的依賴,這樣你就不用手動去 bower.json 中更新依賴了。
再次啓動 grunt server:
$ grunt serve
爲了使用Sortable模塊,咱們須要在 scripts/app.js 中更新Angular 模塊,將 Sortable 能夠加載到咱們的應用中,更改前代碼, 將 ui.sortable 添加進數組中,以下:
angular.module('webApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.sortable' ])
最後,在 views/main.html 中,咱們須要將 ui-sortable
指令做爲一個 div 將 ng-repeat
層包起來。
<!-- Todos list --> <div ui-sortable ng-model="todos"> <p class="input-group" ng-repeat="todo in todos">
添加一些內聯的 CSS,將鼠標顯示爲 「可移動」 樣式來告訴用戶這些 todo 項是能夠移動的:
<p class="input-group" ng-repeat="todo in todos" style="padding:5px 10px; cursor: move;">
完整代碼以下:
<!-- Todos list --> <div ui-sortable ng-model="todos"> <p class="input-group" ng-repeat="todo in todos" style="padding:5px 10px; cursor: move;"> <input type="text" ng-model="todo" class="form-control"> <span class="input-group-btn"> <button class="btn btn-danger" ng-click="removeTodo($index)" aria-label="Remove">X</button> </span> </p> </div>
服務瀏覽器,咱們就能夠對 Todo 事項進行拖拽排序了。
以前項目的數據,當瀏覽器刷新後就不會保存了。咱們能夠安裝 Angular 模塊 angular-local-storage,快速實現本地存儲。
下載依賴:
$ bower install --save angular-local-storage
編輯 scripts/app.js 添加 LocalStorageModule的 適配器:
angular .module('webApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.sortable', 'LocalStorageModule' ])
同時也要配置 localStorageServiceProvider,用 ls 做爲 localStorage名稱前綴:
.config(['localStorageServiceProvider', function(localStorageServiceProvider){ localStorageServiceProvider.setPrefix('ls'); }])
完整的 scripts/app.js 文件:
'use strict'; angular .module('webApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.sortable', 'LocalStorageModule' ]).config(['localStorageServiceProvider', function(localStorageServiceProvider){ localStorageServiceProvider.setPrefix('ls'); }]).config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }) .when('/about', { templateUrl: 'views/about.html', controller: 'AboutCtrl' }) .otherwise({ redirectTo: '/' }); });
而後,須要修改 scripts/controllers/main.js ,改成從本地存儲訪問數據:
'use strict'; angular.module('webApp').controller('MainCtrl', function ($scope, localStorageService) { // 初始化時爲空 var todosInStore = localStorageService.get('todos'); $scope.todos = todosInStore && todosInStore.split('\n') || []; // 監聽變化 $scope.$watch('todos', function () { localStorageService.add('todos', $scope.todos.join('\n')); }, true); $scope.addTodo = function () { $scope.todos.push($scope.todo); $scope.todo = ''; }; $scope.removeTodo = function (index) { $scope.todos.splice(index, 1); }; });
在瀏覽器中查看應用,你會發現 todo 列表中沒有任何東西。由於這個應用從本地存儲中讀取了 todo 數組,而本地存儲中尚未任何 todo 項。
在添加一些項目到列表後,咱們再次刷新咱們的瀏覽器的時候,這些項目都還在。
Karma 是一個 JS 測試框架。Angular 生成器自己已經包括了兩個測試框架:ngScenario 和 Jasmine。當以前咱們運行 yo angular
的時候,在 mytodo 文件夾下會生成了一個 test 目錄,還有一個 karma.conf.js 文件,它會被放入在 Node 模塊中以使用 Karma。咱們將會編輯一個 Jasmine 腳原本完成咱們的測試。如今先來看看要怎麼進行測試。
先安裝依賴:
$ npm install -g phantomjs $ npm install grunt-karma --save-dev
首先,修改 karma.conf.js,添加
'bower_components/jquery/dist/jquery.js', 'bower_components/jquery-ui/ui/jquery-ui.js', 'bower_components/angular-ui-sortable/sortable.js',
最終的樣子是:
files: [ 'bower_components/angular/angular.js', 'bower_components/angular-mocks/angular-mocks.js', 'bower_components/angular-animate/angular-animate.js', 'bower_components/angular-cookies/angular-cookies.js', 'bower_components/angular-resource/angular-resource.js', 'bower_components/angular-route/angular-route.js', 'bower_components/angular-sanitize/angular-sanitize.js', 'bower_components/angular-touch/angular-touch.js', 'bower_components/jquery/dist/jquery.js', 'bower_components/jquery-ui/ui/jquery-ui.js', 'bower_components/angular-ui-sortable/sortable.js', 'app/scripts/**/*.js', 'test/mock/**/*.js', 'test/spec/**/*.js' ],
如今回到命令行結束 grunt server 的進程(使用 Ctrl+c
)。在 Gruntfile.js 中已經有了用於運行測試的 grunt 任務,能夠直接像下面這樣運行:
$ grunt test
修改 test/spec/controllers/main.js 以下:
'use strict'; describe('Controller: MainCtrl', function () { // load the controller's module beforeEach(module('webApp')); var MainCtrl, scope; // Initialize the controller and a mock scope beforeEach(inject(function ($controller, $rootScope) { scope = $rootScope.$new(); MainCtrl = $controller('MainCtrl', { $scope: scope }); })); it('should attach a list of awesomeThings to the scope', function () { expect(scope.awesomeThings.length).toBe(3); }); it('should add items to the list', function () { scope.todo = 'Test 1'; scope.addTodo(); expect(scope.todos.length).toBe(4); }); it('should add then remove an item from the list', function () { scope.todo = 'Test 1'; scope.addTodo(); scope.removeTodo(0); expect(scope.todos.length).toBe(2); }); });
更多有關單元測試的內容,請參考 Unit Testing Best Practices in AngularJS。
爲了將應用發佈爲產品版本,還須要作不少工做:
實現上述目標只需一句:
$ grunt
這個命令將會完成 Grunt 的任務以及根據 Gruntfile.js 文件進行配置,建立一個能夠運行的應用版本。只需等上一分鐘,你就能獲得一個完整的編譯版本,和一份編譯過程耗時的報告。
編譯完成後的文件,放在了 dist 目錄下,是一個能夠拿去服務器上的部署的真正的產品。
你也能夠運行下面命令自動編譯項目,而且啓動 web 服務器
$ grunt serve:dist
Anugular 生成器也支持建立新的視圖、指令和控制器。例如:能夠經過運行 yo angular:route routeName
搭建一個新的控制器,同時在 app.js 中的路由也會被更新。
瞭解更多有關於 Angular 生成器的 Yeoman 命令,請查看 generator readme。
固然,Yeoman 還能夠作更多的事情,它還支持其餘框架的腳手架。
除了 Yeoman 以外,還有幾個框架能夠生產 Angular 項目,請參考 5 Angular JS Seeds & Bootstrap Apps