[TOC]
>[success] # 學習前額外知識補充
1. `localhost`:本質上是一個域名,通常情況下會被解析成**127.0.0.1**
2. `127.0.0.1`:**回環地址(Loop Back Address)**,表達的意思其實是我們主機自己發出去的包,直接被自己接收
* 正常的數據庫包經常 應用層 - 傳輸層 - 網絡層 - 數據鏈路層 - 物理層
* 而回環地址,是在網絡層直接就被獲取到了,是不會經常數據鏈路層和物理層的
* 比如我們監聽 127.0.0.1時,在同一個網段下的主機中,通過ip地址是不能訪問的
3. `0.0.0.0`:監聽IPV4上所有的地址,再根據端口找到不同的應用程序
* 比如我們監聽 0.0.0.0時,在同一個網段下的主機中,**通過ip地址是可以訪問**的;
>[success] # webpack -- 開發環境運行構建
1. 在開過程希望可以做到,當**文件發生變化時**,可以自動的完成 **編譯** 和 **展示**,而不是每次通過`npm run build`編譯相關的代碼后在通過,過`live server`或者直接通過瀏覽器,打開index.html代碼每次刷新來查看改變
2. webpack 完成自動編譯檢測提供的方法
* `webpack watch mode`
* `webpack-dev-server`
>[info] ## webpack -- watch
1 .`Webpack-cli`中的 watch工作模式,這種模式下項目中的文件會被監視,一旦當這些文件發生變化,就會自動**重新運行打包任務**,但需要手動刷新瀏覽器,并且配合一些`http`服務,例如使用`http-server`
2. **原理**輪詢判斷文件的最后編輯時間是否發生變化,一開始有個文件的修改時間,先存儲起來這個修改時間,下次再有修改就會和上次修改時間比對,發現不一致的時候不會立即告訴監聽者,而是把文件修改緩存起來,等待一段時間,等待期間內如果有其他發生變化,會把變化列表一起構建,并生成到`bundle`文件夾
3. 開啟監聽模式兩種方式
* 啟動webpack 命令時 帶上--watch 參數
* 在配置webpack.config.js 中設置watch:true
>[danger] ##### 配置代碼
~~~
const HtmlWebpackPlugin = require('html-webpack-plugin')
/** @type {import('webpack').Configuration} */
const config = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
},
watch: true, // 默認false 不開啟
//只有開啟監聽模式時,watchOptions才有意義
watchOptions: {
//默認為空,不監聽的文件或者文件夾,支持正則匹配
ignored: /node_modules/,
//監聽到變化發生后會等300ms再去執行,默認300ms
aggregateTimeout: 300,
//判斷文件是否發生變化是通過不停詢問系統指定文件有沒有變化實現的,ms為單位下面意思是 每秒檢查一次變動
poll: 1000,
},
plugins: [
new HtmlWebpackPlugin({
title: 'aaa',
}),
],
}
module.exports = config
~~~
>[danger] ##### 如何解決使用watch 瀏覽器自動刷新問題
1. 如果我們希望編譯過后自動刷新瀏覽器 可以利用`live server` 這類工具,當文件發生改變后這類工具本身就會幫我們刷新頁面類似的還有` npm install browser-sync --dev`,使用指令` npm browser-sync dist --files`
2. 這類的**缺點**也狠明顯,這個過程中Webpack會不斷地將文件寫入磁盤,然后這類工具再從磁盤中讀取出來這個過程當中一次就會多出兩部磁盤讀寫操作,**過程中涉及大量磁盤讀寫操作,必然會導致效率低下**
>[info] ## webpack-dev-server (推薦)
1. `webpack-dev-server`使用了一個庫叫`memfs`(memory-fs webpack自己寫的),是 Webpack 官方推出的一個開發工具它提供一個開發服務器,并且集成了自動編譯和自動刷新瀏覽器等一系列功能,安裝完成過后,這個模塊為我們提供了一個叫作` webpack-dev-server` 的 **CLI 程序** 是**開發時候官方提供一個本地自啟服務**
2. `webpack-dev-server`為了提高工作效率,并沒有將打包后的結果寫入到磁盤。它是將打包結果暫時存放在內存當中,而內部的`http-server`也正是將內存中的這些**文件讀出來發送給瀏覽器**
3. 安裝 `npm install webpack-dev-server -D`
4. 使用 執行`webpack-dev-server`
>[danger] ##### 使用
~~~
// 開啟熱更新
devServer: {
hot: true,
},
~~~
~~~
const HtmlWebpackPlugin = require('html-webpack-plugin')
/** @type {import('webpack').Configuration} */
const config = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
},
// 開啟模塊熱更新
devServer: {
hot: true,
},
plugins: [
new HtmlWebpackPlugin({
title: 'aaa',
}),
],
}
module.exports = config
~~~
* **更多配置**
1. `webpack-dev-serve`配合的插件 `new webpack.HotModuleReplacementPlugin()`,但配置時候**hot: true 會自動引入這個 plugin**
2. 對**devServer中contentBase**'字段說明,某些資源沒有通過`webpack`打包但也想被`webpack-dev-server`調用,例如`copy-webpack-plugin`插件將一些不需要參加構建的靜態文件復制到指定文件夾,如果開發階段也使用`copy-webpack-plugin`這類插件,因為在開發過程中,我們會頻繁重復執行打包任務,假設這個目錄下需要拷貝的文件比較多,如果每次都需要執行這個插件,那打包過程開銷就會比較大,每次構建的速度也就自然會降低這類插件往往只在**上線前的那一次打包中使用**,在開發過程更多推薦這種情況使用`contentBase` 作為配置
3. `proxy`由于開發服務器的緣故,我們還將應用運行在localhost的一個端口上面,當我們訪問線上環境的,如果接口沒有開啟'CORS'跨域,就會產生跨域問題,解決開發階段這種問題的產生可以使用
~~~
// plugins:[
// new webpack.HotModuleReplacementPlugin(), // hot: true 會自動引入這個 plugin
// ],
devServer: { // 配置devServer
contentBase: './public', // 額外指明靜態資源目錄
proxy: { // 添加代理服務配置
'/api': { // 需要被代理的請求路徑前綴
// http://localhost:8080/api/users -> https://api.github.com/api/users
target: 'https://api.github.com', // 代理目標
// ----------------------注意下面pathRewrite 和上面是兩種情況一般二選一---------------------------------------
// 但是我們需要請求的接口地址沒有/api
// http://localhost:8080/api/users -> https://api.github.com/users
pathRewrite: { // 代理路徑重寫
'^/api': ''
},
// 不能使用 localhost:8080 作為請求 GitHub 的主機名
changeOrigin: true // 以實際代理請求的主機名請求
}
open: true, // 自動打開瀏覽器
port: 3000, // 設置啟動時候的運行端口
contentBase: './dist', // 指定托管的根目錄
hot: true // 啟用熱更新
// hotOnly: true // 代碼報錯會顯示錯誤信息不回進行熱更新,hot 遇到報錯會進行上一次的更新導致沒有錯誤信息
}
~~~
其他字段
**`compress`是否為靜態文件開啟gzip compression默認值是false,可以設置為true**

**`port`設置監聽的端口,默認情況下是8080**
**`open`是否打開瀏覽器**
>[danger] ##### 熱更新
1. 名詞解釋瀏覽器的熱更新,指的是我們在本地開發的同時打開瀏覽器進行預覽,當代碼文件發生變化時,瀏覽器自動更新頁面內容的技術。這里的自動更新,表現上又分為**自動刷新整個頁面**,以及**頁面整體無刷新而只更新頁面的部分內容**
>[danger] ##### 模塊熱更新 -- 開啟HMR
1. **HMR**的全稱是`Hot Module Replacement`,翻譯為模塊熱替換,熱更新最好的方式就是這種模塊熱更新,因為可以做到應用程序運行過程中,**替換、添加、刪除模塊**,而**無需重新刷新整個頁面**
2. 默認情況下,`webpack-dev-server`已經支持HMR,我們只需要開啟即可(默認已經開啟),在不開啟HMR的情況下,當我們修改了源代碼之后,整個頁面會自動刷新,使用的是live reloading 產生問題 **一旦頁面整體刷新,頁面中任何之前的操作狀態都會丟失**,**可以解決**應用運行過程中實時替換某個模塊,應用運行狀態不受影響,解決自動刷新導致頁面狀態丟失等。熱替換只將修改的模塊實時替換至應用中
~~~
devServer: {
hot: true,
},
~~~
3. **是否開啟了熱更新意味著所有模塊都可以享受熱更新?**
* **當對css 進行更改的時候發現開啟熱更新不在是整個頁面進行刷新**,似乎滿足了我們期望的**只對更改的局部**
* **js替換時 出現頁面刷新**
原因,因為 樣式文件經過`Loader`處理,自動處理了樣式文件的**模塊熱更新**,CSS文件僅需要替換文件就可以覆蓋樣式;而**JS無規律**,導出類型以及引用雜亂,因此沒有通用的模塊替換方案
4. **Vue/React**等腳手架項目JS照樣可以**模塊熱更新**,使用框架下的開發,每種文件都是有規律的,且腳手架創建的項目內部都集成了**HMR**方案。例如們使用`vue-loader`,此loader支持vue組件的HMR,提供開箱即用的體驗,`React Hot Loader`,實時調整react組件(目前React官方已經棄用了,改成使用**react-refresh**)
* `style-loader` 舉例子
~~~
//為了清晰期間,我們將模塊名稱注釋以及與熱更新無關的邏輯省略,并將 css 內容模塊路徑賦值為變量
//cssContentPath 以便多處引用,實際代碼可從示例運行時中查看
var cssContentPath = "./node_modules/css-loader/dist/cjs.js!./src/style.css"
var api = __webpack_require__("./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");
var content = __webpack_require__(cssContentPath);
...
var update = api(content, options);
...
module.hot.accept(
cssContentPath,
function(){
content = __webpack_require__(cssContentPath);
...
update(content);
}
)
module.hot.dispose(function() {
update();
});
// update(content) 是將新的樣式內容更新到原 style 標簽中,而 update() 則是移除注入的 style 標簽,
//'module.hot' 是由'模塊熱替換插件(HotModuleReplacementPlugin)' 提供的'API'
~~~
>[danger] ##### 自己開發js 模塊進行模塊熱更新
1. JS 代碼中的熱替換利用`模塊熱替換插件(HotModuleReplacementPlugin)`提供的API
~~~
// ./text.js
export const text = 'Hello World'
// ./index2.js
import {text} from './text.js'
const div = document.createElement('div')
document.body.appendChild(div)
function render() {
div.innerHTML = text;
}
render()
if (module.hot) {
module.hot.accept('./text.js', function() {
render()
})
}
~~~
>[danger] ##### 問答
~~~
1. 熱更新會產生新的文件么?
答:不輸出文件,而是放在內存中。不輸出出文件指的是那些入口打包后的那些'js' 文件
2.HotModuleReplacementPlugin 這個熱更新插件:
這里面的熱更新有最核心的是 'HMR' Server 和 'HMR' runtime。'HMR Server' 是服務端,用來將變化的 js 模塊
通過 websocket 的消息通知給瀏覽器端。'HMR Runtime'是瀏覽器端,用于接受 'HMR Server' 傳遞的模塊數據,
瀏覽器端可以看到 .hot-update.json 的文件過來。(HMR 是HotModuleReplacementPlugin 縮寫)
3.HotModuleReplacementPlugin是做什么用的?
答:webpack 構建出來的 bundle.js 本身是不具備熱更新的能力的,HotModuleReplacementPlugin 的作用就是將 HMR runtime
注入到 bundle.js,使得bundle.js可以和HMR server建立websocket的通信連接
4.webpack-dev-server和hot-module-replacement-plugin之間的關系?
答:'webpack-dev-server(WDS)'的功能提供 bundle server的能力,就是生成的 bundle.js 文件可以通過 localhost://xxx 的方式去訪
問,另外 WDS 也提供 livereload(瀏覽器的自動刷新)。
'hot-module-replacement-plugin' 的作用是提供 HMR 的 runtime,并且將 runtime 注入到 bundle.js 代碼里面去。
一旦磁盤里面的文件修改,那么 HMR server 會將有修改的 js module 信息發送給 HMR runtime,然后 HMR runtime
去局部更新頁面的代碼。因此這種方式可以不用刷新瀏覽器。
簡單理解:hot-module-replacement-plugin 包給 webpack-dev-server 提供了熱更新的能力。
5.熱更新分析原理如圖,來自極客時間
最開始運行時候 走的是1-》2-》A -》B
更改內容時候熱更新 1-》2-》3-》4
~~~

- 工程化 -- Node
- vscode -- 插件
- vscode -- 代碼片段
- 前端學會調試
- 谷歌瀏覽器調試技巧
- 權限驗證
- 包管理工具 -- npm
- 常見的 npm ci 指令
- npm -- npm install安裝包
- npm -- package.json
- npm -- 查看包版本信息
- npm - package-lock.json
- npm -- node_modules 層級
- npm -- 依賴包規則
- npm -- install 安裝流程
- npx
- npm -- 發布自己的包
- 包管理工具 -- pnpm
- 模擬數據 -- Mock
- 頁面渲染
- 渲染分析
- core.js && babel
- core.js -- 到底是什么
- 編譯器那些術語
- 詞法解析 -- tokenize
- 語法解析 -- ast
- 遍歷節點 -- traverser
- 轉換階段、生成階段略
- babel
- babel -- 初步上手之了解
- babel -- 初步上手之各種配置(preset-env)
- babel -- 初步上手之各種配置@babel/helpers
- babel -- 初步上手之各種配置@babel/runtime
- babel -- 初步上手之各種配置@babel/plugin-transform-runtime
- babel -- 初步上手之各種配置(babel-polyfills )(未來)
- babel -- 初步上手之各種配置 polyfill-service
- babel -- 初步上手之各種配置(@babel/polyfill )(過去式)
- babel -- 總結
- 各種工具
- 前端 -- 工程化
- 了解 -- Yeoman
- 使用 -- Yeoman
- 了解 -- Plop
- node cli -- 開發自己的腳手架工具
- 自動化構建工具
- Gulp
- 模塊化打包工具為什么出現
- 模塊化打包工具(新) -- webpack
- 簡單使用 -- webpack
- 了解配置 -- webpack.config.js
- webpack -- loader 淺解
- loader -- 配置css模塊解析
- loader -- 圖片和字體(4.x)
- loader -- 圖片和字體(5.x)
- loader -- 圖片優化loader
- loader -- 配置解析js/ts
- webpack -- plugins 淺解
- eslit
- plugins -- CleanWebpackPlugin(4.x)
- plugins -- CleanWebpackPlugin(5.x)
- plugin -- HtmlWebpackPlugin
- plugin -- DefinePlugin 注入全局成員
- webapck -- 模塊解析配置
- webpack -- 文件指紋了解
- webpack -- 開發環境運行構建
- webpack -- 項目環境劃分
- 模塊化打包工具 -- webpack
- webpack -- 打包文件是個啥
- webpack -- 基礎配置項用法
- webpack4.x系列學習
- webpack -- 常見loader加載器
- webpack -- 移動端px轉rem處理
- 開發一個自己loader
- webpack -- plugin插件
- webpack -- 文件指紋
- webpack -- 壓縮css和html構建
- webpack -- 清里構建包
- webpack -- 復制靜態文件
- webpack -- 自定義插件
- wepack -- 關于靜態資源內聯
- webpack -- source map 對照包
- webpack -- 環境劃分構建
- webpack -- 項目構建控制臺輸出
- webpack -- 項目分析
- webpack -- 編譯提速優護體積
- 提速 -- 編譯階段
- webpack -- 項目優化
- webpack -- DefinePlugin 注入全局成員
- webpack -- 代碼分割
- webpack -- 頁面資源提取
- webpack -- import按需引入
- webpack -- 搖樹
- webpack -- 多頁面打包
- webpack -- eslint
- webpack -- srr打包后續看
- webpack -- 構建一個自己的配置后續看
- webpack -- 打包組件和基礎庫
- webpack -- 源碼
- webpack -- 啟動都做了什么
- webpack -- cli做了什么
- webpack - 5
- 模塊化打包工具 -- Rollup
- 工程化搭建代碼規范
- 規范化標準--Eslint
- eslint -- 擴展配置
- eslint -- 指令
- eslint -- vscode
- eslint -- 原理
- Prettier -- 格式化代碼工具
- EditorConfig -- 編輯器編碼風格
- 檢查提交代碼是否符合檢查配置
- 整體流程總結
- 微前端
- single-spa
- 簡單上手 -- single-spa
- 快速理解systemjs
- single-sap 不使用systemjs
- monorepo -- 工程
- Vue -- 響應式了解
- Vue2.x -- 源碼分析
- 發布訂閱和觀察者模式
- 簡單 -- 了解響應式模型(一)
- 簡單 -- 了解響應式模型(二)
- 簡單 --了解虛擬DOM(一)
- 簡單 --了解虛擬DOM(二)
- 簡單 --了解diff算法
- 簡單 --了解nextick
- Snabbdom -- 理解虛擬dom和diff算法
- Snabbdom -- h函數
- Snabbdom - Vnode 函數
- Snabbdom -- init 函數
- Snabbdom -- patch 函數
- 手寫 -- 虛擬dom渲染
- Vue -- minVue
- vue3.x -- 源碼分析
- 分析 -- reactivity
- 好文
- grpc -- 瀏覽器使用gRPC
- grcp-web -- 案例
- 待續