之前一直對前端構建工具的理解不深,通過幾天的研究特地來總結一下,第一次寫博客,有寫錯的請多多見諒,該文章我也從其餘博客拷了一些內容,若是有冒犯之處,請指出。php
現在,網頁再也不是本身編寫各類功能了,而是如何把各類不一樣功能的模塊組合起來。
之前使用script引用不但增長網絡請求,還會時頁面更加臃腫,爲了解決這類問題,前端的模塊管理應運而生,最先提出解決方法的是AMD,其實踐方案是requireJs和curlJs.它不只實現了js文件的異步加載,還管理了模塊之間的倚賴性,(相似於面向對象的Module模式)css
main就是主模塊,省略了.js後綴,在main.js裏面能夠配置模塊的加載,在其頭部寫require.config前端
在實際應用中,每每還須要在服務端,將全部模塊合併後,再統一加載,這多出了不少工做量java
AMD 經過將模塊的實現代碼包在匿名函數(即AMD 的工廠方法,factory)中實現做用域的隔離,經過文件路徑做爲自然的模塊ID 實現命名空間的控制,將模塊的工廠方法做爲參數傳入全局的define(由模塊加載器事先定義),使得工廠方法的執行時機可控,也就變相模擬出了同步的局部require,於是AMD 的模塊能夠不經轉換地直接在瀏覽器中執行。 所以,在開發時,AMD 的模塊能夠直接以原文件的形式在瀏覽器中加載執行並調試,這也成爲RequireJS 方案很少的優勢之一。node
注意:webpack
然而基於AMD 規範的非JavaScript 資源加載有着本質的以下缺陷。
1.加載與構建的分離致使plugin 須要分別實現兩套邏輯。
2.在構建產物,r.js構建的結果是define(function(){...})的幾何,文件的執行倚賴頁面上事先引入一個amd模塊加載器(如requireJs自身),因此常見的AMD項目線上頁面每每存在兩個Javascript文件:loader.js及bundle.js。而browserify和webpack的構建結果 是能夠執行的js代碼,它們都支持經過配置生成符合格式的結果文件,如以umd形式暴露 庫的exports,以便其餘頁面代碼調用。後者的這種形式更符合js庫的構建
3.瀏覽器的安全策略決定了絕大多數須要讀取文本內容進行解析的靜態資源沒法被跨域加載(即便是JavaScript 模塊自己,也要依靠define 方法包裹,相似於JSONP 原理實現的跨域加載)。es6
其本事不是模塊管理器,只是讓CommondJs格式的模塊能夠運行在瀏覽器端,這意味着它可使用nodeJs的npm模塊管理器。因此,實際上,它等於間接爲瀏覽器提供了npm的功能web
上面這個代碼使用的是CommondJs格式,沒法在瀏覽器中運行,這是須要用到browserify,將上面代碼編譯爲瀏覽器腳本npm
注意:(1). requirejs/seajs: 是一種在線「編譯」模塊的方案,至關於在頁面上加載一個CommonJS/AMD模塊格式解釋器。這樣瀏覽器就認識了define, exports,module這些東西,也就實現了模塊化。gulp
(2).browserify/webpack:是一個預編譯模塊打包的方案,相比於第一種方案,這個方案更加智能。因爲是預編譯的,不須要在瀏覽器中加載解釋器。你在本地直接寫JS,不論是AMD/CMD/ES6風格的模塊化,它都能認識,而且編譯成瀏覽器認識的JS。注意: browerify打包器自己只支持Commonjs模塊,若是要打包AMD模塊,則須要另外的plugin來實現AMD到CMD的轉換!!
browserify不支持異步加載,非js文件加載(img src打包路徑問題)
這裏插入一下es6和CommonJs的區別:
* 運行時加載: CommonJS 模塊就是對象;即在輸入時是先加載整個模塊,生成一個對象,而後再從這個對象上面讀取方法,這種加載稱爲「運行時加載」 * *
編譯時加載: ES6 模塊不是對象,而是經過 export 命令顯式指定輸出的代碼,輸入時採用靜態命令的形式。即在輸入時能夠指定加載某個輸出值,而不是加載整個模塊,這種加載稱爲「編譯時加載」
正如咱們在前面提到的define 函數的做用,沒有define 函數的CommonJS 模塊是沒法直接在瀏覽器中執行的——瀏覽器環境中沒法實現同Node.js 環境同樣同步的require 方法。一樣也由於沒有define 與工廠方法,CommonJS 模塊書寫起來要更簡單、乾淨。在這個顯而易見的好處下,愈來愈多的前端項目開始採用CommonJS 規範的模塊書寫方式。
Gulp / Grunt 是一種工具,可以優化前端工做流程。好比自動刷新頁面、combo、壓縮css、js、編譯less等等。簡單來講,就是使用Gulp/Grunt,而後配置你須要的插件,就能夠把之前須要手工作的事情讓它幫你作了。
gulp相比grunt簡便,藉助unix的流操做思想,經過管道pipe來管理task任務,實現前端的優化,例如把Js和css融合在一塊兒並壓縮
webpack只是在Loader裏面加載的時候,幫咱們默認實現了操做,沒有gulp操做得透明,gulp只是構建工具,因此若是開發SPA單頁面應用的時候,須要用到模塊化開發,這時就須要用到模塊化的概念,若是想用CommondJs風格,就須要藉助browserify來做爲轉換工做,也許你會發如今gulp使用時就有require('gulp')這樣的引用風格,這是npm包管理的模塊,是CommondJs的node的風格,是編寫gulp這些構建工具時用的,不是咱們編寫本身的前端模塊代碼的。因此使不使用模塊方案要看項目工程是否龐大決定,若是簡單,作個多頁面應用,不須要把js或各類資源打包處理,只須要簡單的合併,壓縮,在頁面中引用就好,那就不須要Browserify,webpack。用gulp就夠了。使用es6模塊規範時,經過babel轉之後造成commondJs這樣的代碼,通常還不能使用,由於瀏覽器不識別commondJs,因此須要browserify或者webpack將其打包到一個js文件中。
可是相比於npm , grunt和gulp缺點是至關倚賴插件的開發,若是出現新技術時,須要相關人開發插件,如gulp-eslint,當使用時,須要在gulp-eslint文檔和eslint文檔來回切換,不得不在插件和所抽象的工具之間來回切換上下文。相比於npm這個更大的插件社區,缺點教爲明顯
構建工具完成的目標基本是:
fis也屬於前端構建工具,它的本質是基於靜態資源標記和動態解析靜態資源表,在模版,js裏面使用特殊的標記方法引用前端資源,構建的時候生成一張資源倚賴表,瀏覽器或者後端模版語言在解析的過程當中經過查表獲得某個靜態資源在不一樣環境下的引用路徑,因此不論是純前端渲染仍是服務端渲染,都容易獲得支持,
fis實際上是一種靜態資源表的思想,在這種思想下,對於php的smarty產生了fis-plus,基於java的即是 jello,
後來fis3都將其歸入了其中
fis3的功能和webpack相似,其優勢是靜態資源表
fis3設計之初是用在網頁構建上,因此後端的文件操做之類不適用,fis3的模塊化開發主要是AMD,CMD和自定義擴展commonJs的modJs,三個分別對應於三個插件來實現,因爲本身葛璐開發了一種模式,因此致使貢獻也少了,fis能夠作到完美的解決方案還須要後端的配合,因此也使得其不了了之。
webpack比較黑盒,用起來很方便,十分適合開發SPA項目,可是卻不適合服務端渲染,webpack目前的功能已經很是齊全,也相應的會帶來首次加載,打包時間慢,須要對其打包進行優化
它既吸收了大量已有方案的優勢與教訓,也解決了不少前端開發過程當中已存在的痛點,如代碼的拆分與異步加載、對非JavaScript 資源的支持等。強大的loader 設計使得它更像是一個構建平臺,而不僅是一個打包工具。
考慮到AMD 規範與CommonJS 規範各有各的優勢,且都有着可觀的使用率,webpack 同時支持這兩種模塊格式,甚至支持兩者混用。並且經過使用loader,webpack也能夠支持ES6 module(這一特性在即將到來的webpack 2 中原生支持),能夠說覆蓋了現有的全部主流的 JavaScript 模塊化方案。經過特定的插件實現 shim 後,在webpack 中,甚至能夠把以最傳統全局變量形式暴露的庫看成模塊require 進來。
webpack.config.js實在node.js中運行的,所以不支持es6的import語法
其實webpack是個大boss,我就不在本文細說了,網上對webpack的使用已經有不少案例了。
感謝你的捧場,有什麼錯誤能夠指出,你們多多探討...
***未完待續***