前端工具之WebPack解密之背景

請注意,這是一篇站在徹底新手的角度上來寫的文章。可能你是一個後端人員想了解前端工具的使用和概念;也可能你是一個前端小菜(還在DIV+CSS的世界裏掙扎着)。本文比較適合那些之前徹底沒有接觸過WebPack,而又想使用的朋友。經過本文你能理解webPack工做原理及作用!(不會至於看了半天資料尚未頭緒!)javascript

前言:本人是一個從後端轉向前端的程序猿,在此以前對於前端的印象一直是:HTML + CSS + JS。徹底沒有想過前端會發展的如此的迅速,各類名詞的出現:Node、NPM、Grunt、Gulp、Bower、Webpack、Browserify、Yeoman。瞬間讓感受到不知道如何下手(好像根本學不完的樣子)!html

先上一張別人的圖,目前的前端工具!前端

1、背景

若是你和我同樣,以前對於前端打包工具的發展一無所知,甚至於不知道這些工具出現的必要性。你能夠瀏覽此部分的內容,若是你不想知道這些或者對這些並不感興趣,能夠直接跳過此部分。java

互聯網程序現狀

隨着移動互聯的來襲,當前愈來愈多的網站已經從單純的網頁模式,開始升級爲webapp模式。它們運行在現代的瀏覽器中,使用HTML五、CSS三、ES6等技術開發,已經從單一的瀏覽功能轉變爲一個基於瀏覽器的富客戶端。而且webapp一般是一個SPA(Single Page Application 單頁面應用)。每一個頁面(View)經過異步的方式加載,有着良好的用戶體驗。可是這樣作的結果是致使程序初始化和使用的過程當中須要更多、更復雜的JavaScript代碼來實現,這就對前端程序的開發帶來巨大的挑戰!node

模塊化系統的演變

隨着程序的複雜性的增長,項目結構的龐大。把單一js文件按職責進行模塊化劃分。jquery

咱們在寫頁面的時候會這樣寫:git

<script src="base.js"></script> <script src="utils.js"></script> <script src="vipPush.js"></script>

這是最基礎的JavaScript加載方式,每一個JS的全部方法和屬性都是暴露在window對象中的(就像把全部代碼都放在一個命名空間或者同一個包下),藉助全局對象,咱們就能使用這些屬性和方法。若是更爲複雜的程序會使用命名空間的概念來組織這些模塊的接口,好比:YUIes6

這種開發方式帶來的弊端:github

  • 全局的做用域下容易形成變量的相互衝突(這是一個很常見的問題)
  • 文件只能按照<script>的書寫順序進行加載
  • 開發者要解決各個模塊和代碼庫之間的依賴
  • 若是按照此模式進行開發,長期下去整個項目(前端)代碼一定會混亂不堪

由於有了模塊的概念,讓咱們的開發變得比較方便。讓咱們能夠很方便的使用別人的代碼,想要什麼功能就加載什麼模塊。這樣下去模塊的規範就變的更重要。目前:通用的JavaScript模塊主要有:web

  1. CommonJs
  2. AMDCMD
  3. ES6的模塊

CommonJS: 同步加載解決方案

著名的node.js模塊系統就是參照CommonJS規範來實現的。其核心思想就是經過require來進行同步加載其它模塊,而後經過exports 或 module.exports來導出須要暴露的接口。

require("module")require("./file.js")exports.doStuff function({}; module.exports = someValue;

優勢:

  1. 服務器端模塊便於重用
  2. 在NPM裏有不少功能模塊
  3. 簡單易用

缺點:

  1. 同步加載的方式註定不能用於客戶端(clients),同步的加載意味着阻塞加載,瀏覽器的加載方式是異步的
  2. 不能非阻塞的並行加載多個模塊

表明:

  1. 服務端 node.js
  2. Browserify,瀏覽器端的 CommonJS 實現,可使用 NPM 的模塊,可是編譯打包後的文件體積可能很大

AMD: 異步加載解決方案

AMD(asynchronous Module Definition)意思就是"異步模塊定義",其規範主要是一個接口define(id?, dependencies?, factory),它採用的是異步加載的方式加載模塊,模塊的加載不影響它後面請語句的運行。全部執行語句都是在模塊加載完成以後的回調函數中執行的。

define("module", ["dep1""dep2"]function(d1, d2) return someExportedValue})require(["module""../file"]function(module, file) /* ... */ });

優勢:

  1. 適合在瀏覽器環境中進行加載模塊
  2. 能夠並行多個模塊

缺點:

  1. 提升了併發的成功,代碼的閱讀和書寫比較困難
  2. 不符合通用模塊化的思惟方式,是一種妥協的實現

實現:

CMD: 另外一種異步加載解決方案

CMD(Common Module Definition)規範與AMD很類似,儘可能保持簡單,並與CommonJs和Node.js的Module規範保持了很大的兼容性

define(function(require, exports, module) var $ require('jquery')var Spinning require('./spinning')exports.doSomething = ... module.exports = ... })

優勢:

  1. 依賴就近,延遲執行
  2. 能夠很容易在 Node.js 中運行

缺點:

  1. 依賴 SPM 打包,模塊的加載邏輯偏重

實現:

ES6 模塊

在ECMAScript2015(es6)中,增長了JavaScript語言層面上的模塊體系定義,其設計思想是:儘可能的靜態化,使得編譯時就能肯定模塊的依賴關係,以及輸入和輸出變量。

import "jquery"export function doStuff({} module "localModule" {}

優勢:

  1. 容易進行靜態分析
  2. 面向將來的 EcmaScript 標準

缺點:

  1. 原生瀏覽器端尚未實現該標準
  2. 全新的命令字,新版的 Node.js才支持

實現:

把程序全部的文件進行模塊化以後,咱們還要處理一個問題那就是傳輸問題。模塊的化分讓咱們可讓程序變得能夠組件化進行開發,組件雖然被客戶端執行,可是依然要由服務器傳送給客戶端。

關於組件的傳送有兩個極端:

  1. 每一個組件,一個HTTP請求

    • 優勢:僅僅傳送依賴項
    • 缺點:請求多,負載高,更慢的啓動延遲
  2. 全部的組件,一個HTTP請求

    • 優勢: 更快,更低的延遲
    • 傳送了沒有必要傳送的東西

讓我在這兩種狀況之間作一個妥協:分塊傳輸,按需進行懶加載,在實際用某些模塊的時候進行增量的更新,纔是比較合理的加載方案。

要實現這個功能,須要在編譯打包時進行靜態的分析、模塊進行分批次的打包。那麼這個分批次誰來作呢?
答案就是:WebPack

相關文章
相關標籤/搜索