---
# System prepended metadata

title: webpack
tags: [webpack]

---

---
title: webpack
robots: noindex, nofollow
lang: zh-tw
dir: ltr
breaks: true
tags: webpack
disqus: hackmd
---

# Webpack

## 安裝套件包
- 確認 node 版本 → `node -v`
- 確認 npm 版本 → `npm -v`
- 安裝 npm → `npm install` / `npm i`
- 用 npm 安裝套件 → `npm i PACKAGE` (`npm i webpack`)
- 指定套件版本 → `npm i PACKAGE@x.x.x` (`npm install webpack@5.4.0`)
- 安裝至 devDependencies → `npm i PACKAGE -D`
- 確認 yarn 版本 → `yarn -v`
- 安裝 yarn → `yarn install`
- 用 yarn 安裝套件 → `yarn install PACKAGE`

> - 當專案沒有 `node_modeuls/` 資料夾時需要先安裝 npm
> - 所有的 package 都是小寫

---

## webpack.config.js
### `devtool`
- `sourcemap` → 打包的方式，官方有提供七種打包方式，開發時通常使用 `inline-source-map` 即可，上 prodcution 會拿掉

```javascript
// production 發佈就拿掉 source-map
devtool: DEV_MODE ? 'inline-source-map' : false,
```

### `output`
webpack 會將專案中的所有 JS 打包成一個檔案
- `filename` → 打包後的檔名
- `path` → 打包後的檔案要存放的路徑

### `context`
- `path.resolve('src')` → 指定所有的檔案都從 src 資料夾開始

### `entry`
程式進入點
```javascript
// 完整地寫完
entry: './src/index.js'

// 有先指定進入的資料夾位置，因為有加 context, 所以就不需要寫 src
context: path.resolve('src'),
entry: {
  'app': './app.js'
},
```

---

## package.json
### `scripts`
- `start` → 前端的不成文規定，在開發時皆使用這個指令
	- `webpack --mode development` → 以開發者模式啟動 webpack 打包

```bash
# 使用 npm 啟動使令
$ npm run start

# 使用 yarn 啟動指令
$ yarn run start
```

- `start:watch` → 觀察 `src/` 裡的檔案，如果有異動則即時重新打包一次
	- `webpack --watch --mode development`

```bash
# 使用 npm 啟動使令
$ npm run start:watch

# 使用 yarn 啟動指令
$ yarn run start:watch

# Ctrl+C 退出
```

- `build` → 前端的不成文規定，上 production 時皆使用這個指令
	- `webpack --mode production` → 以 production 模式啟動 webpack 打包

```bash
# 使用 npm 啟動使令
$ npm run build

# 使用 yarn 啟動指令
$ yarn run build
```

---

## 環境變數
使用套件 `cross-env` 以及環境變數 `NODE_ENV` 取代 `--mode development/production`
- `NODE_ENV` → webpack 裡面預設需要支援的環境變數，僅支援 `development` 和 `production` 這兩個關鍵字
```json
// package.json
"scripts": {
  "start": "cross-env NODE_ENV=development webpack",
  "build": "cross-env NODE_ENV=production webpack"
}
```
- `process.env.NODE_ENV` → 可讀取到目前的環境

---

# 模組化概念

## ES6 Module
### 輸出
#### `export`
將 function 輸出，讓別的檔案也能使用，類似 OOP 裡 public 概念，非原生 JS 語法
```javascript
export function add(a, b) {
  return a + b;
}
```

#### `export default`
一個 JS 檔 (一個 module) 裡只能有一個 `export default`，`export default` 優先使用，不夠才使用一般的 `export` (沒有數量限制)
```javascript
class MyClass {
  foo(){
    console.log('foo');
  }
}

export default MyClass;
```

### 引入
#### `import`
- 一般的 `export` 引入需要加上花括號 `{ function 名稱 }`
- `export default` 引入直接寫上 function 名稱

```javascript
// export
import { add, subtract } from "./utils/esm";

// export default
import MyClass from './utils/esm';

// 合併上面兩行
import MyClass, { add, subtract } from "./utils/esm";
```

#### `from`
指的是 `webpack.config.js` 中 `entry` (程式進入點位置)的相對路徑
原本應該包含檔名、副檔名都要完整寫出來，但 webpack 預設會認定 .js 副檔名所以可省略，而若要 import 的檔名剛好為 index 也可以一併省略
```javascript
// 完整的寫法
import { add, subtract } from "./utils/esm/index.js";

// 省略副檔名
import { add, subtract } from "./utils/esm/index";

// 省略 index 檔名
import { add, subtract } from "./utils/esm";
```

## CommonJS
### 輸出
只能 `module.export` (一個個輸出)，沒有 `export default`
```javascript
function multiply(a, b) {
  return a * b;
}
function divide(a, b) {
  return a / b;
}

module.exports = {
  multiply: multiply,
  divide: divide,
};
```

### 引入
```javascript
const utils = require('./utils/commonjs');

utils.multiply(2, 2));
utils.divide(2, 2);
```

---