前端開發環境搭建 Grunt Bower、Requirejs 、 Angular

如今web開發的趨勢是先後端分離。前端採用某些js框架,後端採用某些語言提供restful API,二者以json格式進行數據交互。javascript

若是後端採用node.js,則先後端可使用同一種語言,共享某些可重用的Js代碼,並共享構建工具。但不少時候咱們可能採用別的語言,如ruby/java/scala等,此時先後端代碼基本上是徹底獨立的。雖然你們都在同一個項目中,但能夠分紅互相獨立的兩塊,而且先後端一般使用不一樣的構建工具。css

好比當後端使用Scala時,咱們會使用sbt進行項目構建,對scala代碼進行編譯、測試、打包等。它的專長是處理與scala相關的任務,但對於前端的支持比較弱。前端一些常見的任務,如js庫的下載和管理、css文件的轉換、js文件合併壓縮、js測試的執行等,很難在sbt中找到好用的插件,而利用js世界裏的工具來作反而更加方便一些。html

咱們項目組這幾天正在討論是否在項目中引入一些前端框架,仍是直接用原生Javascript寫。通過反覆討論和調研,最終決定引入AngularJs。但AngularJs的引入並非單一的任務,由於咱們還須要考慮前端代碼的測試、依賴管理等,都須要有相應的工具支持,因此最後引入了這麼一整套工具:前端

  1. Grunt – Js任務管理工具,經過各類插件對項目進行各類操做,好比文件轉換、運行測試、打包部署等。至關於java裏的ant/maven/gradle,ruby中的rack,scala中的sbt。
  2. Bower – Js庫依賴管理工具。當你須要jquery時,不須要手動下載,只須要執行bower install jquery
  3. RequireJs – Js庫加載管理,及模塊化支持。能夠按需及並行加載js庫,能夠把咱們的代碼以模塊化的方式組織。
  4. AngularJs – Js前端框架,支持依賴注入,雙向綁定等我認爲很重要的功能

這套東西都是比較基礎且使用比較普遍的。通常一旦在項目中引入前端框架,或者須要寫比較多的Js代碼時,咱們都會採用它們,因此頗有必要學習並掌握它們。java

各工具都至關的獨立

在開始前,須要先提示一下,在javascript的世界裏,不少東西都是由社區提供的,因此每一種工具都至關獨立。好比,不少工具都有着本身獨立的配置文件,本身的命令行參數,有時候還須要有一些額外的插件把兩個工具結合起來。node

因此下面將會有不少比較瑣碎的命令,咱們須要一一瞭解。不過好在咱們一旦瞭解了,下次就可使用已經配置好的文件,經過幾條命令將把有的東西都準備好,很方便。python

安裝nodejs

在Mac中,咱們可使用brew來安裝。在其它系統下,請使用相應的工具或直接到官網下載。jquery

brew install node

Nodejs可讓咱們在服務器端使用javascript編程,它是不少js工具的基礎。若是你已經安裝,請確保使用最新版本:git

brew upgrade node

查看版本:angularjs

node -v

我這裏顯示:

v0.10.28

npm

Npm是node官方提供的包依賴管理工具。咱們下面使用的grunt等,都是以插件形式下載安裝的。

當咱們安裝好nodejs後,npm就自動可用了。

查看版本:

npm -v

我這裏顯示:

2.0.0-alpha-5

建立項目目錄

下面咱們從零開始,首先在任意位置新建一個目錄做爲咱們的項目根目錄,好比:

mkdir ~/myproject

而後進入該目錄:

cd ~/myproject

後面的命令都將在項目根目錄下操做。

爲npm建立package.json

首先咱們須要爲npm提供一個package.json,告訴它咱們的項目信息,特別是項目中將會使用的插件。咱們不須要手動建立,由於能夠直接調用如下命令:

npm init

它會問咱們一些問題,咱們能夠按需回答,也能夠所有使用默認值,反正之後能夠改起來也很容易。

最後將會產生以下的package.json文件:

