webpack4小白學習全過程記錄
webpack :現代 JavaScript 應用程式的靜態模組打包器
前言:本文描述一個小白學習webpack4從零開始的完整過程全紀錄,可以說完全以一個初學者的口吻來寫這篇文章的,與此同時這篇文章還會長期更新,不足之處還望大佬雅正!
大白話講webpack
對於小白來說,看到一些專業的術語就腦殼疼
什麼是webpack?
簡單來講,就是把我們寫好的程式碼打包。
怎麼個打包法,壓縮程式碼,相同資源抽取,處理一下瀏覽器不識別的程式碼(如ES6+、TS、SASS等)。
一句話,用不到就扔掉,能壓縮就壓縮,能相容就相容
初探webpack
①、安裝npm
npm是世界上最大的軟體登錄檔,使用npm我們可以快速安裝各種大小型軟體和庫
下載:在node.js中都自帶了npm,所以我們下載node.js即可
node.js官網: https://nodejs.org/en/
下載完後,我們可以在dos命令列下可以看到node.js的版本和npm的版本 node -v npm -v
②、建好目錄架構
①、新建練習檔案目錄 ex1
①、在ex1目錄下新建原始檔目錄 src
②、在src目錄下新建入口檔案 index.js
形成的目錄結構如下:
③、初始化package.json
package.json檔案定義了這個專案所需要的各種模組,以及專案的配置資訊(比如名稱、版本、許可證等元資料)。
在ex1目錄下使用命令:
npm init -y
init指令會詢問一系列的問題,並將你的配置寫成一個package.json檔案。
如果使用了-f|--force|-y|--yes這些引數,那麼會生成一個預設的package.json檔案。
這個init過程很快,可以看到在ex1目錄下多了個package.json檔案
④、安裝webpack
提示:webpack4.0以上版本的webpack的腳手架webpack-cli已經被分離出來,需要另外安裝。
安裝webpack分為 全域性安裝 和 本地安裝 (區域性安裝)
全域性安裝(不推薦) npm install webpack webpack-cli -g
(-g就是全域性安裝)
本地安裝 npm install webpack webpack-cli -D
(-D 就是安裝到開發環境)
安裝成功後如圖所示:
再來看下我們的檔案目錄發生了什麼變化:
node_modules資料夾主要是用於放用包管理工具下載安裝了的包,這個檔案的內容有很多
package-lock.json鎖定了包的版本,確保能夠避免包版本不同產生的問題。
⑤、使用npx進行打包
npx 會幫你執行依賴包裡的二進位制檔案。
npx會自動找到node_modules/bin 的webpack.cmd去執行,免去了script的配置
在src的目錄下新建一個名為 demo1.js 的檔案
在 demo1.js 中寫入如下內容
module.exports = '這是common.js的語法,在node端執行,把我用webpack打包之後,就可以在瀏覽器上運行了'
在 index.js 中寫入如下內容
let d1 = require('./demo1.js'); console.log(d1);
使用命令進行打包
npx webpack
結果如圖:
打包後我們可以發現在ex1目錄下多了個 dist 資料夾
這個dist 資料夾中有個 main.js檔案,是打包後的js檔案
為了檢視結果,我們可以在dist目錄下新建一個 index.html 檔案
在index.html使用script標籤引入main.js
<script src="./main.js"></script>
在控制檯裡面就可以看到這麼一句話:'這是common.js的語法,在node端執行,把我用webpack打包之後,就可以在瀏覽器上運行了'
細心的你可能會發現上面打包的結果有一個 黃色的警告
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concep...
黃色警告意為webpack沒有指定是 開發模式development 還是 生產模式productio n
那我們就可以在命令後面加上 --mode development
看,是不是沒有了黃色警告提示。
npx的缺點:雖然使用npx可以快速的幫我們打包,但是不夠靈活,比如打包後文件夾名字都是固定 dist,因此我們需要定義webpack打包的配置檔案,這樣才可以隨心所欲的打包
webpack配置
①、新建配置檔案
我們現在ex1的目錄下新建一個名為 webpack.config.js 檔案
由於webpack是基於node,所以要遵循common.js規範
②、入口(entry)
入口起點(entry point)指示 webpack 應該使用哪個模組,來作為構建其內部依賴圖的開始。進入入口起點後,webpack 會找出有哪些模組和庫是入口起點(直接和間接)依賴的。
entry 屬性的單個入口語法
module.exports = { entry: './src/index.js' };
③、出口(output)
output 屬性告訴 webpack 在哪裡輸出它所建立的 bundles,以及如何命名這些檔案。
預設值為 ./dist。
在 webpack 中配置 output 屬性的最低要求是,將它的值設定為一個物件,包括以下兩點:
- filename 用於輸出檔案的檔名。
- 目標輸出目錄 path 的絕對路 徑。
④、入口和出口的整合
webpack.config.js
// 基於node,遵循common.js規範 const path = require('path') // 引入node.js Path 模組 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') } }
由於path要求為絕對路徑,所以我們使用了 path.join 拼接路徑這個node的語法,
node不能在瀏覽器端執行,所以我們可以利用 vscode 編輯器 的 Code Runner 外掛來檢視當前路徑的結果
在webpack.config.js保留如下程式碼:
const path = require('path') // 引入node.js Path 模組 console.log(path.join(__dirname, './build'));
結果如圖:
在webpack.config.js配置好出入口後,那我們可以嘗試著打包了
打包結果如圖:
在ex1的目錄下多了個 build檔案以及其目錄下的bundle.js檔案
那麼說明了我們的配置是成功的!
⑤、npm指令碼
可以參考阮一峰老師的部落格: http://www.ruanyifeng.com/blo...
npm 允許在package.json檔案裡面,使用scripts欄位定義指令碼命令。
npm 指令碼。它的優點很多
- 專案的相關指令碼,可以集中在一個地方。
- 不同專案的指令碼命令,只要功能相同,就可以有同樣的對外介面。使用者不需要知道怎麼測試你的專案,只要執行npm run test即可。 可以利用
- npm 提供的很多輔助功能。
在我們原有的package.json中,我們可以發現有一個這樣"scripts"欄位
"scripts": { "test": "echo \"Error: no test specified\" && exit 1" }
因此我們可以嘗試使用 npm tes t 命令看下會有什麼結果
結果執行了echo語句
我們可以利用npm指令碼來替代webpack語句,我們修改一下test欄位對應為webpack命令
"scripts": { "test": "webpack" }
接著我們嘗試使用 npm test 命令來執行一下
可以發現我們已經打包成功了。
那麼有的朋友就會問了,一定要test嗎?
好,我們隨便來個命令,就 abc
在test欄位下,我們加多一個abc欄位,如下面程式碼所示:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "abc": "webpack" }
執行 npm abc 命令看看結果怎樣
哎,奇怪了呀,這是什麼情況,有一點很明確的是,並沒有執行webpack打包執行命令。
不急不急,我們先來看下提示先:
注意到這句話: where <command> is one of:
也就是說我們的命令應該下面那些,也就是說只能使用 npm <command>,這個command應該是提示其中之一,我們在提示中可以發現有 test 命令
也就是說只要滿足了上面欄位的其中之一,就可以使用 npm <command>
但是這些命令是npm自帶的,並不是所有都可以用來執行script指令碼的。
除此之外,還有一個start命令也是可以直接執行的,如圖
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack" }
那麼問題來了,我們怎麼知道哪些命令可以直接執行script,要一個個嘗試豈不是很麻煩嗎?
此時我們可以使用npm run <command> 命令來直接執行指令碼
使用npm run script執行指令碼的時候都會建立一個shell,然後在shell中執行指定的指令碼。
所以這次我們不用再為使用什麼script欄位而煩惱了。
好,我們再來試一下abc欄位
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "abc": "webpack" }
哈哈,終於成功了!
⑥、模式設定
在之前我有講到過,黃色警告是由於沒有設定模式而出現,那時候提的方法是每次都要在執行打包的命令的時候加上這麼一句 --mode development/production
那這樣是不是很麻煩,所以我們可以在配置檔案這樣定義
mode: 'development'
那麼,此時我們的webpack.config.js的檔案內容如下:
// 基於node,遵循common.js規範 const path = require('path') // 引入node.js Path 模組 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development'// 模式 }
此時,我們再打包試一下,結果如圖:
我們可清楚地看到黃色警告已經去掉了
webpack入門
①、關係依賴
在我們的package.json檔案裡,可以看到這麼一個欄位 "devDependencies"
除此之外還有一個與之相關的欄位叫 “dependencies ”
*devDependencies 與 dependencies 的區別
devDependencies裡面的模組只用於開發環境(development)
而 dependencies 裡面的模組是需要釋出到生產環境(production) 。
比如我們有一個專案要用到jQuery,在線上執行的時候如果沒有jQuery包的依賴執行就會報錯,這時候就應該把這個依賴寫入 dependencies
而我們使用的一些構建工具如webpack這些只是在開發中使用的包,上線以後就和這些包沒關係了,所以將這種依賴寫入 devDependencies
在我們使npm安裝模組的時候,都會使用一個命令
npm install(可以簡寫為 npm i)
與此對應的還有這兩個重要的對應引數:
--save(可以簡寫為-S)
--save-dev(可以簡寫為-D)
①、npm install m
- 將m模組安裝到node_modules目錄中
- 不會修改package.json
- 執行npm install命令時,不會安裝m模組
②、npm install m –save:
- 把m模組安裝到node_modules目錄中
- 會在package.json的 dependencies 屬性下新增m模組
- 執行npm install命令時,自動安裝m模組到node_modules目錄中
②、npm install m –save-dev:
- 把m模組安裝到node_modules目錄中
- 會在package.json的 devDependencies 屬性下新增m模組
- 執行npm install命令時,會自動安裝到node_modules目錄中
②、本地伺服器(devServer)
webpack-dev-server 能夠用於快速開發應用程式
裡面包含了很多豐富的功能,其中最為重要的當然是能夠監聽原生代碼的修改,利用熱載入自動重新整理瀏覽器,這樣大大地方便了我們進行程式碼的除錯
第一步:安裝webpack-dev-server
在前面,我有講到關係依賴這方面的知識,關於 devDependencies 與 dependencies 的區別,相信大家都能看懂。很明顯 webpack-dev-server 只是用來本地除錯的,上線之後就用不上了,那麼我們可以很明確將webpack-dev-server 放到devDependencies中
執行如下命令:
npm install webpack-dev-server -D
安裝好後,我們再來看一下package.json檔案的變化
第二步:配置webpack-dev-server
配置專案 | 描述 | 注意 |
---|---|---|
contentBase | 告訴伺服器從哪個目錄中提供內容 | 推薦使用絕對路徑。 |
compress | 一切服務都啟用 gzip 壓縮 | compress: true |
host | 指定使用一個 host。預設是 localhost | 可以外部伺服器訪問 |
https | 預設情況下,dev-server 通過 HTTP 提供服務 | https: true |
open | 啟用 open 後,dev server 會開啟瀏覽器 | 預設瀏覽器,可以指定其他 |
port | 指定要監聽請求的埠號 | 預設8080 |
其實webpack-dve-server的配置專案遠遠不止這些,這裡只是列舉了一部分
我們先在package.json中新增script指令碼
"dev": "webpack-dev-server"
①、contentBase解析
再回來看下我們的webpack.json.js檔案,webpack-dve-server配置的欄位為devServer,我們先不配置先,看看會怎麼樣?
此時webpack.json.js的內容
// 基於node,遵循common.js規範 const path = require('path') // 引入node.js Path 模組 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development'// 模式 }
執行命令:
npm run dev
看下結果:
現在可以清楚的看到,我們的專案已經執行在 http://localhost :8080
好的,那麼我們在瀏覽器輸入這個url看看這個頁面會顯示什麼
如圖所示:
這裡只顯示了我們整個檔案的目錄
預設情況下,contentBase將使用當前工作目錄作為提供內容的目錄
為了證明這點,我們在ex1的目錄下新建一個index.html
現在的目錄結構如下:
現在在根目錄下的index.html寫入如下內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> 這是根目錄的index.html </body> </html>
好,現在在重新執行命令 npm run dev
然後在瀏覽器開啟 http://localhost :8080 頁面
我們就可以發現結果不同了
那麼這就可以證明了
預設情況下,contentBase將使用當前工作目錄作為提供內容的目錄
好,現在我們要把內容目錄設在build資料夾下
我們現在build目錄下新建一個index.html檔案
寫入如下內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> 這是build檔案下的index.html </body> </html>
這時候回到我們的配置檔案(webpack.config.js)
寫入如下內容:
devServer: { contentBase: './build' }
現在webpack.config.js的內容如下:
// 基於node,遵循common.js規範 const path = require('path') // 引入node.js Path 模組 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development',// 模式 devServer: { contentBase: './build' } }
好,現在萬事俱備,只欠東風。現在我們再重新執行 npm run dev 命令
同樣的,在瀏覽器可以看到結果
②、open
啟用 open 後,devServer 會開啟瀏覽器。
在devServer設定如下:
open: true
注意,這裡的true是布林值,不是字串
在啟用命令 npm run dev後,devServer 會開啟預設瀏覽器
大家用window一般都是IE瀏覽器作為預設瀏覽器
那麼此時如果我們想使用谷歌瀏覽器來啟動應該怎麼設定呢?
此時,我們可以在package.json對script指令碼進行設定,
// 開啟預設瀏覽器 "dev": "webpack-dev-server --open" // 開啟谷歌瀏覽器 "dev": "webpack-dev-server --open chrome" // 開啟火狐瀏覽器 "dev": "webpack-dev-server --open firefox"
*提示:如果在script設定了--open,那麼可以不用在配置檔案設定open欄位了
③、source map
由於使用webpack打包後,原來的程式碼經過壓縮,去空格,bable的編譯之後,已經變成我們不認識的程式碼了,為了方便我們除錯調式程式碼,定位bug,source map就出現了
在webpack.config.js中,devtool選項用於控制是否生成,以及如何生成 source map。
loader入門
css loader安裝
loader 用於對模組的原始碼進行轉換。loader 可以使你在 import 或"載入"模組時預處理檔案。
webpack本身只能處理javascript檔案,而對於css檔案需要loader來處理
對於css處理,我們常用的有這兩種loader: css-loader 和 style-loader
使用命令安裝這兩個loader
npm i -D style-loader css-loader
接下來在src檔案下新建名為 style 的資料夾,在style 下新建名為 index.css 檔案
為了讓效果更加直觀,往 index.css 檔案寫入如下內容
body{background-color: yellowgreen;}
接著在我們 src目錄下的 index.js 檔案中使用ES6的模組語法 import 將index.css檔案匯入進來
import './style/index.css'
我們先不配置loader,看看瀏覽器會提示什麼
執行 npm run dev 命令,看看會發生什麼,如圖所示:
提示模組解析失敗,需要loader進行處理
loader配置
有三種使用 loader 的方式:
- 配置(推薦):在 webpack.config.js 檔案中指定 loader。
- 內聯:在每個 import 語句中顯式指定 loader。
- CLI:在 shell 命令中指定它們。
我們選擇在webpack.config.js中配置loader
基本寫法如下:
module: { rules: [ { test: /\.css$/,// 利用正則表示式匹配檔名字尾為css的檔案 use: ['style-loader', 'css-loader'] // 一組loader的執行順序預設是從右向左 } ] }
接著,我們再重新執行 npm run dev命令,頁面如圖所示:
說明我們css檔案有效果了,再來看下網頁元素
效果如圖,可以看到是以內聯樣式插入到html
外掛(plugins)入門
外掛目的在於解決 loader 無法實現的其他事。
html-webpack-plugin安裝
這個外掛用來簡化建立服務於 webpack bundle 的 HTML 檔案,由於通常在打包中包含一些含有hash值的名字,而這些名字在每次編譯的時候都發生變化的時候對我們開發人員很麻煩,利用這個外掛,我們可以利用這個外掛捆綁式這些檔案方便我們的開發。
執行安裝命令
npm i -D html-webpack-plugin
使用html-webpack-plugin
在webpack.config.js 配置如下:
// 基於node,遵循common.js規範 const path = require('path') // 引入node.js Path 模組 const HtmlWebpackPlugin = require('html-webpack-plugin')// 引入HtmlWebpackPlugin module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development',// 模式 devServer: { contentBase: './build' }, module: { rules: [ { test: /\.css$/,// 利用正則表示式匹配檔名字尾為css的檔案 use: ['style-loader', 'css-loader'] // 一組loader的執行順序預設是從右向左 } ] }, plugins: [ new HtmlWebpackPlugin() ] }
在這裡,我們這個外掛做了兩步工作:
const HtmlWebpackPlugin = require('html-webpack-plugin') plugins: [ new HtmlWebpackPlugin() ]
接下來,我們需要在src目錄下新建模板檔案,名為 template.html ,我們打包後的檔案都已這個html檔案為模板
在模板html寫入如下內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板檔案</title> </head> <body> 使用模板檔案 </body> </html>
這裡我們只是簡單的使用兩個引數
選項 | 描述 | 注意 |
---|---|---|
filename | 就是html檔案的檔名,預設是index.html | |
template | 生成的檔案所依賴檔案模板的路徑 |
plugins的配置如下
plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: './src/template.html', }) ]
好的,現在所有都配置好了,我們來測試一下
執行命令 npm run dev
可以發現,執行專案時使用的是模板檔案
現在,再來測試一下打包檔案
我們把原來的build檔案刪除(當然可以不刪,因為會覆蓋)
執行命令 npm run abc
此時,我們可以發現 build 目錄下 index.html是這個樣子的
直接就幫我們用script標籤插入了bundle.js
總結:入門不易,掌握更難,紙上得來終覺淺,絕知此事要躬行!