1. 程式人生 > >Grunt+Bower基礎教程,入門篇

Grunt+Bower基礎教程,入門篇

Grunt+Bower的簡單應用

前言

     首先要感謝那些知名的不知名的前輩們,你們的成就是我們進步的基礎。

    本文針對的讀者是那些像之前的我一樣剛剛瞭解Grunt和Bower這兩個名字是什麼,但還不知道究竟是幹什麼的,同樣是以應用為主,已經會基本使用這些的就不需要看了,因為都是最基礎的一些東西,同樣如果您看了之後發現有什麼不符合邏輯或常識的問題,或是有什麼錯誤,我會非常期待您的指正。

1.安裝nodeJS

    grunt以及其外掛都是需要依賴nodejs來執行的,所以如果你的電腦中並沒有安裝,那麼需要安裝nodejs,安裝過程極其簡單,就是傻瓜式的下一步直到install即可

這是官網開啟以後的圖,我們這裡安裝左邊的就可以了。

安裝完成以後,win+r cmd  開啟命令提示符視窗,輸入node -v檢視版本號,以驗證nodejs是否安裝成功

2.安裝grunt-CLI

這裡就與傳統的安裝軟體方式不同了,以後安裝的一些外掛基本都是使用這樣的方式安裝的,所以先不用問這是什麼東西,用的時間長了就明白是個什麼東西了

首先使用nodejs的npm install方式安裝grunt-CLI ,很簡單,就是在命令列裡輸入npm install -g grunt-cli 然後回車鍵


分析一下這句安裝命令分別代表什麼:

npm install :nodejs的安裝外掛方式

-g:全域性安裝

grunt-cli:外掛名

確保電腦聯網且網足夠快

如果安裝成功的話會出現grunt-cli的目錄結構,安裝失敗找出原因重新安裝即可,成功後類似這樣:

進行驗證看是否安裝成功:

命令列輸入grunt 回車鍵,證明grunt-cli安裝成功

grunt-cli到這裡基本上就安裝完成了,接下來建立一個自己的前端專案吧。

3.構建專案目錄結構

這裡可以1.自己先建立一個簡單的進行練手,2.也可以學習以下yoman這類可以直接構建目錄結構的工具(npm install -g yo),3.或者是參考一些優秀的前端工程目錄結構。

這裡用一個簡單的例子做練手,更加方便練習,但如果想要更加專業化,還是參考上邊2、3方法

在D盤或者你的任意目錄下建立一個資料夾,我的是D:\1Project Workspace\New_Test_Project,然後在這個資料夾中建立需要的資料夾和檔案

接下來要建立一個名叫package.json的檔案,有兩種建立方式:

1直接建立文字並儲存為json檔案,內容為:

{
  "name": "new_test_project",
  "version": "1.0.0",
  "description": "test",
  "main": "index.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "ds",
  "license": "ISC"
}

其中左邊的名稱是不可以更改的,右邊的一些相當於引數的東西是可以進行更改的。

2.(推薦)在當前也就是D:\1Project Workspace\New_Test_Project這個目錄下shift+右鍵開啟命令列,輸入npm init,回車鍵然後按照所需資訊一步一步填寫下來,專案名必須都是小寫字母,版本號、簡介等都可以不填寫,一路回車下來,最後輸入yes,就會發現這個檔案已經建立好了:


4.安裝grunt

接下來就是正主grunt的安裝了,這裡首先介紹一下更改npm下載源的方法,網足夠好的可以跳過4.1的步驟接著往下看

4.1將下載源從國外改到淘寶

由於國外網路受網路波動影響大,時常導致下載失敗,所以我們的淘寶團隊將這些國外的映象到了國內。

官方:這是一個完整 npmjs.org 映象,你可以用此代替官方版本(只讀),同步頻率目前為 10分鐘 一次以保證儘量與官方服務同步。

執行:npm install cnpm -g --registry=https://registry.npm.taobao.org;  注意:安裝完後最好檢視其版本號cnpm -v或關閉命令提示符重新開啟,安裝完直接使用有可能會出現錯誤;

注:cnpm跟npm用法完全一致,只是在執行命令時將npm改為cnpm(以下操作將以cnpm代替npm)。

4.2正式安裝

執行安裝命令之前看一下4.1的最後一句話。

在剛才建立的專案目錄中開啟命令提示符,執行:cnpm install grunt --save-dev

命令分析:

cnpm install: npm方式安裝,用淘寶資料來源

