若是你如今還不懂 webpack,我相信你必定和我最開始同樣,對官網的這張圖一臉懵逼,就算如今,我仍是以爲這張圖對新手起了很大的誤導做用。
咱們今天就從js發展的角度來講明,到底什麼是 webpack。
JS的設計初衷
——————
js 早期設計的目的是輔助頁面交互和豐富頁面樣式,這使得 js 能進行 dom 操做。 好比下面這樣。
<html>
<body></body>
<script>
const ele = document.createElement('DIV');
ele.style.background = 'red';
ele.style.width = '100px';
ele.style.height = '100px';
document.body.append(ele);
</script>
</html>
<html>
<body>
<div style="background:red;width:100px;height:100px"></div>
</body>
</html>
雖然使用 js 的寫法很麻煩,可是至少表明了 js 有這方面的能力,他能在不依靠 html 和 css 的狀況下,獨立進行頁面的顯示。
IE最後的禮物
——————
IE 雖然一直讓人詬病,可是有他留下的 xmlHttpRequest 確實是一大寶貝,他能在頁面不刷新的狀況下,請求和獲取後端數據。 這個能力再配合js對於dom操做的能力,就能完成一些騷操做。 好比在頁面不刷新的狀況下,加載一篇新的文章、發佈評論功能等等。 這也是最先單頁面應用的雛形。
你可能不知道早期在論壇進行一次簡單的評論,要通過2次頁面的跳轉。
Node讓js突破能力的界限
———————————
node 他既不是開發語言,也不是什麼框架,他是一個開發環境。 咱們原來的js是運行在瀏覽器,這注定他有不少事情作不了,最基本的就是,他不能在瀏覽器對你本地文件進行增刪改。 而node他是運行在本地的,他沒有在瀏覽器端那些限制,他有極高的權限,其中同樣就是能夠對本地文件進行增刪改。
也正是這一特徵,他讓預處理語言獲得了極大發展。 咱們能夠本身制定一套語法,而後經過轉換器(loader),編譯成html能夠理解的語言。 目前html主要就認識2種文件,css和js。
模塊化的進化
——————
其實前端模塊化一直都在,咱們將一個個js寫好,而後在html裏面一個個引用,這就是最先的模塊化。 可是這產生了一個問題,這些引入關係都是寫在html裏面的,兩個js文件之間要進行交互,也只能經過全局變量賦值的形式。
答案是能夠的,目前比較主流的方式是 Node的common.js和ES6的ESModule兩種方式,下面使用ESModule來改變一下以前的引用方式。
<html>
<body>
<script src="js/jquery.js"></script>
<script src="js/util.js"></script>
<script src="js/index.js"></script>z
</body>
</html>
<html>
<body>
<script src="js/index.js"></script>z
</body>
</html>
/* 這是index.js 的內容 */
import $ from 'jquery.js';
import util from 'util.js';
$('div').remove();
至此,咱們已經瞭解了使用webpack的四個先決條件了。
主角登場
————
如何構建一個單頁面應用? 下面咱們從一個需求入手,來引出爲啥須要webpack。
# 目錄結構
index.html
index.js
<html>
<body>
<script src="index.js"></script>
</body>
</html>
function showIndex(){
document.body.innerText = '這是首頁';
}
function showList(){
document.body.innerText = '這是列表頁';
}
function showArticle(){
document.body.innerText = '這是內容頁';
}
const arr = [
['首頁',showIndex],
['列表頁',showList],
['內容頁',showArticle],
]
arr.forEach((item)=>{
const ele = document.createElement('DIV');
ele.innerText = item[0];
ele.onclick = item[1];
document.body.append(ele);
})
複製代碼
代碼邏輯很簡單,就是在頁面渲染一些內容,而後點擊會跳轉到不一樣的頁。 可是若是全部內容都寫在index.js裏,代碼會變得很巨大,後期也很很差維護,
因此咱們對index.js進行功能拆分,而後使用引用的方式,將他們關聯起來。
# 目錄結構
pages
|__ home.js
|__ list.js
|__ article.js
index.js
index.html
import { showIndex } from 'js/home.js';
import { showList } from 'js/list.js';
import { showArticle } from 'js/article.js';
const arr = [
['首頁',showIndex],
['列表頁',showList],
['內容頁',showArticle],
]
arr.forEach((item)=>{
const ele = document.createElement('DIV');
ele.innerText = item[0];
ele.onclick = item[1];
document.body.append(ele);
})
複製代碼
function showIndex(){
document.body.innerText = '這是首頁';
}
export showIndex;
可是有個問題,上面的代碼在老版本的瀏覽器是沒法運行的,由於老版本瀏覽器,不支持ES6模塊,
因此咱們須要使用node對項目源代碼進行分析打包,造成新的瀏覽器能夠運行的代碼,就變成了新的目錄結構。
# 目錄結構
dist
|__ index.js
|__ index.html
src
|__ pages
| |__ home.js
| |__ list.js
| |__ article.js
|__ index.js
|__ index.html
分析打包的過程就是,咱們須要寫一個腳本,node執行這個腳本,腳本內容是去打開index.js文件,而後對代碼進行解讀,當遇到依賴引入的地方時,而後把代碼複製進來,看下面這個動圖就能夠一清二楚。
固然咱們不須要本身寫這個腳本,由於咱們有 webpack,
webpack的第一個功能,就是作上面的事情,從入口文件開始分析,對依賴進行合併,而後打包輸出。
而webpack的第二個功能,就是他能夠處理你引入任何格式的文件,注意,是任何格式。
前面介紹過,在前端有不少預處理語言,他們能極大方便咱們的開發,可是預處理語言須要進行編譯,才能成爲可以使用的語言。 而webpack,就能幫咱們進行編譯。
webpack 當處理到不認識的文件格式時,會把他轉化爲字符串,而後使用loader對他進行轉化,轉化成js認識的格式。
以上面的項目爲例子,咱們將被引用的幾個腳本文件改成了ts的文件形式。
# 目錄結構
dist
|__ index.js
|__ index.html
src
|__ pages
| |__ home.ts
| |__ list.ts
| |__ article.ts
|__ index.js
|__ index.html
js默認是不認識ts文件裏的內容的,即便他們很像,因此webpack在解析ts文件時,要先作一個事情,就是先把ts轉爲js格式,而後在對轉化後的js進行引入。
loader是能夠拓展的,因此只要你有被引入文件的loader,理論上你能夠引入任何文件格式。
webpack的第三個功能,就是插件。
插件就是webpack在執行分析打包任務時,你能夠作一些額外的操做。
好比說,在引入css後對css進行自動添加適配前綴、對項目總體代碼進行壓縮等等,都是插件的功能體現。 由於說到底,代碼就是字符串,webpack能獲取到整個項目,包括依賴文件的代碼(字符串),而後他在這個字符串作一些操做,也很好理解。
這就是webpack的三個主要功能,他的可拓展性,讓他極具創造力,現在基本已經成爲了全部web應用的基建部分,正所謂時勢造英雄,他生在了前端最須要他的年代,我相信他構建的打包模式,不會是咱們前端的最終形態,只要js還在進步,還在變化,就會有新的模式出現。