国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

簡(jiǎn)單聊聊前端開(kāi)發(fā)中的熱更新原理

MingjunYang / 2006人閱讀

摘要:背景前端項(xiàng)目開(kāi)發(fā)過(guò)程中熱更新的機(jī)制大家都知道,不知道你在開(kāi)發(fā)的時(shí)候是否做了這方面的配置。其實(shí)熱更新的原理并不復(fù)雜,或者說(shuō)很簡(jiǎn)單。服務(wù)器和瀏覽器規(guī)定好消息的規(guī)則,是刷新頁(yè)面還是更新。另外對(duì)模塊熱更新和原理有興趣的可以研究下,后面可能也會(huì)介紹。

背景

前端項(xiàng)目開(kāi)發(fā)過(guò)程中熱更新的機(jī)制大家都知道,不知道你在開(kāi)發(fā)的時(shí)候是否做了這方面的配置。

相信接觸最多的就是 webpack 的熱更新,文件保存后頁(yè)面自動(dòng)刷新,或者 css 自動(dòng)更新,頁(yè)面的樣式在不刷新頁(yè)面的情況下就會(huì)更新。

還有就是模塊熱替換。

熱更新機(jī)制很好玩,能提升不少開(kāi)發(fā)效率,但是只是處于會(huì)用的階段不是我們的目的,我們應(yīng)該適當(dāng)?shù)纳钊雽W(xué)習(xí)下,看看他背后的原理,一個(gè)是否思考過(guò),一個(gè)是否能自己實(shí)現(xiàn)。

熱更新原理

咱們這里主要說(shuō)下怎樣自己實(shí)現(xiàn)一個(gè)熱更新,也就是文件更改了會(huì)自動(dòng)刷新頁(yè)面,可以同步 pc 和 移動(dòng)端,css 更改了可以不刷新頁(yè)面就應(yīng)用最新的 css。

其實(shí)熱更新的原理并不復(fù)雜,或者說(shuō)很簡(jiǎn)單。

咱們一步一步的分析下。

本文不是要告訴你一些 api如何使用,而是利用架構(gòu)的思維去分析和解決問(wèn)題。

【分析】

文件內(nèi)容變更了,瀏覽器是怎么知道的呢?

css 文件內(nèi)容變更了,沒(méi)有刷新頁(yè)面 怎么加載最新的內(nèi)容呢?

只要解決了上面兩個(gè)問(wèn)題,我們就算是完成了。因?yàn)槭O碌镁褪蔷幋a了,這都好說(shuō)。

【結(jié)果】

文件變更了,我怎樣通知瀏覽器?

瀏覽器和服務(wù)器保持著連接。 服務(wù)器有什么事兒直接通過(guò)當(dāng)前的鏈接告訴瀏覽器就可以了。

連接肯定是長(zhǎng)連接,不然怎么實(shí)時(shí)通信。

保持長(zhǎng)連接有哪些方法呢? 輪詢(xún)?eventSorce? 都不夠好。

有么有更好的方案呢?那就是 - websocket

瀏覽器和服務(wù)器先建立好鏈接,服務(wù)器就可以直接通知到客戶(hù)端了。這個(gè)時(shí)候無(wú)論是 pc 上還是手機(jī)上都可以隨時(shí)根據(jù)需要刷新或者加載資源。

css 更新,css 本身是可以通過(guò) dom 去操作的。瀏覽器只要知道是 css更新了,直接重新加載當(dāng)前的 css 文件就可以了。

架構(gòu)思維

咱們?cè)谥匦罗坜圻@個(gè)架構(gòu)。

服務(wù)器和瀏覽器通過(guò) websocket 建立鏈接。

服務(wù)器和瀏覽器規(guī)定好消息的規(guī)則,是刷新頁(yè)面還是更新 css。

基本架構(gòu)有了,其他的就是編碼實(shí)現(xiàn)了。

服務(wù)端使用 node 創(chuàng)建一個(gè) ws 服務(wù)。

瀏覽器使用 websocket 創(chuàng)建一個(gè)鏈接和服務(wù)器進(jìn)行鏈接。

雙方通過(guò)對(duì)應(yīng)的 api 進(jìn)行數(shù)據(jù)的操作。

代碼實(shí)現(xiàn)

