Webpack 實作入門1:寫給 「非Node.js開發者」 的教學


作者: | 2017/08/21 10:34:24 | 留言


webpack - module bundler

會寫這篇純粹是想整理一個單純的 Webpack 教學 (給非 Node.js 開發者)

我自己的經驗是這樣的。

一開始想學習 Webpack 時,都會先在網路上找教學,但通常都是後端也使用 Node.js 的人或純前端工程師寫的教學,很容易會談太多範例是基於他們自己的開發流程,所以總是一開始就會提到像是 react, jsx … 等等,範例語法也常常出現 Node.js 的寫法,以至於很難理解單純的 Webpack 要怎麼應用在自己的(非node.js)專案上。

有鑑於此,我想自己邊摸索邊寫篇教學來記錄一下,基本上是寫給非 node.js 的開發者,像是 WordPress 的佈景開發者XD。

我的開發環境是 MAC OS,如果你用的是其他OS,概念上應該都是一樣的,但能不能成功就隨緣了~ XD

完整範例檔在:https://github.com/mrmu/webpack-tutorial-1-examples,但還是希望你手動自己建立自己的範例,這樣印象最深刻。

本篇教學只要求你有基本的 HTML + CSS + JavaScript/jQuery 編寫經驗就好了,然後你必須不害怕輸入超級簡單的命令列指令。

最好你有一點學習 webpack 或 node.js 失敗的經驗,這樣至少 NPM 和 Webpack 就不用再裝了XD。(對了,本篇就不寫 NPM 和 Webpack 的詳細安裝方法,因為別的教學都有寫,而且我相信你一定看得懂怎麼裝XD)

我覺得就先從單純的 HTML+CSS+JS 組成的簡單頁面開始來看,比方我們的專案目錄底下有這些靜態的檔案:

專案目錄名稱/
│
├── index.html
└── src/
      ├── css/
      │     ├── style.css 
      │     └── buttons.css 
      └── js/
             ├── init.js 
             └── main.js

分別看一下它們的內容吧。

index.html 長這樣:

<!-- index.html -->

<!DOCTYPE html>
<html lang="zh_TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>認識 Webpack</title>

    <!-- 載入 bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">

    <!-- 載入自製的css -->
    <link rel="stylesheet" href="src/css/style.css">
    <link rel="stylesheet" href="src/css/buttons.css">
</head>
<body>
    <h1>認識 Webpack</h1>
    <button id="my-button">不是有很多其他教學嗎,幹嘛又寫?</button>
    <p id="my-desc">想單純認識 Webpack 嘛</p>

    <!-- 載入 jquery & bootstrap -->
    <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>

    <!-- 載入自製的js -->
    <script src="src/init.js"></script>
    <script src="src/main.js"></script>
</body>
</html>

其實很單純,除了載入 jQuery,還放進我慣用的 bootstrap (這個非必要)。

src/css/style.css 長這樣:

/* src/css/style.css - 定義基本的樣式 */

body {
    font-family: Helvetica, Arial, sans-serif;
    text-align: center;
}

h1 {
    font-size: 28px;
    margin: 20px;
}

p {
    border: 1px solid black;
    padding: 20px;
    margin: 30px auto;
    width: 50%;
    font-size: 18px;
}

src/css/buttons.css 是這樣:

/* src/css/buttons/css - 定義一些按鈕的樣式 */

button {
    border: 1px solid black;
    background-color: white;
    padding: 8px;
    font: inherit;
    cursor: pointer;
    outline: none;
}

button:hover {
    background-color: #ccc;
}

css 檔都很單純,隨便你寫都可以。

src/js/init.js 是:

/* src/js/init.js - 定義一些 DOM 變數 */

var myButton = $('#my-button');
var myDesc = $('#my-desc');

就只是很假掰地用來定義一些 dom 變數。

src/js/main.js 也很簡單:

/* src/js/main.js - 寫一些 jQuery 效果 */

myDesc.hide();
myButton.on('click', function(e){
    myDesc.toggle();    
});

簡單來說,就是我按了按鈕 myButton,就會去 show/hide 底下的描述區塊 myDesc。
你一定會發現 init.js 和 main.js 根本可以很直覺地寫在一起,但我在這裡刻意分離它們,除了裝逼外也是為了描述相依性所做的簡單配置。

init.js 和 main.js 有相依關係,就是指它們的載入順序不能隨便調換,因為 init.js 裡有定義 main.js 需要的變數,所以你在使用 main.js 前,一定要先載入 init.js,不然就會 GG。

到這裡,請先確定好你的 demo 頁是可以正常運作的 (按按鈕會show/hide下方描述)。

先這樣看待 Webpack

