[FE201] webpack 讓你把各種資源包在一起(基本介紹篇)


Posted by s103071049 on 2021-07-07

webpack is a module bundler

從模組化開始談

module (模組/模塊)

當我完成某個功能,我要如何方便地分享給其他人 ? 最簡單的方式就是寫一個 FUNCT,把 FUNCT 給別人用。如果不只有一個 FUNCT,就包成一個檔案。

NODE.JS => require/ module.exports()

在 utils.js 寫 code,在 node.js 裡面會將 Utils 這個物件給輸出

// utils.js
const Utils = {
  first: function(str) {
    return str[0]
  },
  last: function(str) {
    return str[str.length-1]
  }
}
module.exports = Utils

使用者只要 require 進來,引入進來就可以用裡面的 method。

// index.js
const utils = require('./utils')

console.log(utils.first('abcde'))

基本上 module 很多都是以檔案為單位。接著透過某種方式將 module 對外輸出,接著其他人就可以將它引入進來使用。

瀏覽器 => 透過全域變數

瀏覽器沒有 require 的語法,所以之前使用 jQuery,都是直接 script 東西進來,接著就有全域變數 $ 或全域變數 jQuery 這個物件可以使用。

因為透過全域變數輸出 module,所以有了命名衝突的問題

如果我有兩個 library,一個叫 jQuery,一個叫 math(裡面 $ 表示整數),現在我同時引用這兩個 library,我就不曉得到底 $ 代表的是甚麼。

所以 jQuery 提供了 jQuery.noConflict()

因為瀏覽器沒有 require 所以也只能透過全域變數進行輸出,因此會有命名衝突的缺陷。node.js 就沒有,因為它 import 進來的名字可以自己改變。所以 node.js 這套 requrie 在 node.js 上面才可以用,在瀏覽器上面不行。

網頁上的 JS 與 node.js

js 是一個程式語言,在網頁上執行時它的執行環境(runtime)是瀏覽器,在電腦上用 node.js 執行時,它的執行環境就是 node.js。所以,在這兩個地方執行 js 是不同的兩件事情。

在 node.js 上執行有 require 可以用,在瀏覽器上執行沒有。

模組化規範各有不同

早期滿多人試著解決這個問題,因為在網頁上沒有模組機制非常麻煩。所以有些人自己實做了一些規範,CommonJS, AMD, UMD, 這些規範就像個家廠牌的手機充電線,它的功能目的都是一樣就是充電,但蘋果的頭與安卓的頭不同。它的目的都是一樣,但用法與規範不同,所以不同規範也可能不能相容。

它規範要用甚麼語法去使用一個模組,要怎麼將模組給別人用。 node.js 用的這套規範就叫做 CommonJS

上述的這幾個都不是官方的規範!

直到後來瀏覽器原生支援了 ES Modules 這個規範,可以用 import, export的語法。

舉例、

// utils.js
export function first(str) {
  return str[0]
}
// index.js
import {first} from './utils.js'
console.log(first('abc'))
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src= './index.js' type= 'module'></script>
</head>
<body>

</body>
</html>

這邊無法以檔案的方式打開,要用 server 開。

目前問題

  1. 支援度 : 這些規範比較新,在舊的瀏覽器上無法跑
  2. 技術相對早期階段 : 近幾年才出來,瀏覽器才支援,雖然已經有點成熟但還在相對早期階段。

結論

瀏覽器未支援的東西,用工具自己轉換就好了,所以有了這些工具,讓我們用模組化的規範,透過某個程式,幫忙 compile 之後產生出的檔案就可以丟到瀏覽器上執行。簡單地說,webpack 把我的模組全部都包在一起做一些轉換,我就可以在瀏覽器上使用這些東西。

把模組包在一起 === modules bundle

事實上,webpack 不只包模組,它將模組的概念推得更遠(將圖片、css 也當作模組),現階段,可以先理解成將 js 的模組包在一起讓他可以在瀏覽器上使用的一個工具。


環境設置

https://webpack.js.org/guides/getting-started/
npm init -y,再 npm install webpack webpack-cli --save-dev
開發專案,會使用各種不同工具,因此會安裝有不同的設定。會需要先 compile 過的 code 不會寫再根目錄,而是會寫在 src (source code) 底下,工具轉換完的 code 再放到其他地方。

所以,先開一個資料夾 src mkdir src

現在讓 index.js, utils.js 都放到 src 裡面。

const utils = require('./utils')

console.log(utils.first('abc'))
// utils.js
const Utils = {
  first: function(str) {
    return str[0]
  }
}

module.exports = Utils

確定 node index.js 在 node.js 上執行沒有問題

接著下指令 npx webpack 就會啟用 webpack 這個工具幫我們打包,webpack 預設的設定會去找 src 資料夾下 index.js 這個檔案,它會把這個當作程式的入口點(程式一開始就去執行這個檔案),打包好它會把東西放到 dist (distribution)。

因為之前設定過 minify, uglify 所以打包完的 main.js 會變成一個看不懂很醜的東西。打包好在執行一次 node dist/main.js 還是會出現相同的結果。

接著回到原本的 index.html,修改原本的 script => <script src= 'dist/main.js'></script>,打開檔案發現:我們寫的 require 的東西可以在瀏覽器上執行。

webpack 幫我們在瀏覽器上實作 require 這個功能,再幫我們把模組包在一起,所以我們才可以在瀏覽器上用這個東西。

利用關鍵字 js beautify => js beautify,可以將 dist/main.js 的 code 貼到上面,檢視其實作流程。

如果不是預設,可以做設定檔,touch webpack.config.js 如果不要預設檔名也可以改,改的話下 webpack 指令就要用不同的下法。

const path = require('path');

module.exports = {
  mode : '',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

entry 表示程式的入口點,將模組引入進來做事情的地方就叫做 entry(入口點),通常都是 index.js,如果只有一個檔案通常那個檔案就會是 entry。

output 表示輸出的內容。其中 __dirname 會抓到現在執行的資料夾。所以 path: path.resolve(__dirname, 'dist'), 是說現在資料夾底下 dist 這個資料夾是我要輸出的路徑位置。

mode 沒有給預設為 production,production 表示正式環境/生產環境的版本,所以預設是 production,才會打包出已經壓縮過的 code。另外還有另一種是 mode: development,用這個模式打包出的 code 會比較看得懂,因為它不會幫我做壓縮。

先調整 package.json => 在 script 加入 "build" : "webpack",,所以現在我在 node.js 上打 npm run build,就會去執行 webpack 這個指令。接著 webpack 就會去找 webpack.config.js 這個檔案,然後根據這個設定檔進行打包。打包出來的檔案會把我要用的模組甚麼的都打包進去。

重點

  1. 安裝工具
  2. 找官方文件看怎麼執行
  3. 改設定檔

#Webpack







Related Posts

介紹 Git

介紹 Git

[FE302] React 基礎 - hooks 版本 (Function component vs Class component)

[FE302] React 基礎 - hooks 版本 (Function component vs Class component)

3. 優美地定義 React 型別

3. 優美地定義 React 型別


Comments