本文只是講解下思路,并沒(méi)有實(shí)現(xiàn)文件的監(jiān)聽(tīng),文件監(jiān)聽(tīng)后面會(huì)介紹。咱暫時(shí)先確定好兩個(gè)消息規(guī)則:

瀏覽器收到 命令為:htmlFileChange ,此時(shí)瀏覽器刷新;

瀏覽器收到命令為:cssFileChange,此時(shí)不刷新頁(yè)面,自動(dòng)加載 css 文件;

具體代碼如下:

服務(wù)端:
//web-socket.js 創(chuàng)建 ws 服務(wù)
var ws = require("nodejs-websocket");//需要安裝這個(gè)包

module.exports = function(){
    return function () {
        console.log("重度前端提醒,開(kāi)始建立連接...")

        var sessions = [];//存放每一個(gè)鏈接對(duì)象
        var server = ws.createServer(function (conn) {
            sessions.push(conn);//將新的鏈接對(duì)象存放在數(shù)組中

            conn.on("text", function (str) {
                console.log("收到的信息為:" + str)
                sessions.forEach(item=>{
                    item.sendText(str) //所有客戶(hù)端都發(fā)送消息
                });

            });
            conn.on("close", function (code, reason) {
                console.log("關(guān)閉連接")
            });
            conn.on("error", function (code, reason) {
                console.log("異常關(guān)閉")
            });
        }).listen(6152)
        console.log("WebSocket建立完畢")
    }
}

//server.js http 服務(wù)代碼

let http = require("http");
let fs = require("fs");
let webSocket = require("./node/web-socket");

const BASEROOT = process.cwd();//獲得當(dāng)前的執(zhí)行路徑
//讀取 index.html內(nèi)容
let getPageHtml = function () {
    let data = fs.readFileSync(BASEROOT+"/html/index.html");
   return data.toString();
}
//讀取 index.css內(nèi)容
let getPageCss = function () {
    let data = fs.readFileSync(BASEROOT + "/html/index.css");
    return data.toString();
}

//node 端 開(kāi)啟 ws 服務(wù)
webSocket()();

http.createServer(function (req, res) {//創(chuàng)建 http 服務(wù)

    let body = "",url = req.url;

    req.on("data", function (chunk) {
        body += chunk;
    });

    req.on("end", function () {
        //路由簡(jiǎn)單處理 根據(jù)不同路徑輸出不同內(nèi)容給瀏覽器
        if(url.indexOf("/index.css")>-1){
            res.write(getPageCss());
        }else{
            res.write(getPageHtml());
        }

        res.end();

    });

}).listen(6151);

console.log("重度前端提醒...... server start");
頁(yè)面截圖

客戶(hù)端
//index.html 布局代碼省略

 const nick = ["a", "b", "c", "d", "e", "f", "g", "aa", "cc"];
    let index = 0;
    // Create WebSocket connection.
    const socket = new WebSocket("ws://10.70.69.191:6152");

    // Connection opened
    socket.addEventListener("open", function (event) {
        socket.send(navigator.userAgent);
    });

    // 監(jiān)聽(tīng)服務(wù)器推送的消息
    socket.addEventListener("message", function (event) {
        if (index > nick.length) {
            index = 0;//只是為了每次輸出不同的昵稱(chēng),沒(méi)實(shí)際意義
        }

        var ele = document.createElement("div");
        ele.innerHTML = nick[index] + ":" + event.data;
        if (event.data === "htmlFileChange") {
            //html 文件更新了 刷新當(dāng)前頁(yè)面
            location.reload();
        }
        if (event.data === "cssFileChange") {
            //css 文件更新了 刷新當(dāng)前頁(yè)面
            reloadCss();
        }
        document.getElementById("content").append(ele);
        index += 1;
    });
    //重新加載 css
    function reloadCss() {
        var cssUrl = [],
            links = document.getElementsByTagName("link"),
            len = links.length;
        for (var i = 0; i < len; i++) {
            var url = links[i].href;
            document.getElementsByTagName("head")[0].appendChild(getLinkNode(url)); //創(chuàng)建新的 css 標(biāo)簽
            document.getElementsByTagName("head")[0].removeChild(links[i]); //移除原有 css

        }
        console.log(document.getElementsByTagName("head")[0])

        function getLinkNode(cssUrl) {
            var node = document.createElement("link");
            node.href = cssUrl;
            node.rel = "stylesheet";
            return node;
        }
    }

    document.getElementById("btn1").onclick = function () {
        socket.send(document.getElementById("message").value);
        document.getElementById("message").value = "";
    }

index.css 內(nèi)容

 input {
      outline: none;
  }

  #content {
      height: 400px;
      width: 400px;
      border: solid 1px #ccc;
      color: red;
  }

代碼倒是次要的。解決問(wèn)題的思路才重要。有了解決問(wèn)題的架構(gòu)思維,代碼實(shí)現(xiàn)都好說(shuō)。

寫(xiě)到這里咱們還能順便實(shí)現(xiàn)一個(gè)群聊。

本質(zhì)就是服務(wù)器和瀏覽器怎樣實(shí)時(shí)通信,解決了這個(gè)問(wèn)題,其他的都是小事兒。

這個(gè)技術(shù)實(shí)現(xiàn)還是比較簡(jiǎn)單的。

另外對(duì)模塊熱更新和 websocket 原理有興趣的可以研究下,后面可能也會(huì)介紹。

總結(jié)

本文主要介紹

簡(jiǎn)易版熱更新的原理;

熱更新實(shí)現(xiàn)思路和代碼實(shí)現(xiàn);

架構(gòu)思維:簡(jiǎn)單的帶出架構(gòu)思維的作用;

希望本文對(duì)你有用。

原創(chuàng)不易、請(qǐng)多鼓勵(lì)
自家觀點(diǎn)、歡迎打臉

代碼示例下載

https://github.com/bigerfe/ho...

作者:微信公眾號(hào) - 重度前端 主筆:八門(mén)
歡迎關(guān)注 重度前端-每周5原創(chuàng)全棧干貨+每周三深度技術(shù)文章

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/101478.html

相關(guān)文章

  • Node.js 前后端分離開(kāi)發(fā)新思路

    摘要:從事開(kāi)發(fā)的程序員,對(duì)于前后端分離模式多半不陌生,這也是目前主流的開(kāi)發(fā)模式,具體關(guān)于前后端分離的模式可以參看文章你不得不了解的前后端分離原理,在這里寫(xiě)者不進(jìn)行說(shuō)明。原理圖如下,前后端在一個(gè)進(jìn)程同一個(gè)端口中,通過(guò)熱替換更新的,而不是全量重啟。 從事 Web 開(kāi)發(fā)的程序員,對(duì)于前后端分離模式多半不陌生,這也是目前主流的 Web 開(kāi)發(fā)模式,具體關(guān)于前后端分離的模式可以參看文章《你不得不了解的前...

    Lionad-Morotar 評(píng)論0 收藏0
  • Webpack 熱更新機(jī)制

    摘要:聯(lián)想到我在微信小程序上的開(kāi)發(fā)體驗(yàn),真心覺(jué)得如果有熱更新機(jī)制的話(huà),開(kāi)發(fā)效率要高很多。熱更新示例下面通過(guò)例子來(lái)進(jìn)一步解釋熱更新機(jī)制。 想必作為前端大佬的你,工作中應(yīng)該用過(guò) webpack,并且對(duì)熱更新的特性也有了解。如果沒(méi)有,當(dāng)然也沒(méi)關(guān)系。 下面我要講的,是我對(duì) Webpack 熱更新機(jī)制的一些認(rèn)識(shí)和理解,不足之處,歡迎指正。 首先: 熱更新是啥? 熱更新,是指 Hot Module Re...

    mikasa 評(píng)論0 收藏0
  • 如何在前端項(xiàng)目中實(shí)現(xiàn)熱更新

    摘要:如果你的項(xiàng)目中使用了的話(huà),你會(huì)很幸運(yùn),借助插件可以實(shí)現(xiàn)項(xiàng)目的熱更新。對(duì)模板更新的處理目前項(xiàng)目中使用的是的模板引擎。 showImg(https://segmentfault.com/img/bVrAa7);這個(gè)是組內(nèi)一位同學(xué)在平時(shí)開(kāi)發(fā)中,發(fā)現(xiàn)調(diào)試不便,為團(tuán)隊(duì)開(kāi)發(fā)的熱更新工具。很厲害,文章中的技術(shù)實(shí)現(xiàn)內(nèi)容也是我了解了他的具體實(shí)現(xiàn)思路后,整理出來(lái)的。 工具源碼EHU(esl-hot-upd...

    antz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<