它是一個打包 “前端” 檔案的工具,它也是用 javascript 寫的,要使用 Webpack 不是在它身上點兩下,而是在命令列打指令執行,然後它就會將你網站目錄下某個「來源目錄」裡的前端檔案 (js, css/scss, 圖片檔…),做一些優化和打包,然後再另存到其他「目標目錄」下,而你的網頁只要載入這些處理後的目標檔案就好。

要安裝 Webpack 需要透過 NPM 來幫忙將它安裝在網站專案上。

安裝 NPM

NPM 是所謂套件管理工具,可以協助我們快速安裝 JavaScript 工具套件,我們需要它來幫忙安裝 Webpack,所以先下載安裝 NPM。(還沒裝的人快去 google 怎麼裝,我等你 ;D )

接著在專案目錄 (跟 index.html 同層) 下執行 npm init:

$npm init

之後會提示一些問題,像是專案名稱,這個隨你填,我是填 webpack-test,然後 license 我填 MIT…,完畢後你就會發現多了一個 package.json。

接著我們要用 NPM 安裝 Webpack,在專案目錄下執行 npm install webpack –save-dev:

$npm install webpack --save-dev

跑完了就會發現 webpack 開始安裝並且 package.json 裡的 devDependencies 屬性多了一個 webpack 的相依套件描述。

package.json 就是在紀錄你的專案用了哪些套件,邊裝邊紀錄,這樣對後續將網站專案部署到別的地方很有幫助,之後只要下 npm install 就會都裝好。來看一下 package.json 的內容:

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
  },
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "webpack": "^3.5.1"
  }
}

開始試著使用 Webpack

一開始先修改一下 package.json,因為我們需要透過 NPM 來執行 Webpack,在 scripts 屬性描述的地方加上一段 build 指令:

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build": "webpack src/js/main.js dist/bundle.js",
  },
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "webpack": "^3.5.1"
  }
}

這段 “build”: “webpack src/js/main.js dist/bundle.js” 就是指在執行 npm run build 後,會使用 webpack 將「來源檔案」 src/js/main.js 打包成「目標檔案」dist/bundle.js。

存檔後如果你直接在命令列執行 npm run build:

$npm run build

應該會出現一堆錯誤訊息,為什麼呢?因為 main.js 沒有「匯入」 init.js,我們是用 index.html 的方式載入 init.js 的,Webpack 沒那麼神,不知道要去載入 init.js。

JavaScript 的 Module 載入機制 – ES6 (ES2015)

js 可以 import 其他的 js,但要使用用 ES6 的 Module 語法,所以要用 export 和 import 的方式,讓 main.js 可以匯入 init.js 裡的變數定義。

src/js/init.js 改完後的內容:

/* src/js/init.js */

export var myButton = $('#my-button');
export var myDesc = $('#my-desc');

主要是前面加上 export,把定義匯出來給其他檔案使用。

src/js/main.js 改完後的內容:

/* src/js/main.js */
import {myButton, myDesc} from './init';

myDesc.hide();
myButton.on('click', function(e){
    myDesc.toggle();    
});

主要是第一行加上一段 import 描述,把 myButton 和 myDesc 兩個元件從 init.js 匯入使用。

改完以後,你會發現你的瀏覽器應該不支援這種寫法,所以現在直接開 DEMO 網頁,應該會GG。先不要太急,因為 Webpack 看得懂 ES6,先讓它 Build 看看,在網站專案目錄下執行 npm run build。

$npm run build

如果順利的話,Webpack 會提示成功打包到 dist/bundle.js 的訊息,然後你的專案目錄下就會多了一個 dist 的目標目錄,裡面就會有一個 bundle.js,它就是打包完的目標檔案。

將index.html 改為載入 dist/bundle.js

打包好的目標檔案一定是主流瀏覽器都看得懂的「優化後」的檔案,所以改成載入它就好:

    ...(略)...
    <!-- 載入自製的js -->
    <!--<script src="src/init.js"></script>-->
    <!--<script src="src/main.js"></script>-->
    <script src="dist/bundle.js"></script>
    ...(略)...

DEMO 網站應該回復正常運作了。

內建的JS最小化功能

打開 package.json,在 build 指令下再加一行: “build:prod”: “webpack src/js/main.js dist/bundle.js -p”
跟 build 很像,只是最後多加一個 -p。

在專案目錄下執行:

$npm run build:prod

此時 webpack 會幫忙把 bundle.js 以最小化的方式打包起來。

下集待續

第一集我們重點放在認識 Webpack 是一個什麼東西,然後簡單看一下它怎麼運作,不貪快。

現在你一定會覺得意猶未盡吧,看看那個 build 指令也太弱了吧,怎麼只能打包一個檔案呢?說好的打包一大堆檔案呢?

下一篇我們來談 webpack.config.js 設定,包含怎麼把 css/scss 也一起處理好再打包!

下一篇:http://www.mrmu.com.tw/2017/08/18/webpack-tutorial2-css-scss/


標籤:,

分類:,

本文作者是Audi Lu

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。

*

*

*

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料