- 前提:node npm
- 安裝grunt命令行工具 npm install -g grunt-cli
- 在工做目錄安裝grunt npm install grunt --save-dev
- 編輯Gruntfile.js文件
- 在命令行執行grunt命令
格式以下,三步上籃:
javascript
module.exports=function(grunt){//包裹函數,全部代碼都在這裏 grunt.initConfig({});//1配置任務內容 grunt.loadNpmTasks();//2加載插件 grunt.registerTask();//3註冊任務 }
initconfig——配置
能夠有多個插件名,每一個的插件名-加載插件名-註冊任務中執行的插件名字要一致。
每一個插件名能夠有多個任務描述,默認所有執行,也能夠指定執行某些任務。css
grunt.initConfig({ 插件名1: { 任務描述1: { //描述xxx }, 任務描述2: { //描述xxx2 } }, 插件名2: { 任務描述3: { //描述xxx3 } } }); 好比: uglify: { main: { //描述 src: '1.js',//源文件 dest: '1.min.js'//目標文件 } }
loadNpmTasks——引入插件
html
grunt.loadNpmTasks('grunt-contrib-uglify');
registerTask——註冊任務
前端
grunt.registerTask('default', ['uglify']);
執行的是registerTask註冊的任務java
- 插件基本都能自動建立文件夾
- 重複執行grunt的話,已經存在的文件會被覆蓋,不報錯,不在後面添加。
- 通配符 *號 代指全部
- 通配符 **號 代指全部,包括沒有
- cwd 描述想要做爲當前文件夾的文件夾路徑
- expand,分開成一個個的文件,uglify能夠壓縮文件到一個文件,cssmin不能夠
- ext參數,設置後綴名
- grunt中的模板
<%= grunt.template.today("yyyy-mm-dd HH-MM-ss") %>
, 也能夠放一個常量json進來能夠在模板中使用,避免重複寫,也便於更改
結合<%= %>使用模板- grunt輸出
grunt > log.txt
- concat 鏈接起來,不壓縮,生成的是一個文件【注意: 順序未知】
- grunt.file上面有基於nodeJs的fs包裝好的操做文件的方法,好比:
grunt.file.readJSON()
一般用來讀取json文件,直接轉化爲可用的json- copy 帶文件夾層級複製,複製多個文件時,要有expand,不然會報錯
- watch —— 監測,(自動化)
轉自阮一峯的博客:最先的時候,全部Javascript代碼都寫在一個文件裏面,只要加載這一個文件就夠了。後來,代碼愈來愈多,一個文件不夠了,必須分紅多個文件,依次加載。下面的網頁代碼,相信不少人都見過。node
<script src="1.js"></script> <script src="2.js"></script> <script src="3.js"></script> <script src="4.js"></script> <script src="5.js"></script> <script src="6.js"></script>
這段代碼依次加載多個js文件。隨着代碼愈來愈多,當依賴關係很複雜的時候,代碼的編寫和維護都會變得困難。就算是代碼做者本人,在後期維護起來也會愈來愈吃力,更不敢想多人合做了。jquery
在前端開發過程當中,常常會出現一個單文件幾千行甚至近萬行的狀況。這種大文件,對協做開發、後續維護、性能調優等都不利。模塊化開發初衷是幫助前端開發工程師將大文件拆分紅小文件,能保持小顆粒度的模塊化開發,同時不須要過多考慮依賴關係,讓依賴管理輕鬆自如,將更多精力聚焦在代碼自己的邏輯上。git
先分開介紹,再對比
CMD seaJs 玉伯
玉伯(王保平),淘寶前端類庫 KISSY、前端模塊化開發框架SeaJS、前端基礎類庫Arale的創始人。
github
- 懶加載——Execution must be lazy.
- 一個模塊就是一個文件,代碼的書寫格式以下:define(factory);
- define 是一個全局函數,用來定義模塊。
define 接受 factory 參數,factory 能夠是一個函數,也能夠是一個對象或字符串。npm
- factory 爲對象、字符串時,表示模塊的接口就是該對象、字符串
factory 爲函數時,表示是模塊的構造方法。執行該構造方法,能夠獲得模塊向外提供的接口。factory 方法在執行時,默認會傳入三個參數:require、exports 和 module:
define(function(require, exports, module) {//參數的順序必須是這樣的 // 模塊代碼 //require是獲取其餘模塊的函數 //exports用來輸出當前模塊 //module用來輸出當前模塊 //exports 僅僅是 module.exports 的一個引用。在 factory 內部給 exports 從新賦值時,並不會改變 module.exports 的值。所以給 exports 賦值是無效的,不能用來更改模塊接口。 });
- 常用的 API 只有 define, require, exports, module.exports而已,簡單明瞭
最簡單的seaJs案例
//主html <!doctype html> <html> <head> <script src="../sea-modules/seajs/seajs/2.2.0/sea.js"></script> <script> seajs.use("main");//main是main.js,是用define定義的模塊 </script> </head> <body> 頁面內容 </body> </html>
//main.js define(function(require) { alert(1); });
- 主文件配置參數 seajs.config(); 官方介紹
seajs.config({//paths 配置能夠結合 alias 配置一塊兒使用,讓模塊引用很是方便。 // 設置路徑,方便跨目錄調用 paths: { 'arale': 'https://a.alipayobjects.com/arale', 'jquery': 'https://a.alipayobjects.com/jquery' }, // 設置別名,方便調用 alias: { 'class': 'arale/class/1.0.0/class', 'jquery': 'jquery/jquery/1.10.1/jquery' } });
- 主文件使用模塊:seajs.use();——頭(or衣領)API介紹
// 加載一個模塊 seajs.use('./a'); // 加載一個模塊,在加載完成時,執行回調 seajs.use('./a', function(a) { a.doSomething(); }); // 加載多個模塊,在加載完成時,執行回調 seajs.use(['./a', './b'], function(a, b) { a.doSomething(); b.doSomething(); });
- 如何定義模塊
用define來定義模塊。Sea.js 推崇一個模塊一個文件,遵循統一的寫法:
define(function(require, exports, module) { // 模塊代碼 // exports 被require的對象上的屬性或方法 // 對外提供 foo 屬性 // 在外部使用:require(xx).foo exports.foo = 'bar'; // 對外提供 doSomething 方法 // 在外部使用:require(xx).dosomething exports.doSomething = function() {}; //********************// // module.exports 就是被require的對象 module.exports = { name: 'a', doSomething: function() {}; }; });
- 如何引用模塊
require 用來獲取指定模塊的接口。
define(function(require, exports, module) { // 獲取模塊 a 的接口 var a = require('./a'); // 調用模塊 a 的方法 a.doSomething(); });
- 總結:用define來定義模塊,一個模塊就是一個文件,在模塊裏用require來引用其餘模塊,在主html文件裏引入seajs後用seajs.use()來開啓js文件。
AMD requireJs
- 全稱 Asynchronous Module Definition——異步模塊定義規範。
- 模塊和模塊的依賴能夠被異步加載。
- 模塊的依賴被異步加載完成之後,工廠函數纔會執行。
- define 是一個全局函數,用來定義模塊。
define 能夠接受多種格式的參數,不過一般能夠是:
- define(依賴的數組,工廠函數);
- define(工廠函數);
- define(一個對象);
- 一個模塊就是一個文件
最簡單的requireJs案例
//主html <!doctype html> <html> <head> <script src="js/require.js"></script> <script> require(['jquery'], function($){ alert('jquery loaded'); }); </script> </head> <body> 頁面內容 </body> </html>
or:
//主html <!doctype html> <html> <head> <script src="js/require.js" data-main="js/main.js"></script> </head> <body> // 這樣寫,會異步加載data-main指定的js文件,並把data-main所在的路徑做爲config配置的baseUrl。若是不想異步,就像上面同樣寫。 頁面內容 </body> </html> //main.js require(['jquery'], function($){//會在jquery模塊執行完成後,把jquery的輸出作爲參數傳入後面的工廠函數,並執行工廠函數 alert('jquery loaded'); });
- 配置: 可使用require.config來設置依賴的模塊的名稱和對應的路徑,也能夠在引入require.js以前定義一個名字爲require的json。兩種方式均可以進行配置。; requireJs配置官方介紹
<script src="scripts/require.js"></script> <script> require.config({ baseUrl: "/another/path", paths: { "some": "some/v1.0" } }); require( ["some/module", "my/module"], function(someModule, myModule) { //..... } ); </script> 或者是: <script> var require = { baseUrl: "/another/path", paths: { "some": "some/v1.0" } }; </script> <script src="scripts/require.js"></script>
- 主文件如何使用模塊:從上面已經能夠看到,不一樣於seaJs的使用seajs.use()函數,requireJs使用require()函數來開始執行。
如何定義模塊
用define來定義模塊:常見的3種狀況
define(依賴的數組,工廠函數);
define(['aModule','bModule'],function(a,b) { // 模塊代碼 // 這個定義的模塊在被調用時,aModule和bModule模塊加載完成以後,纔會以他們的返回值做爲參數執行工廠函數 });define(工廠函數); 語法糖
define(function(require, exports, module) { // 模塊代碼 // 這種方式實際上是requireJs的語法糖,能夠在函數裏面用變量接受require過來的模塊(就像seaJs作的那樣),並不真的是同步require那個代碼,而是用的Function.prototype.toString()轉換成數組裏面的格式(怎麼轉換的我們無論)後異步下載後執行回調。 });define(一個對象);
define({ color: "black", size: "12" });
如何引用模塊
用require來獲取指定模塊的接口(常見有2種):
require(依賴的數組,工廠函數);
require(['aModule','bModule'],function(a,b) { // 模塊代碼 // aModule和bModule模塊加載完成以後,纔會以他們的返回值做爲參數執行工廠函數 });
- require(依賴的數組);
//只是用來作一個頭,異步引入js後本身不用再作其餘事情 require(['aModule','bModule']) ;
- 總結:
用define來定義模塊,一個模塊就是一個文件。
define新模塊時用數組提早聲明依賴的模塊。
在主html文件裏引入requirejs後用require()來開啓js文件。
共同點:
- 都是模塊加載器,倡導模塊化開發理念
- 核心價值是讓 JavaScript 的模塊化開發變得簡單天然
不一樣點:
- RequireJS是異步加載模塊,SeaJs是同步加載模塊
- RequireJS是提早聲明並加載依賴,SeaJs是按需加載依賴模塊
咱們目前使用的是 RequireJS。