從0-1搭建webpack的前端工程化項(xiàng)目教程
1.1 前端工程化的相關(guān)概念
1 小白眼中的前端開發(fā) vs 實(shí)際的前端開發(fā)
小白眼中的前端開發(fā):
- 會(huì)寫HTML+CSS +javascript
- 美化頁面就拽一個(gè)bootstrap過來
- 需要操作DOM或發(fā)起Ajax請求就拽一個(gè)jQuery過來
- 需要快速實(shí)現(xiàn)一個(gè)頁面布局效果就拽一個(gè)Layui過來
實(shí)際的前端開發(fā):
- 模塊化 (js的模塊化,css的模塊化,資源的模塊化)
- 組件化 (復(fù)用現(xiàn)有的UI結(jié)構(gòu),樣式,行為)
- 規(guī)范化 (目錄結(jié)構(gòu)的劃分,編程規(guī)范化,接口規(guī)范化,文檔規(guī)范化,Git分支管理)
- 自動(dòng)化 (自動(dòng)化構(gòu)建,自動(dòng)部署,自動(dòng)化測試)
2 什么是前端工程化
前端工程化指的是:在企業(yè)級的前端項(xiàng)目開發(fā)中 把前端開發(fā)所需的工具,技術(shù),流程,經(jīng)驗(yàn)等進(jìn)行規(guī)范化,標(biāo)準(zhǔn)化。
企業(yè)中的Vue項(xiàng)目和React項(xiàng)目,都是基于工程化的方式進(jìn)行開發(fā)的
好處:前端開發(fā)自成體系,有一套標(biāo)準(zhǔn)的開發(fā)方案和流程
3 前端工程化的解決方案
早期的前端工程化解決方案:
- grunt( https://www.gruntjs.net/ )
- gulp( https://www.gulpjs.com.cn/ )
目前主流的前端工程化解決方案:
- webpack( https://www.webpackjs.com/ )主要用于做項(xiàng)目
- parcel( https://zh.parceljs.org/ )更多是開發(fā)第三方包的時(shí)候會(huì)用
1.2 webpack 的基本使用
1.2.1 什么是 webpack
- 概念:webpack 是前端項(xiàng)目工程化的具體解決方案。
- 主要功能:它提供了友好的前端模塊化開發(fā)支持,以及代碼壓縮混淆、處理瀏覽器端 JavaScript 的兼容性,性能優(yōu)化等強(qiáng)大的功能。
- 好處:讓程序員把工作的重心放到具體功能的實(shí)現(xiàn)上,提高了前端開發(fā)效率和項(xiàng)目的可維護(hù)性。
- 注意:目前 Vue,React 等前端項(xiàng)目,基本上都是基于 webpack 進(jìn)行工程化開發(fā)的。
1.2.創(chuàng)建列表隔行變色項(xiàng)目
① 新建項(xiàng)目空白目錄,并運(yùn)行 npm init –y 命令,初始化包管理配置文件 package.json。(文件夾必須是英文的)
- package.json
...
② 新建 src 源代碼目錄。 (放程序員寫的代碼)
③ 新建 src -> index.html 首頁和 src -> index.js 腳本文件
④ 初始化首頁基本的結(jié)構(gòu)
ul>li{這是第$個(gè)li}*9 //快速生成1-9個(gè)li
- src -> index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./index.js"></script>
</head>
<body>
<ul>
<li>這是第 1 個(gè) li</li>
<li>這是第 2 個(gè) li</li>
<li>這是第 3 個(gè) li</li>
<li>這是第 4 個(gè) li</li>
<li>這是第 5 個(gè) li</li>
<li>這是第 6 個(gè) li</li>
<li>這是第 7 個(gè) li</li>
<li>這是第 8 個(gè) li</li>
<li>這是第 9 個(gè) li</li>
</ul>
</body>
</html>
⑤ 運(yùn)行 npm install jquery –s 命令,安裝 jQuery (不用搜索下載了,–s是加到dependencies()) -s是–save的縮寫
- package-lock.json(增加)
.....
- node_modules(增加文件夾)
⑥ 通過 ES6 模塊化的方式導(dǎo)入 jQuery,實(shí)現(xiàn)列表隔行變色效果
- src -> index.js
// 1. 使用 ES6 導(dǎo)入語法,導(dǎo)入 jQuery
import $ from 'jquery'
// 2. 定義 jQuery 的入口函數(shù)
$(function () {
// 3. 實(shí)現(xiàn)奇偶行變色
// 奇數(shù)行為紅色
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'pink')
// 0 是偶數(shù)
// 1 是奇數(shù)
})
結(jié)果你會(huì)發(fā)現(xiàn)報(bào)錯(cuò)因?yàn)檎Z法高級無法識別接下來就需要用webpack
1.2.3. 在項(xiàng)目中安裝 webpack
在終端運(yùn)行如下的命令,安裝 webpack 相關(guān)的兩個(gè)包:
- npm install webpack@5.42.1 webpack-cli@4.7.2 -D (–S是加到devDependencies(只在開發(fā)階段用)這個(gè)節(jié)點(diǎn)中)
- -D是–save-dev的縮寫 在npmjs.com 官方文檔中可以查看放在那里
注意:安裝完webpack在node_modules文件夾會(huì)多很多文件夾
1.2.4 在項(xiàng)目中配置 webpack
① 在項(xiàng)目根目錄中,創(chuàng)建名為 webpack.config.js 的 webpack 配置文件,并初始化如下的基本配置:
- webpack.config.js
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣?,而不是體積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development'
}
② 在 package.json 的 scripts 節(jié)點(diǎn)下,新增 dev 腳本如下:
- 注意package.json中原先就有
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}//把"test": "echo \"Error: no test specified\" && exit 1"刪掉換成下面的
//"test": "echo \"Error: no test specified\" && exit 1"是沒用的代碼
- package.json
"scripts": {
"dev": "webpack"
},
③ 在終端中運(yùn)行 npm run dev 命令,啟動(dòng) webpack 進(jìn)行項(xiàng)目的打包構(gòu)建(一會(huì)介紹打包介紹)
終端(又又又報(bào)錯(cuò)了):
PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm run dev
> change-rows-color@1.0.0 dev
> webpack
node:internal/crypto/hash:71
this[kHandle] = new _Hash(algorithm, xofLen);
^
Error: error:0308010C:digital envelope routines::unsupported
at new Hash (node:internal/crypto/hash:71:19)
at Object.createHash (node:crypto:133:10)
at BulkUpdateDecorator.hashFactory (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack\lib\util\createHash.js:145:18)
at BulkUpdateDecorator.update (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack\lib\util\createHash.js:46:50)
at RawSource.updateHash (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack-sources\lib\RawSource.js:64:8)
at NormalModule._initBuildHash (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack\lib\NormalModule.js:868:17)
at handleParseResult (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack\lib\NormalModule.js:934:10)
at D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack\lib\NormalModule.js:1026:4
at processResult (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack\lib\NormalModule.js:743:11)
at D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack\lib\NormalModule.js:807:5 {
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'
}
Node.js v18.15.0
這個(gè)錯(cuò)誤是node版本太高
我的建議是安裝nvm可以隨意切換node的版本
安裝方法自己查
如下:
PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm run dev > change-rows-color@1.0.0 dev D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color > webpack asset main.js 319 KiB [emitted] (name: main) runtime modules 937 bytes 4 modules cacheable modules 279 KiB ./src/index.js 315 bytes [built] [code generated] ./node_modules/jquery/dist/jquery.js 278 KiB [built] [code generated] //將上面的兩個(gè)index.jsjquery.js合并在了main.js webpack 5.42.1 compiled successfully in 253 ms
運(yùn)行完之后在文件中多了 dist文件夾 并且在dist文件夾下有main.js
main.js是webpage根據(jù)我們index.js生成的
也就是說index.js可以用main.js替換,因?yàn)閙ain.js解決了兼容性問題
- 第四步 修改 src -> index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="./index.js"></script> -->
<script src="../dist/main.js"></script>
</head>
<body>
<ul>
<li>這是第1個(gè)li</li>
<li>這是第2個(gè)li</li>
<li>這是第3個(gè)li</li>
<li>這是第4個(gè)li</li>
<li>這是第5個(gè)li</li>
<li>這是第6個(gè)li</li>
<li>這是第7個(gè)li</li>
<li>這是第8個(gè)li</li>
<li>這是第9個(gè)li</li>
</ul>
</body>
</html>
1 mode 的可選值
mode 節(jié)點(diǎn)的可選值有兩個(gè),分別是:
① development
- 開發(fā)環(huán)境
- 不會(huì)對打包生成的文件進(jìn)行代碼壓縮和性能優(yōu)化
- 打包速度快,適合在開發(fā)階段使用
② production
- 生產(chǎn)環(huán)境
- 會(huì)對打包生成的文件進(jìn)行代碼壓縮和性能優(yōu)化
- 打包速度很慢,僅適合在項(xiàng)目發(fā)布階段使用
production的使用
- webpack.config.js 修改
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣?,而不是體積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'production'
}
PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm run dev > change-rows-color@1.0.0 dev D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color > webpack //注意這里的體積變?yōu)?5.5 KiB asset main.js 85.5 KiB [emitted] [minimized] (name: main) 1 related asset runtime modules 663 bytes 3 modules cacheable modules 279 KiB ./src/index.js 315 bytes [built] [code generated] ./node_modules/jquery/dist/jquery.js 278 KiB [built] [code generated] webpack 5.42.1 compiled successfully in 1778 ms
2 webpack.config.js 文件的作用
webpack.config.js 是 webpack 的配置文件。webpack 在真正開始打包構(gòu)建之前,會(huì)先讀取這個(gè)webpack.config.js 配置文件,
從而基于給定的配置,對項(xiàng)目進(jìn)行打包。
注意:由于 webpack 是基于 node.js 開發(fā)出來的打包工具,因此在它的配置文件中,支持使用 node.js 相關(guān)的語法和模塊進(jìn)行 webpack 的個(gè)性化配置。
3 webpack 中的默認(rèn)約定
在 webpack 4.x 和 5.x 的版本中,有如下的默認(rèn)約定:
① 默認(rèn)的打包入口文件為 src -> index.js ,如果改變src文件夾的名字和index.js的名字,然后使用npm run dev 命令會(huì)報(bào)錯(cuò)
② 默認(rèn)的輸出文件路徑為 dist -> main.js
注意:可以在 webpack.config.js 中修改打包的默認(rèn)約定
4 自定義打包的入口與出口
在 webpack.config.js 配置文件中,通過 entry 節(jié)點(diǎn)指定打包的入口。通過 output 節(jié)點(diǎn)指定打包的出口。
先將index.js改為index1.js
示例代碼如下:
- webpack.config.js
//導(dǎo)入path模塊
const path = require('path');
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣龋皇求w積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個(gè)文件'
//__dirname 相當(dāng)于當(dāng)前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
}
}
將dist文件夾刪除
- 終端運(yùn)行 npm run dev
PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm run dev > change-rows-color@1.0.0 dev D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color > webpack asset bundle.js 319 KiB [emitted] (name: main) runtime modules 937 bytes 4 modules cacheable modules 279 KiB ./src/index1.js 315 bytes [built] [code generated] ./node_modules/jquery/dist/jquery.js 278 KiB [built] [code generated] webpack 5.42.1 compiled successfully in 279 ms PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color>
- 并改變index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="./index.js"></script> -->
<!-- <script src="../dist/main.js"></script> -->
<script src="../dist/bundle.js"></script>
</head>
<body>
<ul>
<li>這是第1個(gè)li</li>
<li>這是第2個(gè)li</li>
<li>這是第3個(gè)li</li>
<li>這是第4個(gè)li</li>
<li>這是第5個(gè)li</li>
<li>這是第6個(gè)li</li>
<li>這是第7個(gè)li</li>
<li>這是第8個(gè)li</li>
<li>這是第9個(gè)li</li>
</ul>
</body>
</html>
思考一個(gè)問題,此時(shí)當(dāng)我們改變index1.js中的代碼,使奇數(shù)行變成金色 ,會(huì)不會(huì)影響頁面中的顏色
答案:不會(huì),因?yàn)槲覀冊趇ndex.js中導(dǎo)入的是webpage工程化之后的代碼;
想要看到奇數(shù)行變成金色 ,必須重新運(yùn)行npm run dev
但是每次運(yùn)行npm run dev 太麻煩了 下面來解決這個(gè)問題
1.3 webpack 中的插件
1.3.1 webpack 插件的作用
通過安裝和配置第三方的插件,可以拓展 webpack 的能力,從而讓 webpack 用起來更方便。最常用的
webpack 插件有如下兩個(gè):
① webpack-dev-server
- 類似于 node.js 階段用到的 nodemon 工具
- 每當(dāng)修改了源代碼,webpack 會(huì)自動(dòng)進(jìn)行項(xiàng)目的打包和構(gòu)建
② html-webpack-plugin
- webpack 中的 HTML 插件(類似于一個(gè)模板引擎插件)
- 可以通過此插件自定制 index.html 頁面的內(nèi)容
1.3.2 webpack-dev-server
webpack-dev-server 可以讓 webpack 監(jiān)聽項(xiàng)目源代碼的變化,從而進(jìn)行自動(dòng)打包構(gòu)建。
1 安裝 webpack-dev-server
運(yùn)行如下的命令,即可在項(xiàng)目中安裝此插件:
- npm install webpack-dev-server@3.11.2 -D (只在開發(fā)階段用到的工具)
PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm install webpack-dev-server@3.11.2 -D //....一堆警告 只要不報(bào)錯(cuò)就行 + webpack-dev-server@3.11.2 added 374 packages from 227 contributors and updated 125 packages in 17.789s 41 packages are looking for funding run `npm fund` for details
2 配置 webpack-dev-server
① 修改 package.json -> scripts 中的 dev 命令如下:
這個(gè)是用來進(jìn)行實(shí)時(shí)打包的,只要程序員保存代碼就是重新打包項(xiàng)目
- 將package.json下的scripts屬性的dev改成如下
"scripts": {
"dev": "webpack serve",
}
② 再次運(yùn)行 npm run dev 命令,重新進(jìn)行項(xiàng)目的打包 (又又又報(bào)錯(cuò))
PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm run dev
> change-rows-color@1.0.0 dev D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
> webpack serve
[webpack-cli] Unable to load '@webpack-cli/serve' command
[webpack-cli] TypeError: options.forEach is not a function
at WebpackCLI.makeCommand (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\webpack-cli\lib\webpack-cli.js:173:21)
at ServeCommand.apply (D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color\node_modules\@webpack-cli\serve\lib\index.js:41:19)
//...省略
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\86184\AppData\Roaming\npm-cache\_logs\2023-05-25T11_47_09_839Z-debug.log
解決方法沒有安裝 npm i --save-dev webpack-cli
PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm i --save-dev webpack-cli //..... + webpack-cli@4.10.0 removed 9 packages and updated 4 packages in 3.99s 34 packages are looking for funding run `npm fund` for details //查看版是否安裝webpack-cli PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npx webpack --version webpack: 5.42.1 webpack-cli: 4.10.0 webpack-dev-server 3.11.2 //再次執(zhí)行 PS D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color> npm run dev > change-rows-color@1.0.0 dev D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color > webpack serve // 需要訪問http://localhost:8080 地址 i ?wds?: Project is running at http://localhost:8080/ // 我們在webpack.config.js中加入了output屬性 則說明更新的js代碼在http://localhost:8080/bundle.js中 i ?wds?: webpack output is served from / i ?wds?: Content not from webpack is served from D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color //..... webpack 5.42.1 compiled successfully in 447 ms i ?wdm?: Compiled successfully. //當(dāng)看到光標(biāo)在這里一閃一閃的就好了
注意這個(gè)不能用瀏覽器打開了需要訪問http://localhost:8080 地址
注意:我們重新打包的 是放在內(nèi)存中,沒有放到磁盤中 因?yàn)榉磸?fù)讀寫磁盤慢還會(huì)造成磁盤損毀。
如果我們刪除dist文件夾 再去保存index.js中的代碼 ,你會(huì)發(fā)現(xiàn)不會(huì)生成dist文件夾,這正是因?yàn)槲覀兇娣诺牡絻?nèi)存中,并沒有在磁盤中生成dist文件夾
那么既然保存在內(nèi)存中那我們index.js就不能在**<script src=“…/dist/bundle.js”></script>**中訪問到
在上面運(yùn)行的指令中說明了是在http://localhost:8080/bundle.js中可以訪問
那么就是將**<script src=“…/dist/bundle.js”></script>換為<script src=“/bundle.js”></script>**
③ 在瀏覽器中訪問 http://localhost:8080 地址,查看自動(dòng)打包效果
- 打開網(wǎng)址如下:

