Hello webpack! 基礎設定

Hello webpack! 基礎設定

Why do we need Webpack?

在沒有打包工具以前, 一個網頁程式中包含多個CSS, HTML, JS, 而JS中有些可能是外部套件,有些可能會高度耦合, 導致import的順序不可輕易更動。後來有了Grunt和gulp, js可以被整合成一支檔案, 就不用擔心引入的順序問題, 可是這些工具無法判別哪些是套件。

Webpack可以判別哪些是額外使用的套件, 並且幫助我們打包程式碼, 不管是javascript, typescript, css, sass…, Webpack都可以幫我們把繁雜且交錯的程式碼整合成一份, 就不用再去擔心引入的順序問題

範例

在webpack之前

在還沒有引入webpack之前, 我們的專案會這樣寫

hello.js和index.js可以被當作是套件, 或是js模組。

在hello.js中定義一個function
hello.js

1
2
3
function hello() {
console.log('hello world!');
}

在index.js中呼叫
index.js

1
hello();

這時打開瀏覽器, 會跳出錯誤:
hello is not defined

問題並不在這兩支檔案的程式碼中,而是他們在index.html中引入的順序問題。

1
2
<script src="./src/index.js"></script>
<script src="./src/hello.js"></script>

呼叫hello的index比hello被定義的位置hello.js還要先被import和執行, 此時hello尚未產生。

正確的順序應該是這樣

1
2
<script src="./src/hello.js"></script>
<script src="./src/index.js"></script>

這個例子說明了相依性(dependency)產生的問題
現在只有兩支檔案, 所以記憶他們的順序並不困難, 可是當引入的檔案多,且彼此的相依關係又很複雜的時候,就會要花很多心力。
這時可以使用Webpack幫助我們整合內部的模組和外部套件,打包成一支js,也只要在html中引入這一支js就好,這支檔案就是我們的入口檔案(entrypoint)

引入webpack

在終端機中使用npm init -y來啟用npm,參數-y代表默認預設配置, 就不用自己設定一堆有的沒的。

這個指令會產生一個package.json檔案

package.json

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "webpack_tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

接著安裝webpack, 在終端機輸入以下指令
npm install webpack webpack-cli --save-dev
安裝webpack和其command line interface, 指令介面工具, 就是可以在終端機中輸入webpack的指令啦

--save-dev的意義可以見這裡

現在package.json會變這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"name": "webpack_tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
// ---- 套件
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
}
}

此時工作目錄中新增了一個資料夾: node_modules, 套件的原始碼都會放在這裡

之後若是有人下載這份專案, 想要在自己的電腦上運作的話, 可以看這份檔案找套件的相關紀錄, 以及跑npm install把需要的套件下載起來

webpack設定檔

在根目錄新增一支webpack.config.js的檔案

這支檔案會是一個物件

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
// ----- 必填
// entrypoint: 載入所有需要的套件的地方, 在打包時webpack會從這裡開始跑
entry: './src/index.js',
output: {
// 完成打包之後產生的檔案名稱
filename: "bundle.js",
// 打包之後檔案會被放在哪裡
path: './dist',
},
mode: 'none',
// ----- 必填
}

在package.json新增一個腳本

1
2
3
4
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},

我們可以把html中的script tag移除了, 改成引入剛剛設定的output檔

index.html

1
2
<!-- 我們要引入的js是打包完的, 根據剛剛的設定, 它會在dist資料夾中 -->
<script src="./dist/bundle.js"></script>

我們需要在剛剛設定的入口(entrypoint)檔案中import所有我們需要的東西, 打包會從這裡開始
./src/index.js

1
2
3
import hello from './hello.js';

hello();

被引入的檔案要記得export

1
2
3
4
5
6
function hello() {
console.log('hello world!');
}

// es6
export default hello;

產生dist

設定完之後,可以來打包看看了。
npm run build開始打包,沒想到跳錯


這個錯誤是說,我們的設定檔不符合webpack的api要求, 因為目前輸出的路徑是相對路徑, 而api要求絕對路徑

我們目前的輸出(output)路徑是這樣寫

1
2
3
4
5
output: {
filename: "bundle.js",
// 相對路徑
path: './dist',
},

要改成絕對路徑, 可以運用node.js底下的path改寫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 引入node.js中的path物件
const path = require('path');

module.exports = {
entry: './src/index.js',
output: {
filename: "bundle.js",
path: path.resolve(__dirname, './dist'),
// 要是絕對路徑
// path.resolve會產生一個絕對路徑
// __dirname, 指向目前的資料夾, 例如目前是webpack_tutorial/, __dirname就是webpack_tutorial/, resolve會將這個路徑與後方的參數結合, 解析出絕對路徑
// ./表示是目前的同層資料夾, 以現在的例子來說就是在根目錄下, 產生的一個dist資料夾, 路徑為:webpack_tutorial/dist
},
mode: 'none',
}

可以看到根目錄底下產生一個名為dist的資料夾, 裡面放的是打包後的檔案, 檔名跟我們在設定檔中作的設定一致

js也能運作了

參考來源

Webpack 4 in 2020

path module

tags: webpack
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×