webpack之文件監(jiān)聽及熱更新

webpack 的文件監(jiān)聽

文件監(jiān)聽是在源碼發(fā)生變化時,自動重新構(gòu)建出新的輸出文件。
webpack開啟監(jiān)聽模式,有兩種方式:

  • 啟動 webpack 命令時,帶上 --watch 參數(shù)。
    {
      "name": "project",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "build": "webpack",
        "watch": "webpack --watch"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
    }
    
  • 在配置 webpack.config.js 中設(shè)置 watch: true
    但是,這種方式需要每次手動刷新瀏覽器

webpack文件監(jiān)聽的原理

webpack會輪詢判斷文件的最后編輯時間是否變化。
某個文件發(fā)生了變化,并不會立即告訴監(jiān)聽者,而是先緩存起來,等 aggregateTimeout

module.exports = {
    // 默認(rèn)是false,即不開啟
    watch: true,
    // 只有開啟監(jiān)聽模式時,watchOptions才有意義
    watchOptions: {
        // 默認(rèn)為空,不監(jiān)聽的文件或者文件夾,支持正則匹配
        ignored: /node_modules/,
        // 監(jiān)聽到變化發(fā)生后會等300ms再去執(zhí)行,默認(rèn)300ms
        aggregateTimeout: 300,
        // 判斷文件是否發(fā)生變化是通過不停詢問系統(tǒng)指定文件有沒有變化實現(xiàn)的,默認(rèn)每秒問1000次
        poll: 1000
    },
};

熱更新

使用webpack-dev-server

安裝依賴

npm i -D webpack-dev-server
  • WDS 不刷新瀏覽器
  • WDS 不輸出文件,而是放在內(nèi)存中
  • 使用 Hot ModuleReplacementPlugin插件
{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --open"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
}

因為WDS主要是在開發(fā)過程中使用,生產(chǎn)環(huán)境是用不到的,所以我們將mode改為development,然后再引入webpack自帶的Hot ModuleReplacementPlugin插件,由于該插件是內(nèi)置的,所以我們先引入webpack,再將插件加進來,最后還要配置一下devServer。

const webpack = require('webpack');

module.exports = {
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        contentBase: './dist', // 服務(wù)的基礎(chǔ)目錄
        hot: true   // 開啟熱更新
    }
};

升級填坑

但是,當(dāng)你升級webpack4 ---->webpack5時,如果你的版本是webpack-cli 4*時,就會報錯

Error: Cannot find module 'webpack-cli/bin/config-yargs'

{
  "webpack": "^5.36.0",
  "webpack-cli": "^4.6.0",
  "webpack-dev-server": "^3.11.2"
}

這是,因為在webpack-cli 4*中,作者刪除了config-yargs,所以會報錯
這里有兩種解決方案:

  • 臨時解決方案:將webpack-cli版本降級到webpack-cli 3*
  • 終極解決方案:修改配置文件,使用webpack serve替代webpack-dev-server也就是將配置項的 "dev": "webpack-dev-server --open"改為"dev": "webpack serve --open"

使用webpack-dev-middleware

WDM將webpack輸出的文件傳輸給服務(wù)器,適用于靈活的定制場景。
使用這種方式,通常需要再引入一個server,一般是express或者koa

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath
}));

app.listen(3000, function(){
  console.log('Example app listening on port 3000!\n');
})

熱更新原理分析

  • Webpack Compile(webpack的編譯器):將JS的源代碼編譯成Bundle
  • HMR Server:將熱更新的文件輸出給 HMR Runtime
  • Bundle server:提供文件在瀏覽器的訪問,可以讓你的文件以服務(wù)器的方式訪問,比如“http://localhost:8080/search.html
  • HMR Runtime:會被注入到瀏覽器端的bundle.js里面,bundle.js就可以與服務(wù)器建立一個連接,通常這個連接是一個websocket,當(dāng)它收到一些數(shù)據(jù),一些回包之后,就會自動更新文件
  • bundle.js:構(gòu)建輸出的文件

熱更新的過程

  • 啟動階段,是在文件系統(tǒng)里面,文件系統(tǒng)的一個編譯,就是將初始的代碼經(jīng)過Webpack Compile進行一個打包,打包好以后,將打包好的文件傳輸給bundle server,也就是一個服務(wù)器,bundle server就可以讓這個文件以server的方式讓瀏覽器訪問到
  • 更新階段,如果本地開發(fā)時,有文件發(fā)生了變化,這時的流程是一個文件系統(tǒng)的變化,然后代碼還是會經(jīng)過Webpack Compile進行編譯,編譯好以后會將代碼發(fā)送給HMR Server,HMR Server就可以知道哪些模塊(源代碼部分的模塊)發(fā)生了變化,然后HMR Server就會通知HMR runtimeHMR Server是在服務(wù)端,HMR runtime是在客戶端)。通常是以json的格式進行數(shù)據(jù)傳輸,傳遞給HMR runtime之后,HMR runtime就會更新我們的代碼,最后我們的代碼進行了改變,并且不需要刷新瀏覽器。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容