從0-1搭建webpack的前端工程化項目教程
1.1 前端工程化的相關概念
1 小白眼中的前端開發(fā) vs 實際的前端開發(fā)
小白眼中的前端開發(fā):
- 會寫HTML+CSS +javascript
- 美化頁面就拽一個bootstrap過來
- 需要操作DOM或發(fā)起Ajax請求就拽一個jQuery過來
- 需要快速實現一個頁面布局效果就拽一個Layui過來
實際的前端開發(fā):
- 模塊化 (js的模塊化,css的模塊化,資源的模塊化)
- 組件化 (復用現有的UI結構,樣式,行為)
- 規(guī)范化 (目錄結構的劃分,編程規(guī)范化,接口規(guī)范化,文檔規(guī)范化,Git分支管理)
- 自動化 (自動化構建,自動部署,自動化測試)
2 什么是前端工程化
前端工程化指的是:在企業(yè)級的前端項目開發(fā)中 把前端開發(fā)所需的工具,技術,流程,經驗等進行規(guī)范化,標準化。
企業(yè)中的Vue項目和React項目,都是基于工程化的方式進行開發(fā)的
好處:前端開發(fā)自成體系,有一套標準的開發(fā)方案和流程
3 前端工程化的解決方案
早期的前端工程化解決方案:
- grunt( https://www.gruntjs.net/ )
- gulp( https://www.gulpjs.com.cn/ )
目前主流的前端工程化解決方案:
- webpack( https://www.webpackjs.com/ )主要用于做項目
- parcel( https://zh.parceljs.org/ )更多是開發(fā)第三方包的時候會用
1.2 webpack 的基本使用
1.2.1 什么是 webpack
- 概念:webpack 是前端項目工程化的具體解決方案。
- 主要功能:它提供了友好的前端模塊化開發(fā)支持,以及代碼壓縮混淆、處理瀏覽器端 JavaScript 的兼容性,性能優(yōu)化等強大的功能。
- 好處:讓程序員把工作的重心放到具體功能的實現上,提高了前端開發(fā)效率和項目的可維護性。
- 注意:目前 Vue,React 等前端項目,基本上都是基于 webpack 進行工程化開發(fā)的。
1.2.創(chuàng)建列表隔行變色項目
① 新建項目空白目錄,并運行 npm init –y 命令,初始化包管理配置文件 package.json。(文件夾必須是英文的)
- package.json
...
② 新建 src 源代碼目錄。 (放程序員寫的代碼)
③ 新建 src -> index.html 首頁和 src -> index.js 腳本文件
④ 初始化首頁基本的結構
ul>li{這是第$個li}*9 //快速生成1-9個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 個 li</li>
<li>這是第 2 個 li</li>
<li>這是第 3 個 li</li>
<li>這是第 4 個 li</li>
<li>這是第 5 個 li</li>
<li>這是第 6 個 li</li>
<li>這是第 7 個 li</li>
<li>這是第 8 個 li</li>
<li>這是第 9 個 li</li>
</ul>
</body>
</html>
⑤ 運行 npm install jquery –s 命令,安裝 jQuery (不用搜索下載了,–s是加到dependencies()) -s是–save的縮寫
- package-lock.json(增加)
.....
- node_modules(增加文件夾)
⑥ 通過 ES6 模塊化的方式導入 jQuery,實現列表隔行變色效果
- src -> index.js
// 1. 使用 ES6 導入語法,導入 jQuery
import $ from 'jquery'
// 2. 定義 jQuery 的入口函數
$(function () {
// 3. 實現奇偶行變色
// 奇數行為紅色
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'pink')
// 0 是偶數
// 1 是奇數
})
結果你會發(fā)現報錯因為語法高級無法識別接下來就需要用webpack
1.2.3. 在項目中安裝 webpack
在終端運行如下的命令,安裝 webpack 相關的兩個包:
- npm install webpack@5.42.1 webpack-cli@4.7.2 -D (–S是加到devDependencies(只在開發(fā)階段用)這個節(jié)點中)
- -D是–save-dev的縮寫 在npmjs.com 官方文檔中可以查看放在那里
注意:安裝完webpack在node_modules文件夾會多很多文件夾
1.2.4 在項目中配置 webpack
① 在項目根目錄中,創(chuàng)建名為 webpack.config.js 的 webpack 配置文件,并初始化如下的基本配置:
- webpack.config.js
module.exports = {
// mode 代表 webpack 運行的模式,可選值有兩個 development 和 production
// 結論:開發(fā)時候一定要用 development,因為追求的是打包的速度,而不是體積;
// 反過來,發(fā)布上線的時候一定能要用 production,因為上線追求的是體積小,而不是打包速度快!
mode: 'development'
}
② 在 package.json 的 scripts 節(jié)點下,新增 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"
},
③ 在終端中運行 npm run dev 命令,啟動 webpack 進行項目的打包構建(一會介紹打包介紹)
終端(又又又報錯了):
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
這個錯誤是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] //將上面的兩個index.jsjquery.js合并在了main.js webpack 5.42.1 compiled successfully in 253 ms
運行完之后在文件中多了 dist文件夾 并且在dist文件夾下有main.js
main.js是webpage根據我們index.js生成的
也就是說index.js可以用main.js替換,因為main.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個li</li>
<li>這是第2個li</li>
<li>這是第3個li</li>
<li>這是第4個li</li>
<li>這是第5個li</li>
<li>這是第6個li</li>
<li>這是第7個li</li>
<li>這是第8個li</li>
<li>這是第9個li</li>
</ul>
</body>
</html>
1 mode 的可選值
mode 節(jié)點的可選值有兩個,分別是:
① development
- 開發(fā)環(huán)境
- 不會對打包生成的文件進行代碼壓縮和性能優(yōu)化
- 打包速度快,適合在開發(fā)階段使用
② production
- 生產環(huán)境
- 會對打包生成的文件進行代碼壓縮和性能優(yōu)化
- 打包速度很慢,僅適合在項目發(fā)布階段使用
production的使用
- webpack.config.js 修改
module.exports = {
// mode 代表 webpack 運行的模式,可選值有兩個 development 和 production
// 結論:開發(fā)時候一定要用 development,因為追求的是打包的速度,而不是體積;
// 反過來,發(fā)布上線的時候一定能要用 production,因為上線追求的是體積小,而不是打包速度快!
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 在真正開始打包構建之前,會先讀取這個webpack.config.js 配置文件,
從而基于給定的配置,對項目進行打包。
注意:由于 webpack 是基于 node.js 開發(fā)出來的打包工具,因此在它的配置文件中,支持使用 node.js 相關的語法和模塊進行 webpack 的個性化配置。
3 webpack 中的默認約定
在 webpack 4.x 和 5.x 的版本中,有如下的默認約定:
① 默認的打包入口文件為 src -> index.js ,如果改變src文件夾的名字和index.js的名字,然后使用npm run dev 命令會報錯
② 默認的輸出文件路徑為 dist -> main.js
注意:可以在 webpack.config.js 中修改打包的默認約定
4 自定義打包的入口與出口
在 webpack.config.js 配置文件中,通過 entry 節(jié)點指定打包的入口。通過 output 節(jié)點指定打包的出口。
先將index.js改為index1.js
示例代碼如下:
- webpack.config.js
//導入path模塊
const path = require('path');
module.exports = {
// mode 代表 webpack 運行的模式,可選值有兩個 development 和 production
// 結論:開發(fā)時候一定要用 development,因為追求的是打包的速度,而不是體積;
// 反過來,發(fā)布上線的時候一定能要用 production,因為上線追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個文件'
//__dirname 相當于當前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
}
}
將dist文件夾刪除
- 終端運行 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個li</li>
<li>這是第2個li</li>
<li>這是第3個li</li>
<li>這是第4個li</li>
<li>這是第5個li</li>
<li>這是第6個li</li>
<li>這是第7個li</li>
<li>這是第8個li</li>
<li>這是第9個li</li>
</ul>
</body>
</html>
思考一個問題,此時當我們改變index1.js中的代碼,使奇數行變成金色 ,會不會影響頁面中的顏色
答案:不會,因為我們在index.js中導入的是webpage工程化之后的代碼;
想要看到奇數行變成金色 ,必須重新運行npm run dev
但是每次運行npm run dev 太麻煩了 下面來解決這個問題
1.3 webpack 中的插件
1.3.1 webpack 插件的作用
通過安裝和配置第三方的插件,可以拓展 webpack 的能力,從而讓 webpack 用起來更方便。最常用的
webpack 插件有如下兩個:
① webpack-dev-server
- 類似于 node.js 階段用到的 nodemon 工具
- 每當修改了源代碼,webpack 會自動進行項目的打包和構建
② html-webpack-plugin
- webpack 中的 HTML 插件(類似于一個模板引擎插件)
- 可以通過此插件自定制 index.html 頁面的內容
1.3.2 webpack-dev-server
webpack-dev-server 可以讓 webpack 監(jiān)聽項目源代碼的變化,從而進行自動打包構建。
1 安裝 webpack-dev-server
運行如下的命令,即可在項目中安裝此插件:
- 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 //....一堆警告 只要不報錯就行 + 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 命令如下:
這個是用來進行實時打包的,只要程序員保存代碼就是重新打包項目
- 將package.json下的scripts屬性的dev改成如下
"scripts": {
"dev": "webpack serve",
}
② 再次運行 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 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. //當看到光標在這里一閃一閃的就好了
注意這個不能用瀏覽器打開了需要訪問http://localhost:8080 地址
注意:我們重新打包的 是放在內存中,沒有放到磁盤中 因為反復讀寫磁盤慢還會造成磁盤損毀。
如果我們刪除dist文件夾 再去保存index.js中的代碼 ,你會發(fā)現不會生成dist文件夾,這正是因為我們存放的到內存中,并沒有在磁盤中生成dist文件夾
那么既然保存在內存中那我們index.js就不能在**<script src=“…/dist/bundle.js”></script>**中訪問到
在上面運行的指令中說明了是在http://localhost:8080/bundle.js中可以訪問
那么就是將**<script src=“…/dist/bundle.js”></script>換為<script src=“/bundle.js”></script>**
③ 在瀏覽器中訪問 http://localhost:8080 地址,查看自動打包效果
- 打開網址如下:

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

3 打包處理 css 文件
- src–>css–>index.css
li {
list-style: none;
}
以前我們是在index.html中引用css,但是以后可以把css當作一個模塊來使用。如下
import './css/index.css'
- src–>index1.js
// 1. 使用 ES6 導入語法,導入 jQuery
import $ from 'jquery'
// 導入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導入語法進行導入和使用)
import './css/index.css'
// 2. 定義 jQuery 的入口函數
$(function () {
// 3. 實現奇偶行變色
// 奇數行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數
// 1 是奇數
})
此時運行會報錯
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 --你需要一個合適loder的文件去處理這個問題
① 運行 npm i style-loader@3.0.0 css-loader@5.2.6 -D 命令,安裝處理 css 文件的 loader
② 在 webpack.config.js 的 module -> rules 數組中,添加 loader 規(guī)則如下:
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
]
}
其中,test 表示匹配的文件類型, use 表示對應要調用的 loader
注意:
- use 數組中指定的 loader 順序是固定的
- 多個 loader 的調用順序是:從后往前調用 [‘style-loader’, ‘css-loader’]
工作原理
- webpack 默認只能打包處理.js 結尾的文件,處理不了其他后綴的文件
- 由于代碼中包含了index.js這個文件,因此webpack默認處理不了
- 當webpack發(fā)現某個文件處理不了,就會查早webpack.config.js 這個配置文件,看module.rules數組中,是否配置了對應的loader加載器
- webpack把index.css這個文件,先轉交給最后一個loader進行處理(先轉交給css-loader)
- 當 css-loader 處理完畢之后,會把處理的結果,轉交給下一個loader(轉交給 style-loader)
- 當style-loader處理完畢之后,發(fā)現沒有下一個loader了,于是就把處理的結果,轉交給webpack
- webpack 把style-loader處理的結果,合并到./dist/bundle.js 中,最終生成打包好的文件。
4 打包處理 less 文件
less和css
區(qū)別:
1、Less是一門CSS預處理語言,而css是一種用來表現HTML或XML等文件樣式的計算機語言;
2、less擴展了CSS語言,增加了css本身沒有的變量、函數等特性;
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 導入語法,導入 jQuery
import $ from 'jquery'
// 導入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導入語法進行導入和使用)
import './css/index.css'
import './css/index.less'
// 2. 定義 jQuery 的入口函數
$(function () {
// 3. 實現奇偶行變色
// 奇數行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數
// 1 是奇數
})
① 運行 npm i less-loader@10.0.1 less@4.1.1 -D 命令
② 在 webpack.config.js 的 module -> rules 數組中,添加 loader 規(guī)則如下:
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
- webpack.config.js
//導入path模塊
const path = require('path');
// 1. 導入 html-webpack-plugin 這個插件,得到插件的構造函數
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構造函數,創(chuàng)建插件的實例對象,相當于實例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復制哪個頁面
template:'./src/index.html',
// 指定復制出來的文件名和存放路徑
filename:'./index.html'
})
module.exports = {
// mode 代表 webpack 運行的模式,可選值有兩個 development 和 production
// 結論:開發(fā)時候一定要用 development,因為追求的是打包的速度,而不是體積;
// 反過來,發(fā)布上線的時候一定能要用 production,因為上線追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個文件'
//__dirname 相當于當前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
},
// 3. 插件的數組,將來 webpack 在運行時,會加載并調用這些插件
plugins: [htmlPlugin],
devServer: {
// 首次打包成功后,自動打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運行的主機地址
host: '127.0.0.1'
},
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader',] },
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
// 處理圖片文件的 loader
]
}
}
5 打包處理樣式表中與url 路徑相關的文件
- src–>image–>xunlei 放一個小圖標的圖片
- 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> -->
<!-- 加載和引用內存中的 bundle.js -->
<script src="/bundle.js"></script>
</head>
<body>
<ul>
<li>這是第1個li</li>
<li>這是第2個li</li>
<li>這是第3個li</li>
<li>這是第4個li</li>
<li>這是第5個li</li>
<li>這是第6個li</li>
<li>這是第7個li</li>
<li>這是第8個li</li>
<li>這是第9個li</li>
</ul>
<!-- 需求:把 /src/images/logo.jpg 設置給 src 屬性 -->
<img src="" alt="" class="box">
</body>
</html>
語法
// 1. 導入圖片,得到圖片文件
import logo from './image/XunLei.png'
// console.log(logo)
// 2. 給 img 標簽的 src 動態(tài)賦值
$('.box').attr('src', logo) //attr()方法設置或返回被選元素的屬性值
- src–>index1.js
// 1. 使用 ES6 導入語法,導入 jQuery
import $ from 'jquery'
// 導入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導入語法進行導入和使用)
import './css/index.css'
import './css/index.less'
// 1. 導入圖片,得到圖片文件
import logo from './image/XunLei.png'
// console.log(logo) 打印圖片得到了 圖片的base64的字符串
// 2. 給 img 標簽的 src 動態(tài)賦值
$('.box').attr('src', logo) //attr()方法設置或返回被選元素的屬性值
// 2. 定義 jQuery 的入口函數
$(function () {
// 3. 實現奇偶行變色
// 奇數行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數
// 1 是奇數
})
① 運行 npm i url-loader@4.1.1 file-loader@6.2.0 -D 命令
② 在 webpack.config.js 的 module -> rules 數組中,添加 loader 規(guī)則如下:
其中 ? 之后的是 loader 的參數項:
- limit 用來指定圖片的大小,單位是字節(jié)(byte)
- 只有 ≤ limit 大小的圖片,才會被轉為 base64 格式的圖片 ,如果大于則是路徑
樣式的轉換過程
注意在 webpack中 把 .css和.less結尾的樣式轉換成了bundle.js中 類似于js的方式去運行
6. 打包處理 js 文件中的高級語法
webpack 只能打包處理一部分高級的 JavaScript 語法。對于那些 webpack 無法處理的高級 js 語法,需要借
助于 babel-loader 進行打包處理。例如 webpack 無法處理下面的 JavaScript 代碼:
- src–>index1.js
// 1. 使用 ES6 導入語法,導入 jQuery
import $ from 'jquery'
// 導入樣式(在 webpack 中,一切皆模塊,都可以通過 ES6 導入語法進行導入和使用)
// 如果某個模塊中,使用 from 接收到的成員為 undefined,則沒必要進行接收
import './css/index.css'
import './css/index.less'
// 這里沒有寫成 import a from './css/index.css' console.log(a) 都是underfined
// 注意在 webpack中 把 .css和.less結尾的樣式轉換成了bundle.js中 類似于js的方式去運行
// 1. 導入圖片,得到圖片文件
import logo from './image/XunLei.png'
console.log(logo) //打印圖片得到了 圖片的base64的字符串
// 2. 給 img 標簽的 src 動態(tài)賦值
$('.box').attr('src', logo) //attr()方法設置或返回被選元素的屬性值
// 2. 定義 jQuery 的入口函數
$(function () {
// 3. 實現奇偶行變色
// 奇數行為紅色odd
$('li:odd').css('background-color', 'red')
$('li:even').css('background-color', 'green')
// 0 是偶數
// 1 是奇數
})
// 定義裝飾器函數
function info(target) {
target.info = 'Person info.'
}
// 定義一個普通的類
@info
class Person {}
console.log(Person.info)
6.1 安裝 babel-loader 相關的包
運行如下的命令安裝對應的依賴包:
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 數組中,添加 loader 規(guī)則如下:
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
- webpack.config.js
//導入path模塊
const path = require('path');
// 1. 導入 html-webpack-plugin 這個插件,得到插件的構造函數
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構造函數,創(chuàng)建插件的實例對象,相當于實例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復制哪個頁面
template: './src/index.html',
// 指定復制出來的文件名和存放路徑
filename: './index.html'
})
module.exports = {
// mode 代表 webpack 運行的模式,可選值有兩個 development 和 production
// 結論:開發(fā)時候一定要用 development,因為追求的是打包的速度,而不是體積;
// 反過來,發(fā)布上線的時候一定能要用 production,因為上線追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個文件'
//__dirname 相當于當前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
filename: 'bundle.js'
},
// 3. 插件的數組,將來 webpack 在運行時,會加載并調用這些插件
plugins: [htmlPlugin],
devServer: {
// 首次打包成功后,自動打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運行的主機地址
host: '127.0.0.1'
},
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader',] },
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
// 處理圖片文件的 loader
// 如果需要調用的 loader 只有一個,則只傳遞一個字符串也行,如果有多個loader,則必須指定數組
// 在配置 url-loader 的時候,多個參數之間,使用 & 符號進行分隔
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=4096&outputPath=images' },
// 使用 babel-loader 處理高級的 JS 語法
// 在配置 babel-loader 的時候,程序員只需要把自己的代碼進行轉換即可;一定要排除 node_modules 目錄中的 JS 文件
// 因為第三方包中的 JS 兼容性,不需要程序員關心
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
]
}
}
6.2 配置 babel-loader
在項目根目錄下,創(chuàng)建名為 babel.config.js 的配置文件,定義 Babel 的配置項如下:
module.exports = {
// 聲明 babel 可用的插件
// 將來,webpack 在調用 babel-loader 的時候,會先加載 plugins 插件來使用
plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]]
}
- babel.config.js
module.exports = {
// 聲明 babel 可用的插件
// 將來,webpack 在調用 babel-loader 的時候,會先加載 plugins 插件來使用
plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]]
}
運行后在控制臺輸出 Person info.
注意:上面就是插件中的插件 babel-loader用到了插件plugin-proposal-decorators
詳情請參考 Babel 的官網 https://babeljs.io/docs/en/babel-plugin-proposal-decorators
1.5 打包發(fā)布
前面就是打包到了內存中但是我需要打包到磁盤中,就需要下面的打包發(fā)布,交給后端人員
1.5.1 為什么要打包發(fā)布
項目開發(fā)完成之后,需要使用 webpack 對項目進行打包發(fā)布,主要原因有以下兩點:
① 開發(fā)環(huán)境下,打包生成的文件存放于內存中,無法獲取到最終打包生成的文件
② 開發(fā)環(huán)境下,打包生成的文件不會進行代碼壓縮和性能優(yōu)化
為了讓項目能夠在生產環(huán)境中高性能的運行,因此需要對項目進行打包發(fā)布。
1.5.2 配置 webpack 的打包發(fā)布
在 package.json 文件的 scripts 節(jié)點下,新增 build 命令如下:
"scripts": {
"dev": "webpack",
"build": "webpack --mode production"
//注意這里 要用 npm run build進行發(fā)布 ,前面使用npm run dev來進行實時保存到內存中
// 注意build可以隨便命名 但是后面的webpack --mode production不能隨便寫
},
–model 是一個參數項,用來指定 webpack 的運行模式。production 代表生產環(huán)境,會對打包生成的文件
進行代碼壓縮和性能優(yōu)化。
注意:通過 --model 指定的參數項,會覆蓋 webpack.config.js 中的 model 選項。
- package.json
"scripts": {
"dev": "webpack serve",
"build": "webpack --mode production"
}
注意這里說一下流程
我們在運行或者打包時 ,先進入webpack.config.js 再到package.json中
- 在npm run dev 時我們要求的是速度快,所以不需要壓縮 而不需要壓縮則速度快,所以 在webpack.config.js 中修改 module.exports = {mode: production’'}
- 在npm run build時 我們時發(fā)布 要求體積小 ,所以需要壓縮,而壓縮需要時間 所以 在webpack.config.js 中修改module.exports = {mode: ‘development’}
由上可知 我們在打包中就不需要 在 webpack.config.js 指定類型,而在package.json中 修改 “scripts”: {“build”: “webpack --mode production”}將mode的默認值development進行修改,改為production, 因為–mode選項的優(yōu)先級高于選項mode的優(yōu)先級 會進行覆蓋
當打包過后就可以發(fā)布到服務器了
1.5.3 把 JavaScript 文件統(tǒng)一生成到 js 目錄中
我們發(fā)現我們打包生成的東西比較亂,我們打包后希望圖片和圖片放一起,js和js放一起。那么我們就需要用到下面的知識。
在 webpack.config.js 配置文件的 output 節(jié)點中,進行如下的配置:
module.exports = {
output: {//這個時指定打包時要放到的地方
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
//filename: 'bundle.js'
//現在需要統(tǒng)一js
filename: 'js/bundle.js'
},
}
1.5.4 把圖片文件統(tǒng)一生成到 image 目錄中
修改 webpack.config.js 中的 url-loader 配置項,新增 outputPath 選項即可指定圖片文件的輸出路徑:
- webpack.config.js
module.exports = {
//前面的代碼省略
module: {
rules: [
// 處理圖片文件的 loader
// 如果需要調用的 loader 只有一個,則只傳遞一個字符串也行,如果有多個loader,則必須指定數組
// 在配置 url-loader 的時候,多個參數之間,使用 & 符號進行分隔
// outputPath參數是指打包后存放的路徑 ,這里等于images表示打包生成的圖片放在dist-->images中
// 注意只有圖片大小超過limit的圖片才會放到dist-->images中
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=409&outputPath=images' },
]
}
}
1.5.5 自動清理 dist 目錄下的舊文件
由于每次打包發(fā)布都需要刪除dist目錄比較麻煩。
為了在每次打包發(fā)布時自動清理掉 dist 目錄中的舊文件,可以安裝并配置 clean-webpack-plugin 插件:
首先找到npmjs.com進入官網,然后去點擊,文檔如下
安裝:-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;
上面的代碼可以簡化為
// 導入clean-webpack-plugin插件
// 下面這句話是解構賦值
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// const obj = require('clean-webpack-plugin');
// console.log(obj);
// 結果為{ CleanWebpackPlugin: [class CleanWebpackPlugin] }
// 則const { CleanWebpackPlugin } = require('clean-webpack-plugin');相當于
// const { CleanWebpackPlugin } = { CleanWebpackPlugin: function () { } };這樣 CleanWebpackPlugin就可以直接使用了
// 這個CleanWebpackPlugin是構造函數,一般首字母大寫的都是構造函數
module.exportCleanWebpackPlugins = {
plugins: [new CleanWebpackPlugin()],
}
webpack.config.js
//導入path模塊
const path = require('path');
// 1. 導入 html-webpack-plugin 這個插件,得到插件的構造函數
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 構造函數,創(chuàng)建插件的實例對象,相當于實例化對象
const htmlPlugin = new HtmlPlugin({
// 指定要復制哪個頁面
template: './src/index.html',
// 指定復制出來的文件名和存放路徑
filename: './index.html'
})
// 導入clean-webpack-plugin插件
// 下面這句話是解構賦值
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// const obj = require('clean-webpack-plugin');
// console.log(obj);
// 結果為{ CleanWebpackPlugin: [class CleanWebpackPlugin] }
// 則const { CleanWebpackPlugin } = require('clean-webpack-plugin');相當于
// const { CleanWebpackPlugin } = { CleanWebpackPlugin: function () { } };這樣 CleanWebpackPlugin就可以直接使用了
module.exports = {
// mode 代表 webpack 運行的模式,可選值有兩個 development 和 production
// 結論:開發(fā)時候一定要用 development,因為追求的是打包的速度,而不是體積;
// 反過來,發(fā)布上線的時候一定能要用 production,因為上線追求的是體積小,而不是打包速度快!
mode: 'development',
// entry: '指定要處理哪個文件'
//__dirname 相當于當前目錄 即D:\筆記之前端\筆記之Vue\筆記\code\第一章\change-rows-color
entry: path.join(__dirname, './src/index1.js'),
// 指定生成的文件要存放到哪里
output: {//這個時指定打包時要放到的地方
// 存放的目錄
path: path.join(__dirname, 'dist'),
// 生成的文件名
//filename: 'bundle.js'
//現在需要統(tǒng)一js
filename: 'js/bundle.js'
},
// 3. 插件的數組,將來 webpack 在運行時,會加載并調用這些插件
// new CleanWebpackPlugin()是 打包時清除舊包 要用到的插件
plugins: [htmlPlugin, new CleanWebpackPlugin()],
devServer: {
// 首次打包成功后,自動打開瀏覽器
open: true,
// 在 http 協(xié)議中,如果端口號是 80,則可以被省略
port: 8080,
// 指定運行的主機地址
host: '127.0.0.1'
},
module: { //所有第三方文件模塊的匹配規(guī)則
rules: [ // 文件后綴名的匹配規(guī)則
// 定義了不同模塊對應的 loader
{ test: /\.css$/, use: ['style-loader', 'css-loader',] },
// 處理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
// 處理圖片文件的 loader
// 如果需要調用的 loader 只有一個,則只傳遞一個字符串也行,如果有多個loader,則必須指定數組
// 在配置 url-loader 的時候,多個參數之間,使用 & 符號進行分隔
// outputPath參數是指打包后存放的路徑 ,這里等于images表示打包生成的圖片放在dist-->images中
// 注意只有圖片大小超過limit的圖片才會放到dist-->images中
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=409&outputPath=images' },
// 使用 babel-loader 處理高級的 JS 語法
// 在配置 babel-loader 的時候,程序員只需要把自己的代碼進行轉換即可;一定要排除 node_modules 目錄中的 JS 文件
// 因為第三方包中的 JS 兼容性,不需要程序員關心
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
]
}
}
// module.exports = {
// // mode 代表 webpack 運行的模式,可選值有兩個 development 和 production
// // 結論:開發(fā)時候一定要用 development,因為追求的是打包的速度,而不是體積;
// // 反過來,發(fā)布上線的時候一定能要用 production,因為上線追求的是體積小,而不是打包速度快!
// mode: 'production'
// }
1.6 Source Map
比如在src–>index1.js中 把第39行的console.log(Person.info)改為consle.log(Person.info)
在我們運行npm run dev時,如果我們代碼報錯,報錯提示的41行是我們在內存中生成的index1.js的行數,而不是我們代碼src–>index1.js中的行數

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

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

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

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

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

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

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