注意:打開src文件夾打開index.html就可以看見
注意:webpack-dev-server 會(huì)啟動(dòng)一個(gè)實(shí)時(shí)打包的 http 服務(wù)器
3 打包生成的文件哪兒去了?
① 不配置 webpack-dev-server 的情況下,webpack 打包生成的文件,會(huì)存放到實(shí)際的物理磁盤上
- 嚴(yán)格遵守開發(fā)者在 webpack.config.js 中指定配置
- 根據(jù) output 節(jié)點(diǎn)指定路徑進(jìn)行存放
② 配置了 webpack-dev-server 之后,打包生成的文件存放到了內(nèi)存中
- 不再根據(jù) output 節(jié)點(diǎn)指定的路徑,存放到實(shí)際的物理磁盤上
- 提高了實(shí)時(shí)打包輸出的性能,因?yàn)閮?nèi)存比物理磁盤速度快很多
4 生成到內(nèi)存中的文件該如何訪問?
webpack-dev-server 生成到內(nèi)存中的文件,默認(rèn)放到了項(xiàng)目的根目錄中,而且是虛擬的、不可見的。
- 可以直接用 / 表示項(xiàng)目根目錄,后面跟上要訪問的文件名稱,即可訪問內(nèi)存中的文件
- 例如 /bundle.js 就表示要訪問 webpack-dev-server 生成到內(nèi)存中的 bundle.js 文件
1.3.3 html-webpack-plugin
上一節(jié)說到 ,如果我們一進(jìn)入8080端口要打開src文件夾才能看到index.html頁面
如果我們想一進(jìn)入8080端口就打開index.html頁面 就需要借助下面的插件
html-webpack-plugin 是 webpack 中的 HTML 插件,可以通過此插件自定制 index.html 頁面的內(nèi)容。
需求:通過 html-webpack-plugin 插件,將 src 目錄下的 index.html 首頁,復(fù)制到項(xiàng)目根目錄中一份!
1 安裝 html-webpack-plugin
運(yùn)行如下的命令,即可在項(xiàng)目中安裝此插件:
npm install html-webpack-plugin@5.3.2 -D
2 配置 html-webpack-plugin
代碼
// 1. 導(dǎo)入 html-webpack-plugin 這個(gè)插件,得到插件的構(gòu)造函數(shù)
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構(gòu)造函數(shù),創(chuàng)建插件的實(shí)例對象,相當(dāng)于實(shí)例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復(fù)制哪個(gè)頁面
template:'./src/index.html',
// 指定復(fù)制出來的文件名和存放路徑
filename:'./index.html'
})
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣龋皇求w積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development',
plugins: [htmlPlugin]
}
- webpack.config.js
//導(dǎo)入path模塊
const path = require('path');
// 1. 導(dǎo)入 html-webpack-plugin 這個(gè)插件,得到插件的構(gòu)造函數(shù)
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構(gòu)造函數(shù),創(chuàng)建插件的實(shí)例對象,相當(dāng)于實(shí)例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復(fù)制哪個(gè)頁面
template:'./src/index.html',
// 指定復(fù)制出來的文件名和存放路徑
filename:'./index.html'
})
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣?,而不是體積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個(gè)文件'
//__dirname 相當(dāng)于當(dāng)前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
},
// 3. 插件的數(shù)組,將來 webpack 在運(yùn)行時(shí),會(huì)加載并調(diào)用這些插件
plugins: [htmlPlugin]
}
3 解惑 html-webpack-plugin
① 通過 HTML 插件復(fù)制到項(xiàng)目根目錄中的 index.html 頁面,也被放到了內(nèi)存中。
② HTML 插件在生成的 index.html 頁面,自動(dòng)注入了打包的 bundle.js 文件。
這句話的意思是,當(dāng)運(yùn)行后,我們把html中的導(dǎo)入的bundle.js文件個(gè)注釋。再去刷新頁面還能加載出來,右鍵查看網(wǎng)頁源代碼發(fā)現(xiàn)
<!DOCTYPE html>
<html lang="en">
<head>
<!-- 這是注釋的-->
<!-- <script src="/bundle.js"></script> -->
<!-- 這是自動(dòng)注入了打包的 bundle.js 文件-->
<script defer src="bundle.js"></script></head>
<body>
<ul>
<li>這是第1個(gè)li</li>
</ul>
</body>
</html>
4 devServer 節(jié)點(diǎn)
如果我們想在第一次打包時(shí),就可以自動(dòng)打開頁面,就要安裝webpack-dev-server 插件
在 webpack.config.js 配置文件中,可以通過 devServer 節(jié)點(diǎn)對 webpack-dev-server 插件進(jìn)行更多的配置,
示例代碼如下:
devServer: {
// 首次打包成功后,自動(dòng)打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運(yùn)行的主機(jī)地址
host: '127.0.0.1'
},
注意:凡是修改了 webpack.config.js 配置文件,或修改了 package.json 配置文件,必須重啟實(shí)時(shí)打包的服
務(wù)器,否則最新的配置文件無法生效!
- webpack.config.js
//導(dǎo)入path模塊
const path = require('path');
// 1. 導(dǎo)入 html-webpack-plugin 這個(gè)插件,得到插件的構(gòu)造函數(shù)
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構(gòu)造函數(shù),創(chuàng)建插件的實(shí)例對象,相當(dāng)于實(shí)例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復(fù)制哪個(gè)頁面
template:'./src/index.html',
// 指定復(fù)制出來的文件名和存放路徑
filename:'./index.html'
})
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣龋皇求w積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個(gè)文件'
//__dirname 相當(dāng)于當(dāng)前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
},
// 3. 插件的數(shù)組,將來 webpack 在運(yùn)行時(shí),會(huì)加載并調(diào)用這些插件
plugins: [htmlPlugin],
devServer: {
// 首次打包成功后,自動(dòng)打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運(yùn)行的主機(jī)地址
host: '127.0.0.1'
}
}
1.4 webpack 中的 loader
1 loader 概述
在實(shí)際開發(fā)過程中,webpack 默認(rèn)只能打包處理以 .js 后綴名結(jié)尾的模塊。其他非 .js 后綴名結(jié)尾的模塊,
webpack 默認(rèn)處理不了,需要調(diào)用 loader 加載器才可以正常打包,否則會(huì)報(bào)錯(cuò)!
loader 加載器的作用:協(xié)助 webpack 打包處理特定的文件模塊。比如:
- css-loader 可以打包處理 .css 相關(guān)的文件
- less-loader 可以打包處理 .less 相關(guān)的文件
- babel-loader 可以打包處理 webpack 無法處理的高級 JS 語法
2 loader 的調(diào)用過程