grunt:我們要安裝外掛的名字

--save-dev: 在當前目錄安裝grunt的同時,順便把grunt儲存為這個目錄的開發依賴項,執行後開啟package.json後就可已發現新增加了開發依賴項grunt

小tips:這裡的名字和--save-dev是可以更換的,不會影響到執行結果,以後類似的命令同樣適用,例如本次命令用cnpm install --save-dev grunt 執行的效果是相同的


首次安裝:會出現目錄結構


如果目錄中多了node_modules資料夾,說明安裝成功了

這時開啟package.json檔案,就會發現多了一些程式碼

而其中devDependencies的意思就是

然後新建一個名叫Gruntfile.js的檔案在專案根目錄下,它的作用是用來將我們需要配置的任務(Task)寫到裡邊去執行的,所以先建立一個空檔案

 這裡要注意的是Gruntfile.js的G是大寫,其它小寫

經過以上幾個步驟,我們可以認為grunt已經安裝成功了,並且分析以上提示:Task ‘default’ not found。 說明我們該配置任務(Task)了,也就是在Gruntfile.js檔案中寫一些任務

5.配置Gruntfile.js(寫Task)

開啟Gruntfile.js輸入以下官方規定的資訊,這個指令碼檔案的規範就是這樣的,所以沒有為什麼。

看原始碼,我們已經讀取了package.json檔案中的資訊

module.exports = function(grunt){

		grunt.initConfig({
			pkg: grunt.file.readJSON('package.json'),
			//這裡要寫之後的任務
		});

		//default任務,即預設任務,執行命令為grunt或grunt default
		grunt.registerTask('default',[]);


		//這是之後配置的稍複雜的任務,這裡我們先註釋掉,稍後解釋。
		//grunt.registerTask('import',['wiredep']);
		//grunt.registerTask('package', ['copy:js','useminPrepare','concat:dist','uglify:dist','usemin']);
		//grunt.registerTask('start',['connect','watch:start']);
};
這裡我們配置好了一個叫default(預設)的任務,它的任務列表,也就是右邊的陣列是空的,所以它可以啟動但是不執行什麼任務,這裡我們執行這個任務的方式就是在命令提示符中輸入grunt grunt default,可以得到如下結果

同時我們再回去看一眼原始碼,其它註釋掉但有內容的執行方式分別是:grunt import ; grunt package ; grunt start。而其後邊的陣列中就是它依次要去執行的任務,那這些任務是如何配置的呢,接下來就一一介紹

6.寫Task(grunt常用外掛介紹)

這裡要用到的就是grunt的外掛了,這些外掛都是從官網被稽核後才能上架下載的,當然我們不需要去官網再艾格尋找下載,用我們的npm方式安裝即可,但有興趣的依然可以去官網看一眼

外掛分為兩類。第一類是grunt團隊貢獻的外掛,這些外掛的名字前面都帶有“contrib-”字首,而且在外掛列表中有星號標註。第二類是第三方提供的外掛,不帶有這兩個特徵。

並不是所有的外掛都需要被用到,這裡我們只去介紹一些我們用到的,常用的,並且每個外掛配置的不同,其用法也不盡相同:

  • grunt-contrib-uglify——壓縮javascript程式碼
  • grunt-contrib-jshint——javascript語法錯誤檢查
  • grunt-contrib-watch——實時監控檔案變化、呼叫相應的任務重新執行
  • grunt-wiredep——bower+grunt-wiredep依賴庫自動注入(自動將bower下載的包匯入html中)
  • grunt-contrib-connect——可配置一個web server伺服器
  • grunt-usemin——根據註釋替換到 CSS/JS 等資源引用(將原本引用的js、css自動改成釋出版本的合併後的js、css)
  • grunt-contrib-copy——複製檔案,從一個資料夾複製到另一個資料夾
  • grunt-contrib-concat——合併多個檔案的程式碼到一個檔案中(合併js,css)

接下來會大致講解以下這些外掛的用法,但不會詳細介紹,只是應用,官網中還有許多更加優秀實用的外掛,可以自行查詢使用

先從應用的角度來看,我們先講connect外掛和watch外掛,有了這兩個之後,我們的前端開發就可以這邊儲存,瀏覽器中自動重新整理看效果了

6.1grunt-contrib-connec

這個外掛的作用是配置一個web server伺服器,這樣我們的前端用記事本都能開發了,這裡推薦用IDE:WebStorm開發前端,因為它可以將命令提示符和grunt整合到開發工具中,用起來很方便,這裡不細說了,以下為配置詳情:

