情景重现

前几天接了个私活,主要是修改一些前端页面样式和优化 html 结构等。

其中 css/js 引入方式为 umd(Universal Module Definition) ,也就是直接用script/link引入。而不是requirejs/seajs/webpack 对应的 amd/cmd/commonjs 加载 javascript 或样式。

在不断地 修改样式 -> 刷新页面的循环中,时间浪费了许多!

于是萌生出:“造一个热更新服务的轮子”。

注意:该工具只支持热更新 umd 引入的依赖

原理

如图,首先需要建立一个 http(s) 服务,通过该服务获取前端静态资源,对于 HTML 文件的请求,服务器需要额外插入一段客户端脚本。脚本的工作主要是用来建立 websocket 长连接。同时需要开启文件监听,异步监听到文件的变化,并广播 reload 消息至依赖该文件的客户端,客户端收到该消息后,便 location.reload() 自动刷新页面

特性

  • 热更新

  • 远程调试(适合局域网中移动端调试)

  • 文件视图
    访问:http://localhost:8082/__hrs__/file

  • 依赖关系查看

    1. 单个文件
      访问:http://localhost:8082/index.html.hrs.map

      {
          "/Users/moyu/my-code/JavaCode/dike/js/jquery-1.9.1.js": "../../js/jquery-1.9.1.js",
          "/Users/moyu/my-code/JavaCode/dike/js/bootstrap.js": "../../js/bootstrap.js",
          "/Users/moyu/my-code/JavaCode/dike/js/navbar.js": "../../js/navbar.js",
          "/Users/moyu/my-code/JavaCode/dike/css/font-awesome.min.css": "../../css/font-awesome.min.css",
          "/Users/moyu/my-code/JavaCode/dike/css/navbar.css": "../../css/navbar.css",
          "/Users/moyu/my-code/JavaCode/dike/css/conceptModel.css": "../../css/conceptModel.css",
          "/Users/moyu/my-code/JavaCode/dike/css/dropzone/dropzone.css": "../../css/dropzone/dropzone.css"
      }
    2. 全局
      访问:http://localhost:8082/__hrs__/map
  • 转发请求(可避免跨域)
    访问:http://localhost:8082/__hrs__/forward?url=http://blog.moyuyc.xyz/head.jpg

  • 配置文件
    默认认为配置文件为:hrs.config.js
    比如:

module.exports = {
    proxy: {
        "/api": {
            target: "http://www.huya.com/longdd",
        },
        "/php": {
            redirect: true, // default: true
            target: "http://localhost:63343/start/static",//"http://localhost:6999",
            changeHost: true,  // default: true

            hot: true, // hot reload enable? default: false
            // Function/RegExp: will be set root config hotRule if it is null
            hotRule: function (filename, request) {
                // console.log(request.url);
                return /\.(php)$/.test(filename);
            },
            // Function: return local file path
            mapLocal: function (request) {
                // request: Express Request Object
                // console.log('mapLocal', request.originalUrl, request.baseUrl, request.url);
                const url = request.url.replace(/\?[\s\S]*/, '')
                return "/Users/moyu/my-code/phpCode/start/static" + url;
            },
            // Function/String: return detected directory path
            mapRoot: function (request) {
                // request: Express Request Object
                return "/Users/moyu/my-code/phpCode/start/static";
            }
        },
    },

    // RegExp or function (filename) {...}
    hotRule: /\.(html|htm)$/, // default: /\.(html|htm)$/

    setUp: function (app) {
        /* app is an express server object. */

        // http://localhost:8082/test
        app.get('/test', function (req, res) {
            res.end("TEST!");
        });
    }
};
  • 支持跨域
    建立起 hot reload server (端口 8082) 服务后,在你需要开启热更新的 html 中手动插入
<script
    src="http://localhost:8082/__hrs__/client-script.js?reload=false&debug=true"
    hrs-local="/Users/moyu/fe-code/a/b/jsonp.html"
    hrs-root="/Users/moyu/fe-code"
></script>
- `hrs-local` 该文件的绝对路径
- `hrs-root` 需要监听的文件夹的路径(默认为`hrs-local`的文件夹路径,例中为:`/Users/moyu/fe-code/a/b`)

安装使用

使用 nodejs 实现,需要 node 环境。

npm install -g simple-hot-reload-server
Usage: hrs [-p port] path

Options:

  -v --version                get current version.
  -p --port                   set port of server. (default: 8082)
  -c --config                 config path. (default hrs.config.js)
  -h --help                   how to use it.

最后,欢迎各位 star