3 打包處理 css 文件
- src–>css–>index.css
li {
list-style: none;
}
以前我們是在index.html中引用css,但是以后可以把css當(dāng)作一個(gè)模塊來使用。如下
import './css/index.css'
- src–>index1.js
// 1. 使用 ES6 導(dǎo)入語法,導(dǎo)入 jQuery
import $ from 'jquery'
// 導(dǎo)入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導(dǎo)入語法進(jìn)行導(dǎo)入和使用)
import './css/index.css'
// 2. 定義 jQuery 的入口函數(shù)
$(function () {
// 3. 實(shí)現(xiàn)奇偶行變色
// 奇數(shù)行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數(shù)
// 1 是奇數(shù)
})
此時(shí)運(yùn)行會(huì)報(bào)錯(cuò)
ERROR in ./src/css/index.css 1:3 Module parse failed: Unexpected token (1:3) --模塊解析失敗 You may need an appropriate loader to handle this file type --你需要一個(gè)合適loder的文件去處理這個(gè)問題
① 運(yùn)行 npm i style-loader@3.0.0 css-loader@5.2.6 -D 命令,安裝處理 css 文件的 loader
② 在 webpack.config.js 的 module -> rules 數(shù)組中,添加 loader 規(guī)則如下:
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應(yīng)的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
]
}
其中,test 表示匹配的文件類型, use 表示對應(yīng)要調(diào)用的 loader
注意:
- use 數(shù)組中指定的 loader 順序是固定的
- 多個(gè) loader 的調(diào)用順序是:從后往前調(diào)用 [‘style-loader’, ‘css-loader’]
工作原理
- webpack 默認(rèn)只能打包處理.js 結(jié)尾的文件,處理不了其他后綴的文件
- 由于代碼中包含了index.js這個(gè)文件,因此webpack默認(rèn)處理不了
- 當(dāng)webpack發(fā)現(xiàn)某個(gè)文件處理不了,就會(huì)查早webpack.config.js 這個(gè)配置文件,看module.rules數(shù)組中,是否配置了對應(yīng)的loader加載器
- webpack把index.css這個(gè)文件,先轉(zhuǎn)交給最后一個(gè)loader進(jìn)行處理(先轉(zhuǎn)交給css-loader)
- 當(dāng) css-loader 處理完畢之后,會(huì)把處理的結(jié)果,轉(zhuǎn)交給下一個(gè)loader(轉(zhuǎn)交給 style-loader)
- 當(dāng)style-loader處理完畢之后,發(fā)現(xiàn)沒有下一個(gè)loader了,于是就把處理的結(jié)果,轉(zhuǎn)交給webpack
- webpack 把style-loader處理的結(jié)果,合并到./dist/bundle.js 中,最終生成打包好的文件。
4 打包處理 less 文件
less和css
區(qū)別:
1、Less是一門CSS預(yù)處理語言,而css是一種用來表現(xiàn)HTML或XML等文件樣式的計(jì)算機(jī)語言;
2、less擴(kuò)展了CSS語言,增加了css本身沒有的變量、函數(shù)等特性;
3、css可以被瀏覽器直接識別,less需要先編譯為css。
- src–>css–>index.less
html,body,ul{
margin: 0;
padding: 0;
li {
line-height: 30px;
padding-left: 20px;
font-size: 12px;
}
}
- src–>index1.js
// 1. 使用 ES6 導(dǎo)入語法,導(dǎo)入 jQuery
import $ from 'jquery'
// 導(dǎo)入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導(dǎo)入語法進(jìn)行導(dǎo)入和使用)
import './css/index.css'
import './css/index.less'
// 2. 定義 jQuery 的入口函數(shù)
$(function () {
// 3. 實(shí)現(xiàn)奇偶行變色
// 奇數(shù)行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數(shù)
// 1 是奇數(shù)
})
① 運(yùn)行 npm i less-loader@10.0.1 less@4.1.1 -D 命令
② 在 webpack.config.js 的 module -> rules 數(shù)組中,添加 loader 規(guī)則如下:
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
- webpack.config.js
//導(dǎo)入path模塊
const path = require('path');
// 1. 導(dǎo)入 html-webpack-plugin 這個(gè)插件,得到插件的構(gòu)造函數(shù)
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構(gòu)造函數(shù),創(chuàng)建插件的實(shí)例對象,相當(dāng)于實(shí)例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復(fù)制哪個(gè)頁面
template:'./src/index.html',
// 指定復(fù)制出來的文件名和存放路徑
filename:'./index.html'
})
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣?,而不是體積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個(gè)文件'
//__dirname 相當(dāng)于當(dāng)前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
},
// 3. 插件的數(shù)組,將來 webpack 在運(yùn)行時(shí),會(huì)加載并調(diào)用這些插件
plugins: [htmlPlugin],
devServer: {
// 首次打包成功后,自動(dòng)打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運(yùn)行的主機(jī)地址
host: '127.0.0.1'
},
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應(yīng)的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader',] },
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
// 處理圖片文件的 loader
]
}
}
5 打包處理樣式表中與url 路徑相關(guān)的文件
- src–>image–>xunlei 放一個(gè)小圖標(biāo)的圖片
- src–>index.js 加上這句<img src=“” alt=“” class=“box”>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="./index.js"></script> -->
<!-- <script src="../dist/main.js"></script> -->
<!-- <script src="../dist/bundle.js"></script> -->
<!-- 加載和引用內(nèi)存中的 bundle.js -->
<script src="/bundle.js"></script>
</head>
<body>
<ul>
<li>這是第1個(gè)li</li>
<li>這是第2個(gè)li</li>
<li>這是第3個(gè)li</li>
<li>這是第4個(gè)li</li>
<li>這是第5個(gè)li</li>
<li>這是第6個(gè)li</li>
<li>這是第7個(gè)li</li>
<li>這是第8個(gè)li</li>
<li>這是第9個(gè)li</li>
</ul>
<!-- 需求:把 /src/images/logo.jpg 設(shè)置給 src 屬性 -->
<img src="" alt="" class="box">
</body>
</html>
語法
// 1. 導(dǎo)入圖片,得到圖片文件
import logo from './image/XunLei.png'
// console.log(logo)
// 2. 給 img 標(biāo)簽的 src 動(dòng)態(tài)賦值
$('.box').attr('src', logo) //attr()方法設(shè)置或返回被選元素的屬性值
- src–>index1.js
// 1. 使用 ES6 導(dǎo)入語法,導(dǎo)入 jQuery
import $ from 'jquery'
// 導(dǎo)入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導(dǎo)入語法進(jìn)行導(dǎo)入和使用)
import './css/index.css'
import './css/index.less'
// 1. 導(dǎo)入圖片,得到圖片文件
import logo from './image/XunLei.png'
// console.log(logo) 打印圖片得到了 圖片的base64的字符串
// 2. 給 img 標(biāo)簽的 src 動(dòng)態(tài)賦值
$('.box').attr('src', logo) //attr()方法設(shè)置或返回被選元素的屬性值
// 2. 定義 jQuery 的入口函數(shù)
$(function () {
// 3. 實(shí)現(xiàn)奇偶行變色
// 奇數(shù)行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數(shù)
// 1 是奇數(shù)
})
① 運(yùn)行 npm i url-loader@4.1.1 file-loader@6.2.0 -D 命令
② 在 webpack.config.js 的 module -> rules 數(shù)組中,添加 loader 規(guī)則如下:
其中 ? 之后的是 loader 的參數(shù)項(xiàng):
- limit 用來指定圖片的大小,單位是字節(jié)(byte)
- 只有 ≤ limit 大小的圖片,才會(huì)被轉(zhuǎn)為 base64 格式的圖片 ,如果大于則是路徑
樣式的轉(zhuǎn)換過程
注意在 webpack中 把 .css和.less結(jié)尾的樣式轉(zhuǎn)換成了bundle.js中 類似于js的方式去運(yùn)行
6. 打包處理 js 文件中的高級語法
webpack 只能打包處理一部分高級的 JavaScript 語法。對于那些 webpack 無法處理的高級 js 語法,需要借
助于 babel-loader 進(jìn)行打包處理。例如 webpack 無法處理下面的 JavaScript 代碼:
- src–>index1.js
// 1. 使用 ES6 導(dǎo)入語法,導(dǎo)入 jQuery
import $ from 'jquery'
// 導(dǎo)入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導(dǎo)入語法進(jìn)行導(dǎo)入和使用)
// 如果某個(gè)模塊中,使用 from 接收到的成員為 undefined,則沒必要進(jìn)行接收
import './css/index.css'
import './css/index.less'
// 這里沒有寫成 import a from './css/index.css' console.log(a) 都是underfined
// 注意在 webpack中 把 .css和.less結(jié)尾的樣式轉(zhuǎn)換成了bundle.js中 類似于js的方式去運(yùn)行
// 1. 導(dǎo)入圖片,得到圖片文件
import logo from './image/XunLei.png'
console.log(logo) //打印圖片得到了 圖片的base64的字符串
// 2. 給 img 標(biāo)簽的 src 動(dòng)態(tài)賦值
$('.box').attr('src', logo) //attr()方法設(shè)置或返回被選元素的屬性值
// 2. 定義 jQuery 的入口函數(shù)
$(function () {
// 3. 實(shí)現(xiàn)奇偶行變色
// 奇數(shù)行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數(shù)
// 1 是奇數(shù)
})
// 定義裝飾器函數(shù)
function info(target) {
target.info = 'Person info.'
}
// 定義一個(gè)普通的類
@info
class Person {}
console.log(Person.info)
6.1 安裝 babel-loader 相關(guān)的包
運(yùn)行如下的命令安裝對應(yīng)的依賴包:
npm i babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 -D
在 webpack.config.js 的 module -> rules 數(shù)組中,添加 loader 規(guī)則如下:
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
- webpack.config.js
//導(dǎo)入path模塊
const path = require('path');
// 1. 導(dǎo)入 html-webpack-plugin 這個(gè)插件,得到插件的構(gòu)造函數(shù)
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構(gòu)造函數(shù),創(chuàng)建插件的實(shí)例對象,相當(dāng)于實(shí)例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復(fù)制哪個(gè)頁面
template: './src/index.html',
// 指定復(fù)制出來的文件名和存放路徑
filename: './index.html'
})
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣?,而不是體積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個(gè)文件'
//__dirname 相當(dāng)于當(dāng)前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
},
// 3. 插件的數(shù)組,將來 webpack 在運(yùn)行時(shí),會(huì)加載并調(diào)用這些插件
plugins: [htmlPlugin],
devServer: {
// 首次打包成功后,自動(dòng)打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運(yùn)行的主機(jī)地址
host: '127.0.0.1'
},
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應(yīng)的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader',] },
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
// 處理圖片文件的 loader
// 如果需要調(diào)用的 loader 只有一個(gè),則只傳遞一個(gè)字符串也行,如果有多個(gè)loader,則必須指定數(shù)組
// 在配置 url-loader 的時(shí)候,多個(gè)參數(shù)之間,使用 & 符號進(jìn)行分隔
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=4096&outputPath=images' },
// 使用 babel-loader 處理高級的 JS 語法
// 在配置 babel-loader 的時(shí)候,程序員只需要把自己的代碼進(jìn)行轉(zhuǎn)換即可;一定要排除 node_modules 目錄中的 JS 文件
// 因?yàn)榈谌桨械?JS 兼容性,不需要程序員關(guān)心
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
]
}
}
6.2 配置 babel-loader
在項(xiàng)目根目錄下,創(chuàng)建名為 babel.config.js 的配置文件,定義 Babel 的配置項(xiàng)如下:
module.exports = {
// 聲明 babel 可用的插件
// 將來,webpack 在調(diào)用 babel-loader 的時(shí)候,會(huì)先加載 plugins 插件來使用
plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]]
}
- babel.config.js
module.exports = {
// 聲明 babel 可用的插件
// 將來,webpack 在調(diào)用 babel-loader 的時(shí)候,會(huì)先加載 plugins 插件來使用
plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]]
}
運(yùn)行后在控制臺輸出 Person info.
注意:上面就是插件中的插件 babel-loader用到了插件plugin-proposal-decorators
詳情請參考 Babel 的官網(wǎng) https://babeljs.io/docs/en/babel-plugin-proposal-decorators
1.5 打包發(fā)布
前面就是打包到了內(nèi)存中但是我需要打包到磁盤中,就需要下面的打包發(fā)布,交給后端人員
1.5.1 為什么要打包發(fā)布
項(xiàng)目開發(fā)完成之后,需要使用 webpack 對項(xiàng)目進(jìn)行打包發(fā)布,主要原因有以下兩點(diǎn):
① 開發(fā)環(huán)境下,打包生成的文件存放于內(nèi)存中,無法獲取到最終打包生成的文件
② 開發(fā)環(huán)境下,打包生成的文件不會(huì)進(jìn)行代碼壓縮和性能優(yōu)化
為了讓項(xiàng)目能夠在生產(chǎn)環(huán)境中高性能的運(yùn)行,因此需要對項(xiàng)目進(jìn)行打包發(fā)布。
1.5.2 配置 webpack 的打包發(fā)布
在 package.json 文件的 scripts 節(jié)點(diǎn)下,新增 build 命令如下:
"scripts": {
"dev": "webpack",
"build": "webpack --mode production"
//注意這里 要用 npm run build進(jìn)行發(fā)布 ,前面使用npm run dev來進(jìn)行實(shí)時(shí)保存到內(nèi)存中
// 注意build可以隨便命名 但是后面的webpack --mode production不能隨便寫
},
–model 是一個(gè)參數(shù)項(xiàng),用來指定 webpack 的運(yùn)行模式。production 代表生產(chǎn)環(huán)境,會(huì)對打包生成的文件
進(jìn)行代碼壓縮和性能優(yōu)化。
注意:通過 --model 指定的參數(shù)項(xiàng),會(huì)覆蓋 webpack.config.js 中的 model 選項(xiàng)。
- package.json
"scripts": {
"dev": "webpack serve",
"build": "webpack --mode production"
}
注意這里說一下流程
我們在運(yùn)行或者打包時(shí) ,先進(jìn)入webpack.config.js 再到package.json中
- 在npm run dev 時(shí)我們要求的是速度快,所以不需要壓縮 而不需要壓縮則速度快,所以 在webpack.config.js 中修改 module.exports = {mode: production’'}
- 在npm run build時(shí) 我們時(shí)發(fā)布 要求體積小 ,所以需要壓縮,而壓縮需要時(shí)間 所以 在webpack.config.js 中修改module.exports = {mode: ‘development’}
由上可知 我們在打包中就不需要 在 webpack.config.js 指定類型,而在package.json中 修改 “scripts”: {“build”: “webpack --mode production”}將mode的默認(rèn)值development進(jìn)行修改,改為production, 因?yàn)?ndash;mode選項(xiàng)的優(yōu)先級高于選項(xiàng)mode的優(yōu)先級 會(huì)進(jìn)行覆蓋
當(dāng)打包過后就可以發(fā)布到服務(wù)器了
1.5.3 把 JavaScript 文件統(tǒng)一生成到 js 目錄中
我們發(fā)現(xiàn)我們打包生成的東西比較亂,我們打包后希望圖片和圖片放一起,js和js放一起。那么我們就需要用到下面的知識。
在 webpack.config.js 配置文件的 output 節(jié)點(diǎn)中,進(jìn)行如下的配置:
module.exports = {
output: {//這個(gè)時(shí)指定打包時(shí)要放到的地方
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
//filename: 'bundle.js'
//現(xiàn)在需要統(tǒng)一js
filename: 'js/bundle.js'
},
}
1.5.4 把圖片文件統(tǒng)一生成到 image 目錄中
修改 webpack.config.js 中的 url-loader 配置項(xiàng),新增 outputPath 選項(xiàng)即可指定圖片文件的輸出路徑:
- webpack.config.js
module.exports = {
//前面的代碼省略
module: {
rules: [
// 處理圖片文件的 loader
// 如果需要調(diào)用的 loader 只有一個(gè),則只傳遞一個(gè)字符串也行,如果有多個(gè)loader,則必須指定數(shù)組
// 在配置 url-loader 的時(shí)候,多個(gè)參數(shù)之間,使用 & 符號進(jìn)行分隔
// outputPath參數(shù)是指打包后存放的路徑 ,這里等于images表示打包生成的圖片放在dist-->images中
// 注意只有圖片大小超過limit的圖片才會(huì)放到dist-->images中
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=409&outputPath=images' },
]
}
}
1.5.5 自動(dòng)清理 dist 目錄下的舊文件
由于每次打包發(fā)布都需要?jiǎng)h除dist目錄比較麻煩。
為了在每次打包發(fā)布時(shí)自動(dòng)清理掉 dist 目錄中的舊文件,可以安裝并配置 clean-webpack-plugin 插件:
首先找到npmjs.com進(jìn)入官網(wǎng),然后去點(diǎn)擊,文檔如下
安裝:-D的縮寫是–save-dev
Installation npm install --save-dev clean-webpack-plugin
使用:由于叫clean-webpack-plugin,所以在webpack.config.js 使用
Usage
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpackConfig = {
plugins: [
/**
* All files inside webpack's output.path directory will be removed once, but the
* directory itself will not be. If using webpack 4+'s default configuration,
* everything under <PROJECT_DIR>/dist/ will be removed.
* Use cleanOnceBeforeBuildPatterns to override this behavior.
*
* During rebuilds, all webpack assets that are not used anymore
* will be removed automatically.
*
* See `Options and Defaults` for information
*/
new CleanWebpackPlugin(),
],
};
module.exports = webpackConfig;
上面的代碼可以簡化為
// 導(dǎo)入clean-webpack-plugin插件
// 下面這句話是解構(gòu)賦值
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// const obj = require('clean-webpack-plugin');
// console.log(obj);
// 結(jié)果為{ CleanWebpackPlugin: [class CleanWebpackPlugin] }
// 則const { CleanWebpackPlugin } = require('clean-webpack-plugin');相當(dāng)于
// const { CleanWebpackPlugin } = { CleanWebpackPlugin: function () { } };這樣 CleanWebpackPlugin就可以直接使用了
// 這個(gè)CleanWebpackPlugin是構(gòu)造函數(shù),一般首字母大寫的都是構(gòu)造函數(shù)
module.exportCleanWebpackPlugins = {
plugins: [new CleanWebpackPlugin()],
}
webpack.config.js
//導(dǎo)入path模塊
const path = require('path');
// 1. 導(dǎo)入 html-webpack-plugin 這個(gè)插件,得到插件的構(gòu)造函數(shù)
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構(gòu)造函數(shù),創(chuàng)建插件的實(shí)例對象,相當(dāng)于實(shí)例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復(fù)制哪個(gè)頁面
template: './src/index.html',
// 指定復(fù)制出來的文件名和存放路徑
filename: './index.html'
})
// 導(dǎo)入clean-webpack-plugin插件
// 下面這句話是解構(gòu)賦值
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// const obj = require('clean-webpack-plugin');
// console.log(obj);
// 結(jié)果為{ CleanWebpackPlugin: [class CleanWebpackPlugin] }
// 則const { CleanWebpackPlugin } = require('clean-webpack-plugin');相當(dāng)于
// const { CleanWebpackPlugin } = { CleanWebpackPlugin: function () { } };這樣 CleanWebpackPlugin就可以直接使用了
module.exports = {
// mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣?,而不是體積;
// 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個(gè)文件'
//__dirname 相當(dāng)于當(dāng)前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {//這個(gè)時(shí)指定打包時(shí)要放到的地方
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
//filename: 'bundle.js'
//現(xiàn)在需要統(tǒng)一js
filename: 'js/bundle.js'
},
// 3. 插件的數(shù)組,將來 webpack 在運(yùn)行時(shí),會(huì)加載并調(diào)用這些插件
// new CleanWebpackPlugin()是 打包時(shí)清除舊包 要用到的插件
plugins: [htmlPlugin, new CleanWebpackPlugin()],
devServer: {
// 首次打包成功后,自動(dòng)打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運(yùn)行的主機(jī)地址
host: '127.0.0.1'
},
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應(yīng)的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader',] },
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
// 處理圖片文件的 loader
// 如果需要調(diào)用的 loader 只有一個(gè),則只傳遞一個(gè)字符串也行,如果有多個(gè)loader,則必須指定數(shù)組
// 在配置 url-loader 的時(shí)候,多個(gè)參數(shù)之間,使用 & 符號進(jìn)行分隔
// outputPath參數(shù)是指打包后存放的路徑 ,這里等于images表示打包生成的圖片放在dist-->images中
// 注意只有圖片大小超過limit的圖片才會(huì)放到dist-->images中
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=409&outputPath=images' },
// 使用 babel-loader 處理高級的 JS 語法
// 在配置 babel-loader 的時(shí)候,程序員只需要把自己的代碼進(jìn)行轉(zhuǎn)換即可;一定要排除 node_modules 目錄中的 JS 文件
// 因?yàn)榈谌桨械?JS 兼容性,不需要程序員關(guān)心
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
]
}
}
// module.exports = {
// // mode 代表 webpack 運(yùn)行的模式,可選值有兩個(gè) development 和 production
// // 結(jié)論:開發(fā)時(shí)候一定要用 development,因?yàn)樽非蟮氖谴虬乃俣龋皇求w積;
// // 反過來,發(fā)布上線的時(shí)候一定能要用 production,因?yàn)樯暇€追求的是體積小,而不是打包速度快!
// mode: 'production'
// }
1.6 Source Map
比如在src–>index1.js中 把第39行的console.log(Person.info)改為consle.log(Person.info)
在我們運(yùn)行npm run dev時(shí),如果我們代碼報(bào)錯(cuò),報(bào)錯(cuò)提示的41行是我們在內(nèi)存中生成的index1.js的行數(shù),而不是我們代碼src–>index1.js中的行數(shù)

1.6.1 生產(chǎn)環(huán)境遇到的問題
前端項(xiàng)目在投入生產(chǎn)環(huán)境之前,都需要對 JavaScript 源代碼進(jìn)行壓縮混淆,從而減小文件的體積,提高文件的
加載效率。此時(shí)就不可避免的產(chǎn)生了另一個(gè)問題:
對壓縮混淆之后的代碼除錯(cuò)(debug)是一件極其困難的事情

- 變量被替換成沒有任何語義的名稱
- 空行和注釋被剔除
1.6.2 什么是 Source Map
Source Map 就是一個(gè)信息文件,里面儲(chǔ)存著位置信息。也就是說,Source Map 文件中存儲(chǔ)著壓縮混淆后的
代碼,所對應(yīng)的轉(zhuǎn)換前的位置。
有了它,出錯(cuò)的時(shí)候,除錯(cuò)工具將直接顯示原始代碼,而不是轉(zhuǎn)換后的代碼,能夠極大的方便后期的調(diào)試。
1.6.3 webpack開發(fā)環(huán)境下的Source Map
在開發(fā)環(huán)境下,webpack 默認(rèn)啟用了 Source Map 功能。當(dāng)程序運(yùn)行出錯(cuò)時(shí),可以直接在控制臺提示錯(cuò)誤行
的位置,并定位到具體的源代碼:
3.1 默認(rèn) Source Map 的問題
開發(fā)環(huán)境下默認(rèn)生成的 Source Map,記錄的是生成后的代碼的位置。會(huì)導(dǎo)致運(yùn)行時(shí)報(bào)錯(cuò)的行數(shù)與源代碼的行
數(shù)不一致的問題。示意圖如下:

3.2 解決默認(rèn) Source Map 的問題
開發(fā)環(huán)境下,推薦在 webpack.config.js 中添加如下的配置,即可保證運(yùn)行時(shí)報(bào)錯(cuò)的行數(shù)與源代碼的行數(shù)
保持一致:
module.exports = {
// 在開發(fā)調(diào)試階段,建議大家都把 devtool 的值設(shè)置為 eval-source-map
// devtool: 'eval-source-map',
// 在實(shí)際發(fā)布的時(shí)候,建議大家把 devtool 的值設(shè)置為 nosources-source-map 或直接關(guān)閉 SourceMap
devtool: 'eval-source-map',
}
1.6.4 webpack生產(chǎn)環(huán)境下的Source Map
在生產(chǎn)環(huán)境下,如果省略了 devtool 選項(xiàng),則最終生成的文件中不包含 Source Map。這能夠防止原始代碼通
過 Source Map 的形式暴露給別有所圖之人。

4.1 只定位行數(shù)不暴露源碼
在生產(chǎn)環(huán)境下,如果只想定位報(bào)錯(cuò)的具體行數(shù),且不想暴露源碼。此時(shí)可以將 devtool 的值設(shè)置為
nosources-source-map。實(shí)際效果如圖所示:

4.2 定位行數(shù)且暴露源碼
在生產(chǎn)環(huán)境下,如果想在定位報(bào)錯(cuò)行數(shù)的同時(shí),展示具體報(bào)錯(cuò)的源碼。此時(shí)可以將 devtool 的值設(shè)置為
source-map。實(shí)際效果如圖所示:

