前端模塊化系列(一):網站需要模塊化的原因


前端模塊化

標簽(空格分隔): 模塊化


前端模塊化系列(一):網站需要模塊化的原因

由於我最近在研究前端各種各樣的模塊化系統,所以就翻譯了一篇來自webpack官網的文章,總的來說作者寫的還是相當不錯的。這樣在自己學習的同時也可以與大家共同學習~~~

在今天的網站正在逐步的向web apps轉變。

  • 單個頁面中越來越多的Javascript。
  • 在現代瀏覽器中你可以做越來越多的功能。
  • 少量的全頁面刷新,以至於單個頁面中有更多的代碼。

正因為這些原因造成越來越多的代碼鑲嵌在瀏覽器端中。

這樣一個大的代碼倉庫(code base)急需做出相應的管理。正好,模塊化系統提供了這些功能分割你的代碼倉庫,把它們分割為一個個的模塊。

各個模塊系統的風格

眼下對於如何定義依賴項和暴露接口有很多的標准:

  • <script>標簽風格(ps:不使用模塊系統)。
  • CommonJs
  • AMD和它的一些衍生物
  • ES6模塊
  • 更多。。。

在下面,我們會一次簡介這些模塊化系統之間的好處以及壞處。

<script>標簽風格

如果你沒有使用模塊化系統,那么你只能用這種方式來處理你的模塊化代碼了。

<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="libraryA.js"></script>
<script src="module3.js"></script>

每個模塊向外暴露一個接口給全局對象,即window對象。模塊就可以通過全局對象訪問依賴項向外暴露的接口。

通常存在的問題

  • 全局對象中的變量沖突。
  • 按需加載的問題。
  • 開發者需要手動解析模塊或者庫的依賴項。
  • 在特別大的項目中,這個現象會變得越來越嚴重,越來越難以管理。

CmmonJs:同步require

這種方式使用了一個同步的require方法去加載依賴項並且返回一個向外暴露的接口。一個模塊可以通過給exports添加屬性或者給module.exports設置固定值來指定向外暴露的值。

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

這個只是被node.js使用在server端。

優點:

  • server端的模塊可以被復用。
  • 有許多現成的模塊以供使用(npm)。
  • 非常的簡單易用。

缺點:

  • 因為網絡請求都是異步的。所以阻塞式的調用在網路中支持的不是很好。
  • 多個模塊之間並能同時並行的加載進來。

實現
1、node.js - server端。
2、browserify
3、modules-webmake-編譯到一個bundle里
4、wreq-客戶端

AMD:異步的require

Asynchronous Module Definition
其他的模塊化系統(對於瀏覽器來說)對於同步require(CommonJs)都有或多或少的問題。接下來我們介紹一個異步require的模塊化系統(定義模塊和暴露值的另外一種實現方式)。

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

優點:

  • 十分適合在現下網絡的異步請求。
  • 支持多個模塊的同時並行加載。

缺點:

  • 寫碼開銷。讀寫十分的困難。
  • 看上去像是一種解決方案。

實現
1、require.js - client端。
2、curl - client端。

獲取更多相關CommonJSAMD的知識。

ES6模塊化

EcmaScript6針對JavaScript添加了一些新的語言結構,其中就包括模塊化系統。

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

優點:

  • 很容易的靜態模塊解析。
  • 未來不久將要作為ES標准來推行。

缺點:

  • 讓大部分的瀏覽器支持這個功能還需要一段時間。
  • 這種風格的模塊太少了,讓人不適應。
咱誰也不偏向誰的解決方案

給開發者關於模塊化風格的選擇權。在現有代碼可以正常運行的前提下,可以很容易地添加自定義模塊。關鍵還要看使用某個模塊系統對於現在的系統影響大不大。

模塊的傳輸方式

模塊是應該在client端被執行的,所以這就需要它們通過http協議讓server端向瀏覽器端傳輸。

現在有兩種方式來處理如何傳輸模塊
1、一個請求一個模塊。
2、所有的模塊都在一個請求里。

這兩種方式都有人在用,不過這兩種都是次優的:

一個請求一個模塊

優點

  • 僅僅傳輸被請求的那個模塊。

缺點:

  • 許多的請求意為着網絡開銷也很大。
  • 程序啟動變慢,因為請求會延遲。
所有的模塊都在一個請求里

優點

  • 很小的請求開銷,少量的延遲。

缺點:

  • 不需要(還沒有)被請求的模塊也被傳輸過來了。

分塊傳輸方式

相對於上面兩種方式都太死板了,所以靈活點的模塊傳輸會不會更好哪?因為向兩個極端之間的折中妥協通常都是最好的。

雖然我們需要把所有的模塊都編輯,把模塊安裝功能和是否公用拆分為多個較小的代碼塊。

我們有很多的小量請求。把那些不需要一開始就請求,或者是需要按需加載的模塊來進行分塊傳輸。瀏覽器最開始的訪問請求並不用包含你的所有代碼庫(code base)。這樣的話,server返回的數據大小也就會變的很小。有效解決了上面兩種方式所出現的問題。
至於如何分隔模塊應該是開發者根據功能,格式,加載順序,繼承關系分割為一個一個單獨的部分.
注意:拆分的粒度問題,可復用問題,效率問題.如何這些問題處理的不好,就有可能出現不想要的后果。

這樣的話。就算再多的代碼也可以解決掉了。

獲取更多相關代碼塊如何分割的知識。

為什么僅僅只是JavaScript?

不知道大家有沒有發現,為什么一個模塊化系統僅僅只幫助開發者處理JavaScript哪?除此之外還需要很多的靜態資源需要我們去處理呀!

  • stylesheets(樣式表)
  • images(圖片)
  • webfonts(web字體)
  • html for templating(html模版)
  • 等等...

當然,還有其他的資源:

  • coffeeScript -> javascript
  • less -> stylesheets
  • jade -> 經過javascript生成的html
  • 等等...

它們也應該向JavaScript一樣可以被很容易的require到:

require("./style.css");
require("./style.less");
require("./template.jade");
require("./image.png");

模塊靜態解析

當編譯所有模塊的時候,為了協調異步環境下模塊開發與性能間的矛盾,我們必須在工程階段就具備依賴分析的能力,把具備依賴關系的資源進行打包。就算不打包,也希望像 F.I.S 那樣有個記錄依賴關系的map.json,可以照單抓葯,一次性地把需要的依賴項加載下來。

策略

一個聰明的解析器將允許大多數現有的代碼可以有效運行,不管開發者有沒有使用模塊化系統。即使開發人員做了一些奇怪的東西,它也會嘗試找到最適合的解決方案。實在不行,也就只能抱歉咯!!!

翻譯自:http://webpack.github.io/docs/motivation.html
翻譯人:張亞濤


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM