如何在移动端真机通过局域网 IP 体验 livereload

解读

面试官想确认三件事:

  1. 你是否理解 Grunt-contrib-watch + grunt-contrib-connect 这套 livereload 的底层机制(WebSocket 脚本注入)。
  2. 能否把本机 127.0.0.1 的默认服务暴露成 局域网可访问的 IP,并解决移动端“看不见”的问题。
  3. 是否具备 中国常见办公网络(Wi-Fi 隔离、防火墙、代理)下的排查经验,而不是只会背文档。
    答得太浅会被认为“没真机调试过”;答得太深(自己写 WebSocket 服务、拆包分析)又显得过度设计。要把“让手机能刷到页面且一改就刷新”讲完整,同时体现工程化思维。

知识点

  • connect 的 hostname 配置:默认 'localhost' 只监听回环,需显式设为 '0.0.0.0' 或本机局域网 IP。
  • 端口放行:Windows 防火墙、macOS 防火墙、公司 802.1X 访客网络、TP-Link 路由器“AP 隔离”都要关掉或加规则。
  • livereload 的脚本地址:grunt-contrib-inject 会在页面尾部插入 <script src="//127.0.0.1:35729/livereload.js">,移动端访问时必须把 127.0.0.1 换成 本机局域网 IP,否则脚本 404。
  • HTML 注入方式
    – 用 grunt-contrib-copy 把 <!-- livereload --> 占位符替换为带 IP 的脚本;
    – 或在 connect 里启用 middleware inject-lr 动态改写。
  • HTTPS 场景:部分企业 Wi-Fi 会拦截 35729 非加密端口,可在 connect 里加 自定义证书 把 livereload 也走 https,并在手机端手动信任根证书。
  • 缓存与 Service Worker:若项目注册了 SW,需勾选 Safari“忽略缓存”或 Chrome DevTools “Bypass for network”,否则刷新的是离线缓存。
  • 真机调试组合
    – iPhone + Mac 用 “开发”菜单 直接调试;
    – Android + Chrome://inspect 需 USB 线 + adb reverse 把 35729 端口反向代理,防止 Wi-Fi 隔离。
  • 性能注意:livereload 默认监听整个 src/,目录过大会触发 EMFILE 报错,需调高 ulimit -n 或用 grunt-newer 限范围。

答案

  1. 确认本机和手机在同一 局域网段(如 192.168.1.x),关闭路由器“AP 隔离”。
  2. 在 Gruntfile 的 connect 任务里把 hostname 改为 '0.0.0.0',port 设 8080,livereload 端口保持默认 35729:
    connect: {
      server: {
        options: {
          hostname: '0.0.0.0',
          port: 8080,
          base: 'dist',
          livereload: 35729
        }
      }
    }
    
  3. 用 grunt-contrib-copy 或 grunt-string-replace 把页面里的 livereload 脚本地址改成 动态局域网 IP
    scriptSrc = 'http://' + require('ip').address() + ':35729/livereload.js?snipver=1';
    
    这样手机访问 http://192.168.1.8:8080 时,浏览器会正确加载 192.168.1.8:35729/livereload.js
  4. 若公司网络屏蔽 35729,可在 connect 里加 middleware 把 livereload 脚本代理到 8080/livereload.js,省一个端口。
  5. 启动 grunt serve,手机浏览器输入 http://192.168.1.8:8080,首次打开后右上角“允许定位”类弹窗点掉,确保 WebSocket 握手成功;随后 PC 端一改文件,真机 2 秒内无刷新跳转更新,即达标。
  6. 若仍失败,按“三步排查”:
    – ping 192.168.1.8 通不通;
    – 手机抓包看 35729 是否返回 101 Switching Protocols;
    – 关闭电脑防火墙再试,定位后加回规则。

拓展思考

  • 无局域网场景:让 grunt-contrib-connect 启动时同步启动 localtunnel 或 ngrok,把 8080 映射成 https://xxx.cn.ngrok.io,手机用 4G 也能 livereload;注意免费隧道 40 请求/分钟限制,适合临时演示。
  • 多设备并行:grunt-concurrent 开 3 个 connect 实例,分别监听 8080/8081/8082,配合 browser-sync 的“镜像点击”做跨端事件同步,一次操作,iPhone、Android、iPad 三端同步滚动。
  • 微前端下 livereload:若页面通过 qiankun 加载子应用,子应用脚本运行在沙箱,需把 livereload 脚本注入到 主应用模板,否则 WebSocket 连不上;可在主应用 public/index.html 里手动加 <script src="//<%= lrHost %>:35729/livereload.js">,用 webpack-html-plugin 的 templateParameters 把 lrHost 传进去。
  • 安全合规:国内金融客户要求“开发机不能监听 0.0.0.0”,可改用 USB 反向代理(adb reverse tcp:8080 tcp:8080 + adb reverse tcp:35729 tcp:35729),手机走 localhost,既满足 livereload 又过安全扫描。