1.6.5 Source Map 的最佳實(shí)踐
① 開發(fā)環(huán)境下(development):
- 建議把 devtool 的值設(shè)置為 eval-source-map
- 好處:可以精準(zhǔn)定位到具體的錯(cuò)誤行
② 生產(chǎn)環(huán)境下(production):
- 建議關(guān)閉 Source Map (也就是注釋掉)或?qū)?devtool 的值設(shè)置為 nosources-source-map
- 好處:防止源碼泄露,提高網(wǎng)站的安全性
實(shí)際開發(fā)中需要自己配置 webpack 嗎?
答案:不需要!
- 實(shí)際開發(fā)中會(huì)使命令行工具(俗稱 CLI)一鍵生成帶有 webpack 的項(xiàng)目
- 開箱即用,所有 webpack 配置項(xiàng)都是現(xiàn)成的!
- 我們只需要知道 webpack 中的基本概念即可!
1.7webpack中@的原理和好處
當(dāng)我們在導(dǎo)入模塊進(jìn)行使用時(shí)有時(shí)需要往上翻 …/…/msg.js
比如新建src–>js,src–>js–>test,src–>js–>test–>info.js,msg.js
- src–>js–>test–>info.js
import msg from '../../msg' //如果這個(gè)我們需要往上翻兩層,才能導(dǎo)入msg.js模塊 console.log(msg)
- msg.js
export default {
msg: 'hello Vue.'
}
- src–>index1.js
// 導(dǎo)入 src/js/test/info.js import './js/test/info.js'
執(zhí)行過程如下 先在src–>index1.js中導(dǎo)入src–>js–>test–>info.js,在從src–>js–>test–>info.js中導(dǎo)入msg.js