安裝方法:命令提示符輸入 cnpm install grunt-contrib-connect --save-dev


同以前一樣,我們將這個配置儲存到我們的package.json中


安裝完成,下面介紹用法:開啟Gruntfile.js修改一些配置

module.exports = function(grunt){

	 // LiveReload的預設埠號,你也可以改成你想要的埠號
	var lrPort = 35729;
	var serveStatic = require('serve-static');
	var serveIndex = require('serve-index')
	 // 使用connect-livereload模組,生成一個與LiveReload指令碼
	 // <script src="http://127.0.0.1:35729/livereload.js?snipver=1" type="text/javascript"></script>
	 var lrSnippet = require('connect-livereload')({ port: lrPort });
	 // 使用 middleware(中介軟體),就必須關閉 LiveReload 的瀏覽器外掛
	var lrMiddleware = function(connect, options, middlwares) {
	  return [
	    lrSnippet,
	    // 靜態檔案伺服器的路徑 原先寫法:connect.static(options.base[0])
	    serveStatic(options.base[0]),
	    // 啟用目錄瀏覽(相當於IIS中的目錄瀏覽) 原先寫法:connect.directory(options.base[0])
	    serveIndex(options.base[0])
	  ];
	};

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		//這裡要寫之後的任務
		
		//connect配置,自動載入web server伺服器
		connect: {
                options: {
                    protocol: 'http',
                    port: 8081,
                    hostname: '*',
                    open:true,
					/*keepalive: true,*/
                    base: ['./']
                },
                livereload: {
				options: {
				// 通過LiveReload指令碼,讓頁面重新載入。
				middleware: lrMiddleware
				}
			}
    	},
	});

	//引入外掛
	grunt.loadNpmTasks('grunt-contrib-connect');


	//default任務,即預設任務,執行命令為grunt或grunt default
	grunt.registerTask('default',['connect']);

	//兩個任務名字不同可同時存在,執行時只要輸入grunt+名字即可,如下:grunt start
	grunt.registerTask('start',['connect']);


	//這是之後配置的稍複雜的任務,這裡我們先註釋掉,稍後解釋。
	//grunt.registerTask('import',['wiredep']);
	//grunt.registerTask('package', ['copy:js','useminPrepare','concat:dist','uglify:dist','usemin']);
	//grunt.registerTask('start',['connect','watch:start']);
};
task配置完成,程式碼中也註釋了語句分別是什麼,然後我們執行一下任務

伺服器配置成功,當然這時實時修改檔案並不能直接讓瀏覽器重新整理,我們還需要一個監聽外掛,即grunt-contrib-watch

6.2grunt-contrib-watch

作用:實時監控檔案變化、呼叫相應的任務重新執行,即配置檔案的監聽,在檔案有變動時候執行task

安裝方法:命令提示符輸入 cnpm install grunt-contrib-watch --save-dev

安裝具體過程同上就不具體說了,不同的地方就是需要配置新的任務,直接給出配置後的Gruntfile.js詳情

module.exports = function(grunt){

	 // LiveReload的預設埠號,你也可以改成你想要的埠號
	var lrPort = 35729;
	var serveStatic = require('serve-static');
	var serveIndex = require('serve-index')
	 // 使用connect-livereload模組,生成一個與LiveReload指令碼
	 // <script src="http://127.0.0.1:35729/livereload.js?snipver=1" type="text/javascript"></script>
	 var lrSnippet = require('connect-livereload')({ port: lrPort });
	 // 使用 middleware(中介軟體),就必須關閉 LiveReload 的瀏覽器外掛
	var lrMiddleware = function(connect, options, middlwares) {
	  return [
	    lrSnippet,
	    // 靜態檔案伺服器的路徑 原先寫法:connect.static(options.base[0])
	    serveStatic(options.base[0]),
	    // 啟用目錄瀏覽(相當於IIS中的目錄瀏覽) 原先寫法:connect.directory(options.base[0])
	    serveIndex(options.base[0])
	  ];
	};

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		//這裡要寫之後的任務
		
		//connect配置,自動載入web server伺服器
		connect: {
                options: {
                    protocol: 'http',
                    port: 8081,
                    hostname: '*',
                    open:true,
					/*keepalive: true,*/
                    base: ['./']
                },
                livereload: {
				options: {
				// 通過LiveReload指令碼,讓頁面重新載入。
				middleware: lrMiddleware
				}
			}
    	},
    	//watch的配置(監聽器)
    	watch:{
	        	start:{
	        		files: ['*.html', 'css/*', 'js/*', 'images/**/*','dist/*','src/*','src/js/*'],
				    options: {
				    	livereload: lrPort
				    }
	        	}
	        },
	});

	//引入外掛
	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-watch');


	//default任務,即預設任務,執行命令為grunt或grunt default
	grunt.registerTask('default',['connect']);

	//兩個任務名字不同可同時存在,執行時只要輸入grunt+名字即可,如下:grunt start
	grunt.registerTask('start',['connect','watch:start']);


	//這是之後配置的稍複雜的任務,這裡我們先註釋掉,稍後解釋。
	//grunt.registerTask('import',['wiredep']);
	//grunt.registerTask('package', ['copy:js','useminPrepare','concat:dist','uglify:dist','usemin']);
	//grunt.registerTask('start',['connect','watch:start']);
};

