最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • [太闲了]自己实现一个网页热加载服务

    正文概述 掘金(ShyWay)   2021-01-26   639

    寒假赋闲在家,没啥业余爱好,闲暇之余喜欢学学好看的css效果,然每次更改完样式都需要刷新浏览器,于是去寻热加载工具,未果,自己写了一个?

    当然,您也可以用react提供的cra等类似工具实现此需求,但是我因为就想用简单一点的方式编辑css效果,所以不喜勿喷哈

    下文的网页热加载均指此需求

    思路

    网页热加载大概分为一下步骤

    1. 开启一个端口实现http服务

    2. server监听文件夹

    3. 文件夹有变动的时候通过SSE发送给client

    4. client刷新重新获取页面

    所以我们要用到的工具有

    • Node包:httpfs
    • WebAPIs:localtion.reload()EventSource

    开始

    提供http服务

    首先,我们开启一个端口来提供http服务

    const http = require('http');
    
    const server = http.createServer((req, res) => {
    });
    
    server.listen(8080, () => {
        console.log(`server running on http://localhost:8080/?...`)
    });
    

    node运行一下,这个时候服务已经开启啦http://localhost:8080/

    接下来要提供静态资源的访问服务,这样我们才能看到我们的网页呀

    这里我们使用fs.readFile读取文件并响应http请求

    注意⚠⚠更换自己的静态资源文件夹路径

    const fs = require('fs');
    //别忘了改成自己监听的文件夹
    fs.readFile("/Users/shwei/code/livereload/public" + url, (err, data) => {
      if (err) {
        res.writeHead(404);
        res.end("File Not Found");
        return;
      }
      res.writeHead(200);
      res.end(data);
    });
    

    加到我们的http服务中就是这样

    这里我们默认访问根目录返回index.html,用一个函数封装一下给其他静态资源复用

    const http = require("http");
    const fs = require("fs");
    const getStaticResource = (url, res) => {
      fs.readFile("/Users/shwei/code/livereload/public" + url, (err, data) => {
        if (err) {
          res.writeHead(404);
          res.end("File Not Found");
          return;
        }
        res.writeHead(200);
        res.end(data);
      });
    };
    const server = http.createServer((req, res) => {
      const { headers, url, method } = req;
      if (url.toLowerCase() === "/" && method.toLowerCase() === "get") {
        getStaticResource("/index.html", res);
        return;
      }
      if (method.toLowerCase() === "get") getStaticResource(url, res);
    });
    
    server.listen(8080, () => {
      console.log(`server running on http://localhost:8080/?...`);
    });
    

    这样的话,我们在相应的文件夹下建立index.html就能在http://localhost:8080/

    看到我们的网页啦

    使用SSE和文件监控实现热加载

    接下来就是实现热加载啦

    首先我们的网页中一定要默认链接一个JS文件,里面放入我们SSE需要的浏览器端API

    //sse.js
    const events = new EventSource("/events"); //监听我们http服务中的/events路由
    events.onmessage = (event) => {
      location.reload();
    };
    

    设定好监听的路由,只需要设置收到信息的时候刷新页面就好啦

    不要忘记链接到HTML中

    <script src="sse.js"></script>
    

    接下来实现我们server端的服务

    首先是文件监听APIfs.watch,我们要配合这个来给浏览器端发送消息

    老样子,写一个函数包装一下,并且应该是立即执行的(因为我们想打开端口就用,如果有业务逻辑则不要学我)

    (function watchFile() {
      fs.watch("./public", { encoding: "buffer" }, () => {
        client.writeHead(200, {
        "Content-Type": "text/event-stream",
        "Connection": "keep-alive",
        "Cache-Control": "no-cache"
      });//headers标准
        client.end("data: reflush\n\n");//别忘了data:和\n\n
      });
    })();
    

    你可能发现,我这里多了一个client变量,不过别急我待会解释,要注意SSE的通信标准(代码中注释)

    由于SSE的本质是不断向server端发送GET请求保持连接一直未中断

    而我们只需要文件更改的时候发送信息给浏览器端,所以我这样安排了响应

    if (url.toLowerCase() === "/events" && method.toLowerCase() === "get") {
        client = res;
        return;
      }
    

    每次响应我们只需要保存“指针”,以便于文件更改的时候能找到

    其实这里全局变量有些不优雅,但是别计较太多

    到这里我们的功能已经实现完全啦

    全代码

    const http = require("http");
    const fs = require("fs");
    let client;
    
    const server = http.createServer((req, res) => {
      const { headers, url, method } = req;
      if (url.toLowerCase() === "/" && method.toLowerCase() === "get") {
        getStaticResource("/index.html", res);
        return;
      }
      if (url.toLowerCase() === "/events" && method.toLowerCase() === "get") {
        client = res;
        return;
      }
      if (method.toLowerCase() === "get") getStaticResource(url, res);
    });
    
    server.listen(8080, () => {
      console.log(`server running on http://localhost:8080/?...`);
    });
    
    (function watchFile() {
      fs.watch("./public", { encoding: "buffer" }, () => {
        client.writeHead(200, {
        "Content-Type": "text/event-stream",
        "Connection": "keep-alive",
        "Cache-Control": "no-cache"
      });//headers标准
        client.end("data: reflush\n\n");//别忘了data和/n/n
      });
    })();
    
    const getStaticResource = (url, res) => {
      fs.readFile("/Users/shwei/code/livereload/public" + url, (err, data) => {
        if (err) {
          res.writeHead(404);
          res.end("File Not Found");
          return;
        }
        res.writeHead(200);
        res.end(data);
      });
    };
    

    打开你的代码编辑器和http://localhost:8080/

    尽情享受吧!


    起源地下载网 » [太闲了]自己实现一个网页热加载服务

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元