結(jié)果為{msg: ‘hello Vue.’} 為了不用…/…/而用@代表根目錄 ,進(jìn)而實(shí)現(xiàn)從外往里找、
首先需要在webpack.config.js中進(jìn)行配置
const path = require('path')
// 1. 導(dǎo)入 html-webpack-plugin 這個(gè)插件,得到插件的構(gòu)造函數(shù)
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構(gòu)造函數(shù),創(chuàng)建插件的實(shí)例對象
const htmlPlugin = new HtmlPlugin({
// 指定要復(fù)制哪個(gè)頁面
template: './src/index.html',
// 指定復(fù)制出來的文件名和存放路徑
filename: './index.html'
})
// 注意:左側(cè)的 { } 是解構(gòu)賦值
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// 使用 Node.js 中的導(dǎo)出語法,向外導(dǎo)出一個(gè) webpack 的配置對象
module.exports = {
mode: 'development',
resolve: {
alias: {
// 告訴 webpack,程序員寫的代碼中,@ 符號表示 src 這一層目錄
'@': path.join(__dirname, './src/')
}
}
}
修改代碼
- src–>js–>test–>info.js
// import msg from '../../msg' //如果這個(gè)我們需要往上翻兩層,才能導(dǎo)入msg.js模塊 import msg from '@/msg.js' // 建議大家使用 @ 表示 src 源代碼目錄,從外往里查找;不要使用 ../ 從里往外查找 // @/msg.js console.log(msg)
- msg.js 不變
export default {
msg: 'hello Vue.'
}
- src–>index1.js
// 導(dǎo)入 src/js/test/info.js import '@/js/test/info.js'
總結(jié)
① 能夠掌握 webpack 的基本使用
- 安裝、webpack.config.js、修改打包入口
- 了解常用的 plugin 的基本使用
- webpack-dev-server、html-webpack-plugin
③ 了解常用的 loader 的基本使用
- loader 的作用、loader 的調(diào)用過程
④ 能夠說出 Source Map 的作用
- 精準(zhǔn)定位到錯(cuò)誤行并顯示對應(yīng)的源碼
- 方便開發(fā)者調(diào)試源碼中的錯(cuò)誤
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解node child_process模塊學(xué)習(xí)筆記
這篇文章主要介紹了詳解node child_process模塊學(xué)習(xí)筆記,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
socket.io學(xué)習(xí)教程之深入學(xué)習(xí)篇(三)
這篇文章更加深入的給大家介紹了socket.io的相關(guān)資料,之前已經(jīng)介紹了socket.io的基本教程和應(yīng)用,本文更為深入的來介紹下socket.io的使用,需要的朋友可以參考借鑒,下面來一起看看吧。2017-04-04
node?NPM庫增強(qiáng)版globby?Promise使用學(xué)習(xí)
這篇文章主要為大家介紹了node?NPM庫增強(qiáng)版globby?Promise使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
NodeJS 實(shí)現(xiàn)手機(jī)短信驗(yàn)證模塊阿里大于功能
這篇文章主要介紹了NodeJS 實(shí)現(xiàn)手機(jī)短信驗(yàn)證模塊阿里大于功能,需要的朋友可以參考下2017-06-06
使用Redis和Node.js來開發(fā)簡單的實(shí)時(shí)聊天功能
在眾多實(shí)時(shí)通信的技術(shù)中,Redis和Node.js的結(jié)合是一種非常強(qiáng)大和流行的選擇,Redis是一種高性能的鍵值存儲(chǔ)數(shù)據(jù)庫,而Node.js是一個(gè)基于事件驅(qū)動(dòng)的JavaScript運(yùn)行時(shí)環(huán)境,兩者的結(jié)合可以輕松實(shí)現(xiàn)實(shí)時(shí)聊天功能,本文將指導(dǎo)您使用Redis和Node.js來開發(fā)一個(gè)簡單的實(shí)時(shí)聊天功能2024-08-08