然後命令列執行task:grunt start

可以直接自動開啟瀏覽器,並且進入到伺服器的資料夾中,說明本地的資料夾已經放到伺服器上,可以進行訪問了

設定好對應檔案的監聽之後,我們可以看到當檔案進行修改之後,會生成如下日誌,並自動重新整理頁面

6.3常用外掛配置介紹

本文中所有任務Gruntfile.js原始碼及講解:

module.exports = function(grunt){

 // LiveReload的預設埠號,你也可以改成你想要的埠號
var lrPort = 35729;
var serveStatic = require('serve-static');
var serveIndex = require('serve-index')
 // 使用connect-livereload模組,生成一個與LiveReload指令碼
 // <script src="http://127.0.0.1:35729/livereload.js?snipver=1" type="text/javascript"></script>
 var lrSnippet = require('connect-livereload')({ port: lrPort });
 // 使用 middleware(中介軟體),就必須關閉 LiveReload 的瀏覽器外掛
var lrMiddleware = function(connect, options, middlwares) {
  return [
    lrSnippet,
    // 靜態檔案伺服器的路徑 原先寫法:connect.static(options.base[0])
    serveStatic(options.base[0]),
    // 啟用目錄瀏覽(相當於IIS中的目錄瀏覽) 原先寫法:connect.directory(options.base[0])
    serveIndex(options.base[0])
  ];
};

		grunt.initConfig({
			pkg: grunt.file.readJSON('package.json'),
			//uglify的配置(js壓縮)
			uglify: {
	            options: {
	                // 此處定義的banner註釋將插入到輸出檔案的頂部
                    mangle: false, //不混淆變數名
                    preserveComments: 'some', //不刪除註釋,還可以為 false(刪除全部註釋),some(保留@preserve @license @cc_on等註釋
					banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
	            },
	            dist: {
                    options: {
                        report: "min",//輸出壓縮率,可選的值有 false(不輸出資訊),gzip
					},
	                files: {
	                    //uglify會自動壓縮concat任務中生成的檔案
	                    'dist/js/app.min.js': ['dist/js/app.js']
	                }
	            }
	        },
	        //jshint的配置(程式碼校驗)
	        jshint:{
	        	build:['src/js/test.js'],
	        	options:{
	        		//這裡是覆蓋JSHint預設配置的選項
                	globals: {
                    jQuery: true,
                    console: true,
                    module: true,
                    document: true
                	}
	        	}
	        },
	        //watch的配置(監聽器)
	        watch:{
	        	build:{
	        		files:['src/*.js'],
	        		tasks:['jshint','uglify'],
	        		options:{spawn:false}
	        	},
	        	start:{
	        		files: ['*.html', 'css/*', 'js/*', 'images/**/*','dist/*','src/*','src/js/*'],
				    options: {
				    	livereload: lrPort
				    }
	        	}
	        },
	        //wiredep的配置(自動將bower下載的包匯入html中)
	        wiredep: {
				target: {
					src: ['src/*.html'],
					directory:"js/libs"
				}
			},
			//connect配置,自動載入web server伺服器
			connect: {
	                options: {
	                    protocol: 'http',
	                    port: 8081,
	                    hostname: '*',
	                    open:true,
						/*keepalive: true,*/
	                    base: ['./']
	                },
	                livereload: {
					options: {
					// 通過LiveReload指令碼,讓頁面重新載入。
					middleware: lrMiddleware
					}
				}
        	},


        	useminPrepare: {
				html: 'src/*.html',
					options: {
					dest: 'dist'
				}
		    },
		    usemin: {
		        html: ['dist/*.html']
		    },
		    //copy任務,將src下的copy到dist
		    copy:{
		    	js:{
		    		expand:true,
                    cwd:'src/',
                    src:['*.html'],
		    		dest:'dist/',
		    	},
		    },
		    //合併
		    concat:{
		    	options: {
			      separator: ';',
			      stripBanners: true,
			      banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
			    },
			    dist: {
			      src: ['src/js/*.js'],
			      dest: 'dist/js/app.js',
			    }
		    },
		});




		grunt.loadNpmTasks('grunt-contrib-uglify');
		grunt.loadNpmTasks('grunt-contrib-jshint');
		grunt.loadNpmTasks('grunt-contrib-watch');
		grunt.loadNpmTasks('grunt-wiredep');
		grunt.loadNpmTasks('grunt-contrib-connect');
		grunt.loadNpmTasks('grunt-usemin');
		grunt.loadNpmTasks('grunt-contrib-copy');
		grunt.loadNpmTasks('grunt-contrib-concat');

		grunt.registerTask('import',['wiredep']);

		grunt.registerTask('package', ['copy:js','useminPrepare','concat:dist','uglify:dist','usemin']);

		grunt.registerTask('start',['connect','watch:start']);
}

