前言:本文描述一個小白學習webpack4從零開始的完整過程全紀錄,能夠說徹底以一個初學者的口吻來寫這篇文章的,與此同時這篇文章還會長期更新,不足之處還望大佬雅正!javascript
對於小白來講,看到一些專業的術語就腦袋疼
什麼是webpack?
簡單來說,就是把咱們寫好的代碼打包。
怎麼個打包法,壓縮代碼,相同資源抽取,處理一下瀏覽器不識別的代碼(如ES6+、TS、SASS等)。
一句話,用不到就扔掉,能壓縮就壓縮,能兼容就兼容css
npm是世界上最大的軟件註冊表,使用npm咱們能夠快速安裝各類大小型軟件和庫
下載:在node.js中都自帶了npm,因此咱們下載node.js便可
node.js官網: https://nodejs.org/en/
下載完後,咱們能夠在dos命令行下能夠看到node.js的版本和npm的版本 node -v npm -v
html
①、新建練習文件目錄 ex1
①、在ex1目錄下新建源文件目錄 src
②、在src目錄下新建入口文件 index.js
造成的目錄結構以下:
java
package.json文件定義了這個項目所須要的各類模塊,以及項目的配置信息(好比名稱、版本、許可證等元數據)。
在ex1目錄下使用命令:node
npm init -y
init指令會詢問一系列的問題,並將你的配置寫成一個package.json文件。
若是使用了-f|--force|-y|--yes這些參數,那麼會生成一個默認的package.json文件。
這個init過程很快,能夠看到在ex1目錄下多了個package.json文件
webpack
提示:webpack4.0以上版本的webpack的腳手架webpack-cli已經被分離出來,須要另外安裝。
安裝webpack分爲全局安裝和本地安裝(局部安裝)web
全局安裝(不推薦) npm install webpack webpack-cli -g
(-g就是全局安裝)
本地安裝 npm install webpack webpack-cli -D
(-D 就是安裝到開發環境)
安裝成功後如圖所示:
正則表達式
再來看下咱們的文件目錄發生了什麼變化:
node_modules文件夾主要是用於放用包管理工具下載安裝了的包,這個文件的內容有不少
package-lock.json鎖定了包的版本,確保可以避免包版本不一樣產生的問題。chrome
npx 會幫你執行依賴包裏的二進制文件。
npx會自動找到node_modules/bin 的webpack.cmd去執行,免去了script的配置shell
在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 仍是 生產模式production
那咱們就能夠在命令後面加上 --mode development
看,是否是沒有了黃色警告提示。
npx的缺點:雖然使用npx能夠快速的幫咱們打包,可是不夠靈活,好比打包後文件夾名字都是固定 dist,所以咱們須要定義webpack打包的配置文件,這樣才能夠爲所欲爲的打包
咱們如今ex1的目錄下新建一個名爲 webpack.config.js 文件
因爲webpack是基於node,因此要遵循common.js規範
入口起點(entry point)指示 webpack 應該使用哪一個模塊,來做爲構建其內部依賴圖的開始。進入入口起點後,webpack 會找出有哪些模塊和庫是入口起點(直接和間接)依賴的。
entry 屬性的單個入口語法
module.exports = { entry: './src/index.js' };
output 屬性告訴 webpack 在哪裏輸出它所建立的 bundles,以及如何命名這些文件。
默認值爲 ./dist。
在 webpack 中配置 output 屬性的最低要求是,將它的值設置爲一個對象,包括如下兩點:
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文件
那麼說明了咱們的配置是成功的!
能夠參考阮一峯老師的博客:http://www.ruanyifeng.com/blo...
npm 容許在package.json文件裏面,使用scripts字段定義腳本命令。
npm 腳本。它的優勢不少
在咱們原有的package.json中,咱們能夠發現有一個這樣"scripts"字段
"scripts": { "test": "echo \"Error: no test specified\" && exit 1" }
所以咱們能夠嘗試使用 npm test 命令看下會有什麼結果
結果執行了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' // 模式 }
此時,咱們再打包試一下,結果如圖:
咱們可清楚地看到黃色警告已經去掉了
在咱們的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
②、npm install m –save:
②、npm install m –save-dev:
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字段了
因爲使用webpack打包後,原來的代碼通過壓縮,去空格,bable的編譯以後,已經變成咱們不認識的代碼了,爲了方便咱們調試調式代碼,定位bug,source map就出現了
在webpack.config.js中,devtool選項用於控制是否生成,以及如何生成 source map。
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 的方式:
咱們選擇在webpack.config.js中配置loader
基本寫法以下:
module: { rules: [ { test: /\.css$/, // 利用正則表達式匹配文件名後綴爲css的文件 use: ['style-loader', 'css-loader'] // 一組loader的執行順序默認是從右向左 } ] }
接着,咱們再從新執行 npm run dev命令,頁面如圖所示:
說明咱們css文件有效果了,再來看下網頁元素
效果如圖,能夠看到是之內聯樣式插入到html
插件目的在於解決 loader 沒法實現的其餘事。
這個插件用來簡化建立服務於 webpack bundle 的 HTML 文件,因爲一般在打包中包含一些含有hash值的名字,而這些名字在每次編譯的時候都發生變化的時候對咱們開發人員很麻煩,利用這個插件,咱們能夠利用這個插件捆綁式這些文件方便咱們的開發。
執行安裝命令
npm i -D 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
總結:入門不易,掌握更難,紙上得來終覺淺,絕知此事要躬行!