{ "name": "grunt-bower-angular-demo", "version": "0.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "https://github.com/freewind/grunt-bower-angular-demo.git" }, "author": "", "license": "BSD", "bugs": { "url": "https://github.com/freewind/grunt-bower-angular-demo/issues" } }

對於像咱們這樣的非nodejs項目來講,裏面的大部份內容都沒用,能夠刪掉大部分,只剩下:

{ "name": "grunt-bower-angular-demo", "version": "0.0.0" }

安裝 grunt

npm install grunt --save-dev

將使用npm下載grunt插件,它們將保存到項目根目錄下的node_components目錄下。

後面的--save-dev參數是說,把這個插件信息,同時添加到package.jsondevDependencies中:

"devDependencies": { "grunt": "~0.4.5" }

因爲grunt僅在開發階段使用,因此使用--save-dev。若是是運行時使用的,則用--save

安裝 grunt-cli

上面安裝的grunt並不包含命令行工具,咱們還需安裝相應的grunt-cli,才能在命令行中調用grunt命令:

npm install grunt-cli -g

後面的-g是說,把grunt-cli安裝成全局工具,以便在任意目錄下使用。

安裝後,輸入:

grunt --version

我這裏顯示爲:

grunt-cli v0.1.13 grunt v0.4.5

在比較少的狀況下,可能提示找不到grunt,則須要根據安裝grunt-cli時的提示信息,把相應的路徑添加到PATH中:

echo PATH=$PATH:/your/path/to/grunt >> ~/.bashrc source ~/.bashrc

爲grunt建立配置文件Gruntfile.js

安裝grunt-init

npm install grunt-init -g

下載grunt模板

git clone https://github.com/gruntjs/grunt-init-gruntfile.git ~/.grunt-init/gruntfile

生成Gruntfile

grunt-init gruntfile

根據須要回答問題,或者使用默認值,將獲得如下Gruntfile.js文件:

/*global module:false*/ module.exports = function(grunt) { // Project configuration. grunt.initConfig({ // Metadata. pkg: grunt.file.readJSON('package.json'), banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n', // Task configuration. concat: { options: { banner: '<%= banner %>', stripBanners: true }, dist: { src: ['lib/<%= pkg.name %>.js'], dest: 'dist/<%= pkg.name %>.js' } }, uglify: { options: { banner: '<%= banner %>' }, dist: { src: '<%= concat.dist.dest %>', dest: 'dist/<%= pkg.name %>.min.js' } }, jshint: { options: { curly: true, eqeqeq: true, immed: true, latedef: true, newcap: true, noarg: true, sub: true, undef: true, unused: true, boss: true, eqnull: true, browser: true, globals: { jQuery: true } }, gruntfile: { src: 'Gruntfile.js' }, lib_test: { src: ['lib/**/*.js', 'test/**/*.js'] } }, qunit: { files: ['test/**/*.html'] }, watch: { gruntfile: { files: '<%= jshint.gruntfile.src %>', tasks: ['jshint:gruntfile'] }, lib_test: { files: '<%= jshint.lib_test.src %>', tasks: ['jshint:lib_test', 'qunit'] } } }); // These plugins provide necessary tasks. grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-watch'); // Default task. grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']); };

它裏面已經包含了一些經常使用的插件,好比grunt-contrib-jshint等,咱們可根據須要刪減一些用不上的。

它同時還會在package.json裏添加上這些插件的依賴:

"grunt-contrib-concat": "~0.4.0", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-qunit": "~0.5.2", "grunt-contrib-uglify": "~0.5.0", "grunt-contrib-watch": "~0.6.1"

這些插件還未下載,若是須要,能夠運行:

npm install

把它們下載到本地

bower

npm install bower -g

package.json

{ "engines": { "node": ">= 0.10.0" }, "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-watch": "~0.6.1", "grunt-contrib-qunit": "~0.5.2", "grunt-contrib-concat": "~0.4.0", "grunt-contrib-uglify": "~0.5.0" } }

安裝bower

bower跟npm在某種意義上類似,它是用來管理經常使用的js庫的依賴的,好比jquery, underscore, angularjs等。

咱們能夠經過npm安裝它:

npm install bower -g

把它裝爲全局工具

爲bower生成配置文件bower.json

bower也有它本身的配置文件bower.json,咱們不須要手動建立。

bower init

將會生成以下的bower.json:

{ "name": "grunt-bower-angular-demo", "version": "0.0.0", "homepage": "https://github.com/freewind/grunt-bower-angular-demo", "authors": [ "Peng Li <nowind_lee@qq.com>" ], "license": "MIT", "ignore": [ "**/.*", "node_modules", "bower_components", "test", "tests" ] }

對於咱們的項目來講,裏面的東西基本上都沒用。有用的是後面將會出現的dependencies

下載requirejs、jquery、angularjs

bower insall requirejs --save bower insall jquery --save bower install angularjs --save

將會自動下載jquery到angularjs相應的文件,到項目根目錄下的bower_components目錄。並在bower.json中添加:

"dependencies": { "angularjs": "~1.2.20", "jquery": "~2.1.1", "requirejs": "~2.1.14" }

安裝grunt-bower-task

bower只負責把依賴下載到本地的bower_components目錄,並不負責把它們拷貝到咱們項目中實際使用的地方,好比public/js/lib目錄下。

爲了實現這樣的功能,咱們還須要另外一個插件的幫助:

npm install grunt-bower-task --save-dev

而後打開其文檔:https://www.npmjs.org/package/grunt-bower-task ,按照上面的提示進行配置。

首先在Gruntfile中合適位置添加:

grunt.loadNpmTasks('grunt-bower-task');

而後在grunt.initConfig({...})參數中,添加相應的配置項:

bower: { install: { options: { targetDir: './public/js/lib', layout: 'byComponent', install: true, verbose: false, cleanTargetDir: false, cleanBowerDir: false, bowerOptions: {} } } }

這裏指定拷貝的目標目錄爲public/js/lib,且文件按照模塊分紅單個目錄(byComponent)。若是想把全部的js放在同一個目錄,全部的css文件放在同一個目錄,則使用byType

關於RequireJs

在前面咱們已經使用bower安裝了requirejs:

bower install requirejs

RequireJs可用來管理頁面中使用的js庫之間的依賴關係,能夠按需、並行、延遲加載js庫。同時它可讓咱們以模塊化的形式組織js代碼。

強烈建議先了解RequireJs的運行原理再動手寫代碼,否則確定會遇到各類坑。RequireJs的文檔寫得有點繞,可參考個人另外一篇文章:TODO

配置RequireJs

前面咱們第三方的依賴,經過grunt-bower-task拷貝到了public/js/lib目錄下。咱們本身寫的js,將會放置在public/js目錄下。

咱們須要手動建立一個config.js文件,用來配置和初始化requirejs。

在HTML中引入requirejs

若是咱們使用了requirejs,則在HTML中,咱們一般只須要一個<script src="http://freewind.me/blog/20140727/..."></script>標籤引入requirejs並指定入口文件便可,而不須要寫多個script標籤手動加載其它js文件。

在HTML中合適位置加入:

<script src="http://freewind.me/public/js/lib/requirejs/require.js" data-main="/public/js/config.js"></script>

這裏首先加載了require.js,並經過data-main屬性告訴requirejs:當你加載完之後,請加載config.js文件進行初始化。

config.js

config.js內容以下:

requirejs.config({ baseUrl: '/public/js', paths: { app: 'app', jquery: 'lib/jquery/jquery', angular: 'lib/angularjs/angular' }, shim: { } }); requirejs(['app'], function(app) { app.hello(); });

咱們在paths中聲明瞭幾個模塊,其中的app是咱們本身建立的js文件,用於放咱們本身的業務代碼,它對應於/public/js/app.jsjqueryangular對應的文件是咱們使用grunt-bower-task拷貝過來的第三方js庫。

shim中用來處理一些沒有遵照requirejs規範的js庫,好比underscore之類。可在裏面對它們進行一些依賴聲明、初始化操做等。這裏暫時用不上。

最後用requirejs來導入咱們本身的模塊,可在後面的callback中拿到對應模塊的實例,並對它進行一些操做,好比咱們調用了app.hello()方法。

app.js

爲了讓這個例子完整,咱們能夠定義相應的app.js:

define([], function() { return { hello: function() { alert("hello, requirejs"); } } });

index.html

爲了能讓例子跑起來,咱們還須要建立一個public/index.html,內容以下:

<html> <head> <script src="http://freewind.me/public/js/lib/requirejs/require.js" data-main="/public/js/config.js"></script> </head> <body> <div>Hello, world!</div> </body> </html>

啓動 web server

進入項目根目錄,運行:

grunt bower

把bower下載的js庫拷貝到public/js/lib下。

而後啓動web server:

python -m SimpleHTTPServer

最後打開瀏覽器,訪問:

http://localhost:8000/public/index.html

若是一切正常的話,會看到彈出一個提示框,上面內容爲:

hello, requirejs

Angularjs

而後咱們作一個簡單的angular的例子。

因爲angularjs並非按requirejs的模塊方式組織代碼的,咱們須要在config.js中添加:

shim: { angular : { exports : 'angular'} }

Angularjs會在全局域中添加一個名爲angular的變量。咱們必須在shim中顯式把它暴露出來,才能經過模塊注入的方式使用它,好比:

define(['angular'], function(ng) { // we can use argument `ng` instead of gloabl `angular` now });

在index.html中添加angular代碼

<div ng-controller="MyController"> <input type="text" ng-model="name" /> <span>{{name}}</span> </div>

準備相應的controller

app.js的內容改成:

define(['angular'], function(angular) { angular.module('myApp', []) .controller('MyController', ['$scope', function ($scope) { $scope.name = 'Change the name'; }]); angular.element(document).ready(function() { angular.bootstrap(document, ['myApp']); }); });

在這段代碼裏,我定義了一個angularjs本身的模塊myApp,以及相應的MyController。在後面,經過angular.bootstrap方法,把該模塊與document結合在了一塊兒。

啓動web server,就能夠看到效果了。當咱們修改了頁面上輸入框裏的內容,它旁邊的文字也會跟着改變。

修改angularjs的佔位符

在html中顯示angularjs裏的一個字段時,咱們使用{{}}來佔位,好比:

<span>{{name}}</span>

若是咱們同時使用了mustcahe模板,就會有衝突。咱們能夠更改angularjs的配置:

angular.module('myApp', []).config(function($interpolateProvider){ $interpolateProvider.startSymbol('[[').endSymbol(']]'); } );

而後咱們就能夠寫成:

<span>[[name]]</span>

了.

項目代碼

上面的操做,都在這個項目中: https://github.com/freewind/grunt-bower-angular-demo

另外,關於requirejs/angularjs的結合使用,能夠參看這個比較好的樣板項目: https://github.com/tnajdek/angular-requirejs-seed

相關文章
相關標籤/搜索