以上的三個任務:grunt import、grunt package、grunt start都是我自行進行任務組合配置的,當然如果你足夠熟悉每一種外掛的作用,完全可以自己進行相應任務的調配。

這些外掛的首次安裝方式都為:cnpm install 外掛名 --save-dev ,這裡就不去一一描述了,下載自己需要的外掛就可以了

7.釋出正式版及外掛批量安裝

    我們在釋出正式版本的時候,是不需要node_modules這個資料夾的,但在開發的時候是需要的,所以我們在釋出正式版本的時候,是需要將我們的原始碼修改為釋出版本之後,保留我們的Gruntfile.js以及package.jsonjson,在命令提示符中輸入npm install 即可生成一個node_modules資料夾並安裝在package.json的devDependencies中所有的外掛,有可能由於網路波動導致安裝失敗,多裝幾次就行了。

    如果你想測試一下如上所說的話,將目錄中的node_modules刪掉,輸入npm install即可。

8.整合bower

    我們已經知道了前端開發時,可以進行使用一些外掛以協助我們開發,當然當專案上線的時候,是不需要這些外掛的。而我們專案中所用到的一些外掛,如bootstrap,jquery這些常用的外掛,我們需要去官網找並下載原始碼,那麼有沒有一種方式來簡化這個過程呢,當然,這就是bower

8.1 bower安裝

bower大概的意義就是專案中的包管理

安裝方法:npm install -g bower

其中-g的意思是全域性安裝

當我們使用bower進行包的安裝時,其路徑並不是我們的安裝路徑

所以我們引入一個.bowerrc檔案,注意是以“.”開頭的,其內容為:

{
    "directory": "js/libs"
}

這樣,我們通過bower安裝的檔案路徑就都為:js下的lib中了

8.2 初始化

bower安裝完成後需要進行初始化:

即在命令提示符中輸入 bower init,同npm init相同的,也需要輸入一些資訊,當然也可以一路回車,然後最後確定即可。可以發現目錄中的多了bower.json檔案

{
  "name": "new_test_project",
  "description": "test",
  "main": "index.js",
  "authors": [
    "ds"
  ],
  "license": "ISC",
  "homepage": "",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

8.3 包的安裝

這裡我們用jquery舉例

安裝方法:命令提示符bower install --save jquery


然後bower就會從遠端下載jquery最新版本到你的js/lib目錄下
其中--save引數是儲存配置到你的bower.json,你會發現bower.json檔案已經多了一行:


我們到資料夾中去看,專案根目錄下的js/libs多了jquery的原始檔

8.4 包的資訊

命令提示符輸入:bower info jquery



即可看到jquerybower.json的資訊,和可用的版本資訊

8.5包的更新

想要修改jquery的版本,只要修改bower.json中為:

"dependencies": {
    "jquery": "~1.11.3"
  }

然後執行 bower update 就可以就行版本的切換了

8.5 包的查詢

命令提示符輸入bower search +關鍵字, 如bower search bootstr,即可搜尋出包含bootstr欄位的所有可用的包


8.6包的解除安裝

包的解除安裝為unstall命令

如jquery的解除安裝:bower uninstall jquery