什么是 Webpack
?為什么要用 Webpack
睁壁?估計(jì)很多小伙伴都知道潘明,但是說(shuō)不出來(lái)~~~記得以前看過(guò)一篇文章 愿未來(lái)沒(méi)有 Webpack钉疫,里面有一段話:我明明只是想打印一個(gè) Hello World
巢价,卻需要安裝 1300
個(gè)不同的依賴包......當(dāng)然壤躲,這是極端抬杠并齐。不可否認(rèn)测垛,webpack
確實(shí)增加了不少學(xué)習(xí)成本链快,但是日常開(kāi)發(fā)中炉峰,它也確實(shí)帶給了我們很多便利婆廊。對(duì)于咱們苦逼的搬磚黨來(lái)說(shuō),大家都在用它帆离,并且它確實(shí)好用猜扮,也只能默默留著兩行淚去學(xué)習(xí)~~~
本文綜合整理來(lái)源:webpack 中文網(wǎng) 和 從基礎(chǔ)到實(shí)戰(zhàn) 手把手帶你掌握新版Webpack4.0
在了解 webpack
的用途之前源譬,我們先來(lái)看一段非常簡(jiǎn)單的代碼
<div id="root"></div>
<script src="lesson/index.js"></script>
// lesson => index.js
const dom = document.getElementById('root')
// header 部分
const header = document.createElement('div')
header.innerText = "header"
dom.append(header)
// sidebar 部分
const sidebar = document.createElement('div')
sidebar.innerText = "sidebar"
dom.append(sidebar)
// content 部分
const content = document.createElement('div')
content.innerText = "content"
dom.append(content)
很簡(jiǎn)單的一段代碼泛烙,就不解讀了。這種面向過(guò)程的編寫方式會(huì)導(dǎo)致所有代碼都堆在一個(gè)文件中润脸,過(guò)于冗余且不利于維護(hù)行施。這個(gè)時(shí)候我們就引入了面向?qū)ο缶幊痰母拍睿俏覀兙椭貥?gòu)一下上面的代碼鲜结。
<body>
<div id="root"></div>
</body>
<script src="lesson/header.js"></script>
<script src="lesson/sidebar.js"></script>
<script src="lesson/content.js"></script>
<script src="lesson/index.js"></script>
// header.js
function Header() {
const header = document.createElement('div')
header.innerText = "header"
dom.append(header)
}
// sidebar.js
function Sidebar() {
const sidebar = document.createElement('div')
sidebar.innerText = "sidebar"
dom.append(sidebar)
}
// content.js
function Content() {
const content = document.createElement('div')
content.innerText = "content"
dom.append(content)
}
// index.js
const dom = document.getElementById('root')
new Header()
new Sidebar()
new Content()
我們將各個(gè)模塊所負(fù)責(zé)的功能都單獨(dú)放在對(duì)應(yīng)的 js
文件里面拗胜,這樣便于后期維護(hù)怒允,但是這又延伸出了一些問(wèn)題纫事?
加載多個(gè)
js
文件丽惶,頁(yè)面加載速度變慢從代碼中看不出文件的相互關(guān)系钾唬,例如:如果打開(kāi)
index.js
可能會(huì)一頭霧水,又要去看html
中的引入文件才行html
中文件的引入順序不能出錯(cuò)壤圃,否則報(bào)錯(cuò)之后很難進(jìn)行排錯(cuò)處理
開(kāi)發(fā)中所有問(wèn)題的曝光都是為了更完美的解決伍绳,寫過(guò) Vue
或者 React
的小伙伴估計(jì)都清楚項(xiàng)目開(kāi)發(fā)中我們引入文件的方式一般為 import xxx from './xxx'
冲杀,這樣不僅解決了加載多個(gè) js
運(yùn)行變慢的問(wèn)題睹酌,并且讓文件之間的依賴關(guān)系更強(qiáng)憋沿,同時(shí)引入文件的順序也不會(huì)影響代碼的正確執(zhí)行辐啄。我們通過(guò)這種方式繼續(xù)改造一下代碼:
<div id="root"></div>
<script src="lesson/index.js"></script>
import Header from './header'
import Sidebar from './sidebar'
import Content from './content'
const dom = document.getElementById('root')
new Header()
new Sidebar()
new Content()
相信大家都知道這么寫肯定會(huì)報(bào)錯(cuò)壶辜,首先我們并沒(méi)有導(dǎo)出就直接引入了,而且瀏覽器不認(rèn)識(shí) import
語(yǔ)法抵怎。所以這個(gè)時(shí)候我們就要借助 webpack
來(lái)讓瀏覽器識(shí)別 import
這種語(yǔ)法結(jié)構(gòu)反惕。
- 首先我們?cè)?
lesson
文件夾中使用npm init -y
快速初始化項(xiàng)目承璃。
// lesson
npm init -y
- 初始化
webpack
和webpck-cli
盔粹,這里限定了版本號(hào)~~~因?yàn)?webpack
版本更新太快了舷嗡,這里就先用這個(gè)版本,實(shí)際項(xiàng)目開(kāi)發(fā)中會(huì)專門在webpack.config.js
進(jìn)行配置捻脖。
npm install webpack@4.25.1 webpack-cli@3.1.2 -D
- 然后運(yùn)行
npx webpack index.js
進(jìn)行編譯
npx webpack index.js
就這樣可婶,項(xiàng)目就被我們用 webpack
完成了打包和編譯矛渴,給我們重新生成了一個(gè) dist
目錄具温,里面有一個(gè) main.js
的文件就是打包所有代碼之后生成的對(duì)應(yīng)文件筐赔,默認(rèn)會(huì)幫我們進(jìn)行代碼壓縮茴丰。然后修改 index.html
中 script
的引入指向较沪,綜合匯總代碼:
<body>
<div id="root"></div>
</body>
<script src="./lesson/dist/main.js"></script>
// index.js // 使用 npx webpack index.js 進(jìn)行打包
import Header from './header'
import Sidebar from './sidebar'
import Content from './content'
new Header()
new Sidebar()
new Content()
// Header
function Header() {
const dom = document.getElementById('root')
const header = document.createElement('div')
header.innerText = "header"
dom.append(header)
}
// 請(qǐng)導(dǎo)出
export default Header
// Sidebar
function Sidebar() {
const dom = document.getElementById('root')
const sidebar = document.createElement('div')
sidebar.innerText = "sidebar"
dom.append(sidebar)
}
export default Sidebar
// Content
function Content() {
const dom = document.getElementById('root')
const content = document.createElement('div')
content.innerText = "content"
dom.append(content)
}
export default Content
一個(gè)小小的栗子下來(lái),是不是對(duì) webpack
能做什么有了一定的了解控轿。有沒(méi)有認(rèn)為webpack
是 js
的一個(gè)翻譯器,幫我們把 js
的高級(jí)語(yǔ)法轉(zhuǎn)換為瀏覽器可以理解的語(yǔ)法~~~其實(shí) webpack
遠(yuǎn)遠(yuǎn)沒(méi)有我們想象的那么強(qiáng)大(當(dāng)然還是很強(qiáng)大的)鹦蠕,它只認(rèn)識(shí) import
這種語(yǔ)法钟病,像 ES6
的一些新 API
其實(shí) webpack
并不能認(rèn)識(shí)肠阱,需要借助 bable
幫我們處理(這是后話~~)屹徘。webpack
的核心定義是:模塊打包工具噪伊。
我們?nèi)粘i_(kāi)發(fā)中通過(guò) import
其實(shí)引入的就是我們自己寫入的模塊氮唯,而 webpack
做的事情就是把這些模塊進(jìn)行整合打包處理惩琉。當(dāng)然模塊的引入方式不僅僅只有 import
琳水,像我們?cè)?node
中使用的 require
也可以通過(guò) webpack
進(jìn)行打包在孝。其實(shí) webpack
剛開(kāi)始的時(shí)候只支持 js
模塊打包私沮,但是隨著技術(shù)的迭代更新和發(fā)展,現(xiàn)在 webpack
同時(shí)支持 img
仔燕、css
晰搀、字體
等不同種類的模塊打包外恕。
此處延伸擴(kuò)展學(xué)習(xí)文檔:webpack 模塊、模塊方法蠕蚜、模塊變量
搭建 Webpack 環(huán)境
Webpack
是基于 node.js
開(kāi)發(fā)的模塊打包工具靶累,它本質(zhì)上是由 node
實(shí)現(xiàn)的挣柬。所以搭建 Webpack
環(huán)境首先要安裝 node
的環(huán)境争舞,這里就不累贅介紹 node
的安裝了~~~首先我們創(chuàng)建了一個(gè) webpack-demo
的文件夾,然后命令行進(jìn)入到這個(gè)文件夾竞川,老規(guī)矩先來(lái)個(gè) npm init -y
店溢,它的含義是可以快速幫我們以 node
規(guī)范的形式創(chuàng)建一個(gè)項(xiàng)目或者創(chuàng)建一個(gè) node
的包文件。此時(shí)即幫我們生成了一個(gè) packge.json
的文件委乌,接下來(lái)就是安裝 webpack
床牧。
- 全局安裝
Webpack
(不推薦)
npm install webpack webpack-cli -g
如果全局安裝成功,此時(shí)運(yùn)行 webpack-v
就可以打印出對(duì)應(yīng)的版本號(hào)遭贸。當(dāng)然這種全局安裝的方式非常不推薦戈咳,因?yàn)?webpack
現(xiàn)在的版本更新太快了,很多以前老版本的配置在新版本中可能就被移除了~~~舉個(gè)栗子:如果我們兩個(gè)項(xiàng)目都用 webpack
進(jìn)行打包著蛙,一個(gè)項(xiàng)目當(dāng)初是通過(guò) webpack 3.0
進(jìn)行配置的,而另一個(gè)項(xiàng)目是通過(guò) webpack 4.0
進(jìn)行配置的耳贬,此時(shí)用我們?nèi)职惭b的 webpack
進(jìn)行打包踏堡,就會(huì)因?yàn)榘姹静煌霈F(xiàn)問(wèn)題。所以就引入了另一種安裝 webpack
的方法咒劲,當(dāng)然在這之前我們要卸掉剛剛?cè)职惭b的 webpack
顷蟆。
npm uninstall webpack webpack-cli -g
- 在項(xiàng)目?jī)?nèi)安裝
webpack
(推薦)
進(jìn)入我們的 webpack-demo
文件夾,在項(xiàng)目?jī)?nèi)進(jìn)行安裝:
npm install webpack webpack-cli --save -dev
// --save -dev === -D 所以也可以寫成下面這樣:
// npm install webpack webpack-cli -D
安裝完成之后腐魂,文件夾中就會(huì)多出一個(gè) node_modules
的文件夾帐偎,當(dāng)然此時(shí)如果我們輸入 webpack -v
是無(wú)法查看對(duì)應(yīng)版本信息的,因?yàn)?node
在全局中無(wú)法找到 webpack
指令蛔屹,所以此時(shí)可以借助 npx webpack -v
來(lái)查看我們項(xiàng)目中 webpack
的版本削樊,因?yàn)?npx
會(huì)幫助我們?cè)陧?xiàng)目的 node_modules
文件夾中去找 webpack
。當(dāng)然日常開(kāi)發(fā)中我們一般會(huì)鎖定一個(gè) webpack
的穩(wěn)定版本判导,所以此時(shí)我們?cè)诎惭b的時(shí)候可以指定對(duì)應(yīng)的版本號(hào):
npm install webpack@4.25.1 webpack-cli@3.1.2 -D
如果我們不知道 webpack
有哪些版本嫉父,可以直接通過(guò)如下命令查看它的所有版本信息:
npm info webpack
- 對(duì)
webpack.config.js
進(jìn)行基礎(chǔ)配置
前面打包都是通過(guò) npx webpack index.js
來(lái)進(jìn)行的沛硅,這是因?yàn)槲覀冎付舜虬奈募?index.js
眼刃。日常開(kāi)發(fā)中绕辖,我們會(huì)對(duì) webpack
進(jìn)行相關(guān)配置,里面可以指定打包的入口文件擂红,打包輸出的地址等等......此時(shí)就我們可以新建一個(gè)配置文件 webpack.config.js
:
// webpack.config.js
const path = require('path')
module.exports = {
entry: './index.js', // 項(xiàng)目打包的入口文件
output: { // 打包的最終文件放在哪里
filename: 'bundle.js', // 打包生成的文件名
path: path.resolve(__dirname, 'dist') // 打包生成文件的文件夾名稱
}
}
上述代碼就是 webpack
最基礎(chǔ)的配置文件仪际,它規(guī)定了打包的入口文件為 index.js
,打包完成后生成的文件名為 bundle.js
昵骤,同時(shí) bundle.js
會(huì)放置在你規(guī)定的 dist
文件夾下树碱。此時(shí)我們運(yùn)行 npx webpack
即可按照我們制定的規(guī)則進(jìn)行打包。
同 vue.config.js
的設(shè)置規(guī)則一樣变秦,webpack.config.js
的名稱也是官方規(guī)定好的成榜,不能隨意更改這個(gè)名字。如果此時(shí)我們將 webpack.config.js
改為 webpackconfig.js
蹦玫,那我們要怎么樣才能正常運(yùn)行代碼呢赎婚?此時(shí)需要手動(dòng)指定 webpackconfig.js
作為我們的配置文件,可以使用如下方法:
npx webpack --config webpackconfig.js
- 結(jié)構(gòu)優(yōu)化
了解了所有的基礎(chǔ)打包步驟之后樱溉,我們可以對(duì)代碼整體的結(jié)構(gòu)進(jìn)行優(yōu)化挣输。新建一個(gè) src
目錄用于放置我們代碼中的源代碼部分(index.js、header.js福贞、sidebar.js撩嚼、content.js
),然后將 index.html
移入到 dist
目錄下挖帘,記得修改 index.html
引入打包后的腳本文件的地址完丽,因?yàn)槲覀兏膭?dòng)了打包的入口文件 index.js
的地址,所以 webpack.config.js
中也要進(jìn)行修改:
const path = require('path')
module.exports = {
entry: './src/index.js', // 項(xiàng)目打包的入口文件
output: { // 打包的最終文件放在哪里
filename: 'bundle.js', // 打包生成的文件名
path: path.resolve(__dirname, 'dist') // 打包目錄
}
}
我們知道拇舀,在 vue
項(xiàng)目的構(gòu)建中逻族,我們通常的打包命令為 npm run build
,雖然我們這個(gè)項(xiàng)目只是一個(gè)入門基礎(chǔ)學(xué)習(xí)項(xiàng)目你稚,但是我們也想用 vue
的項(xiàng)目解構(gòu)和打包指令進(jìn)行打包瓷耙,此時(shí)就可以配置 npm scripts
,即修改 package.json
文件中的 scripts
:
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"private": true,
"keywords": [],
"scripts": {
"build": "webpack" // 使用 bulid 映射 webpack 指令
},
"author": "Chen",
"license": "ISC",
"devDependencies": {
"webpack": "^4.25.0",
"webpack-cli": "^4.1.0"
},
"dependencies": {
"file-loader": "^6.1.1"
}
此時(shí)我們就可以通過(guò) npm run build
對(duì)我們的項(xiàng)目進(jìn)行整體打包了刁赖,最終我們得到一個(gè)類似 vue
項(xiàng)目的結(jié)構(gòu)搁痛,具體結(jié)構(gòu)圖如下:
- 綜合小結(jié)
經(jīng)過(guò)上述一系列操作,我們也算是完成了一個(gè)初步的打包 demo
宇弛,同時(shí)我們也總結(jié)一下 webpack
的三種打包方式:
global
即全局安裝webpack
webpack index.js
local
項(xiàng)目中局部安裝webpack
npx webpack index.js
npm scripts
修改scripts
配置
npm run build => webpack
最終我們也算是得到了一個(gè)類似 vue-cli
腳手架幫我們搭建的項(xiàng)目結(jié)構(gòu)鸡典,那么回過(guò)頭來(lái),我們?cè)诎惭b webpack
的時(shí)候同時(shí)安裝了 webpack-cli
這個(gè)東西枪芒,那么 webpack-cli
有什么用呢彻况?
webpack-cli
的作用就是可以使我們?cè)诿钚欣镎_運(yùn)行webpack
這個(gè)命令谁尸,如果我們不安裝這個(gè)包,那么就無(wú)法在命令行里運(yùn)行webpack
或者npx webpack
這樣的命令纽甘。
此處可以延伸擴(kuò)展學(xué)習(xí):webpack 起步
- 查漏補(bǔ)缺
我們通過(guò) npm run build
打包之后良蛮,命令行也給我們輸出了如下信息:
這些信息都是什么意識(shí)呢?我們一個(gè)一個(gè)來(lái)瞅一瞅:
Hash
:本次打包對(duì)應(yīng)的唯一哈希值Version
:打包使用的webpack
版本Time
:當(dāng)前打包的整體耗時(shí)是411ms
Asset
:打包出了一個(gè)bundle.js
文件Size
:bundle.js
的文件大小Chunks
:每一個(gè)js
文件對(duì)應(yīng)的ID
Chunk Name
:每一個(gè)js
文件對(duì)應(yīng)的名字
那么問(wèn)題來(lái)了悍赢,這里為什么是 main
呢决瞳,我們好像全程都沒(méi)有用到過(guò) main
這個(gè)詞,其實(shí)這個(gè) main
來(lái)源于 webpack.config.js
左权,如下栗子:
// webpack.config.js
const path = require('path')
module.exports = {
mode: 'production',
entry: {
main: './src/index.js'
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
我們前面對(duì) entry
的配置其實(shí)是一種簡(jiǎn)寫模式皮胡,其實(shí)真正在打包過(guò)程中 entry
的配置應(yīng)該如上代碼,main
指向的就是打包的入口文件赏迟。上述代碼中我們還設(shè)置了一個(gè) mode
屡贺,webpack
打包時(shí)如果我們沒(méi)有填寫該項(xiàng),即會(huì)默認(rèn)使用 production
模式锌杀,即打包出來(lái)的 bundle.js
文件會(huì)被壓縮甩栈。mode
還可選值為 development
,此時(shí)打包生成的 bundle.js
文件就不會(huì)被壓縮抛丽。
webpack
入門基礎(chǔ)配置基本就是以上這些內(nèi)容谤职,什么是 loader
?什么是 plugins
? 什么是 babel
亿鲜?就讓我們一點(diǎn)一滴在后續(xù)剝開(kāi)它們神秘的面紗允蜈。再次強(qiáng)烈推薦大家學(xué)習(xí)慕課網(wǎng) Dell Lin
老師的 從基礎(chǔ)到實(shí)戰(zhàn) 手把手帶你掌握新版Webpack4.0 課程,老師所有的課程說(shuō)實(shí)話都非常棒蒿柳,大家該剁手時(shí)一定要毫不留情叭奶住!@萏健妓蛮!
此整理僅供記錄學(xué)習(xí),如果文中有不對(duì)的地方或者理解有誤的地方歡迎大家提出并指正圾叼。每一天都要相對(duì)前一天進(jìn)步一點(diǎn)蛤克,加油!R奈谩构挤!