Tips For Front-End —— LiveReload

ps:下文我将打算用fe代替Front-End一词。

时间过得真快,眨眼一周又过去了。今天我们来侃侃liveReload。聊之前先来扯扯开发家常。
通常来说,Web页面开发的流程大致是这样的:设计师提供设计稿,通常是psd格式。然后fe开发人员来手工的将图片转换为对应的HTML+CSS,常常还需要在各个浏览器中调试等。
一般,设计师还会提供色卡,或至少前景色、背景色、高亮色的值给开发人员。如果没有的话,开发人员会用到一些工具如colorpicker,ruler之类来确保最终的效果和设计稿是一致的。如果你观察过此开发的工作流程的话,你会发现基本的上是这样的:编写HTML,CSS,保存修改内容,切换到浏览器窗口,按F5或者Ctrl-R刷新,然后对比设计稿和实现,如果发现不一致的地方,再切换到编辑器修改代码,反复操作。开发时间长了,效率必定受到影响。

LiveReload

liveReload应该是fe比较关心技术了,有了这个liveReload技术,将大大提高fe效率。别急,我知道还没说liveReload是什么! T_T
何谓liveReload,其实说白了就是监听资源文件变动让浏览器实时自动刷新,理想状态下reload应该是replace —— 实时替换,用资源局部变化方案代替全部重载。也是热门的hot load技术,比如下文提到的webpack就提供了一套成熟hot load的解决方案。

Workflow

有了LiveReload技术后,建立高效的开发流程简直轻而易举:当你修改保存某个文件,浏览器都会自动刷新或替换变化。这样的快速反馈可以告诉我们下一步如何修改:将背景色调整的再淡一点,还是把会h2的字体变得更大,或者图片和文字的上边缘没有对齐 etc.
实时反馈,点滴前进。如果你有双显示器效果就更佳了😄,一台显示PSD设计稿,一台显示编辑器和浏览器,这样调试无非是每个前端的天堂模式。
ps:为了加强理解提供效果图,btw效果图来自互联网!
[workflow]
[two-displays]

实现方案

下面,我将给大家介绍我熟悉的三种方案。

LiveReload插件 + Guard

上文提到的频繁的F5刷新,可以通过LiveReload插件 + Guard两个工具的组合来解决。LiveReload插件是一个浏览器的插件,通过协议与后台的服务器进行通信。当后台文件发生变化时, LiveReload插件会自动刷新页面。Guard会使用操作系统的API来感知本地文件的变化,当文件变化后,它可以通知LiveReload进行刷新,当然Guard可以做其他一些事情,比如监听less文件,当发生变化时,自动编译css等。
由于此方案不是最佳方案,就不再赘述,有兴趣的童鞋可以自行google,查阅相关资料。缺点:这种方式需要先给浏览器安装LiveReload插件

Browsersync + gulp

假如你恰好使用的是gulp作为fe工作流开发,假如你恰好为开发效率烦恼着。哈哈,不用担心,我觉得这套liveReload技术就是为你装备的。这里假设的前提是大家熟悉gulp基本使用。
首先确立一个大致思路:

  • gulp监听静态资源,根据自己的业务情况实现监听,当有文件变化即调用Browsersync提供的API;

    ...
                    
    module.exports = gulp = require 'gulp'
    browserSync = require 'browser-sync'
    # 声明任务
    gulp.task 'hot', ->
    # 初始化browserSync工具
    browserSync.init
    ui: # browserSync管理界面 http://localhost:8082
    port: 8082
    weinre: port: 9092
    proxy: # 转发server
    # middleware: (req, res, next) ->
    target: "localhost:3100"
    startPath: '/index.html?token=jytpsm1433227719&site_id=10001' # 弹出首页
    ghostMode: false # 关闭自动模拟事件,这是一个坑
    console.log "开始监听资源文件..."
    gulp.watch 'less/**/*.less', ->
    console.log "less文件重新加载..."
    browserSync.reload()
    gulp.watch 'js/**/*.{js,html,mustache}', ->
    console.log "组件文件重新加载..."
    browserSync.reload()
    gulp.watch 'static/runtime/**/*.{js}', ->
    console.log "runtime文件重新加载..."
    browserSync.reload()
    ...
  • Browsersync负责调用API刷新浏览器或者替换变化,访问管理界面,还能进一步调试页面、多设备同步效果:

    ...
    # 重新加载资源
    browserSync.reload()
    ...

更多文档:http://www.browsersync.cn/docs

  • 开发模式下,主进程开启liveReload功能,只需要调用gulp提供的api即可:
    ...
    if process.env.NODE_ENV != 'production'
    gulp = require './gulpfile'
    gulp.start 'hot'
    ...

ps:此方案还能进一步优化,比如浏览器不必实时刷新,仅改变页面元素变化即可,当然Browsersync插件-bs-html-injector已经实现了我们想要的,不必重复造轮子了。

Webpack-Hot技术

后续…

技术原理

再来说说上文介绍的三种方案背后的原理,首先要明确这些技术的目标是什么,简单地说就是后端监听到资源被修改立刻通知浏览器。带着问题去试探技术背后的原理会比较容易理解。

browserSync

1、browserSync 工作模式:
browserSync本身就内置一个静态文件服务器,此服务器不仅可以脱离业务逻辑直接管理静态资源,并且可以不处理业务逻辑代理到下游服务,前者是手动模式,后者是代理模式。代理模式是方便了对接已有业务的情况。
2、browserSync 初始化:
browserSync一旦配置成功便会初始化一个server实例,以便browserSync服务与浏览器通信,通信协议用的是websocket协议实现长连接通信。
3、proxy模式:
选择代理模式,browserSync将完全接管后端入口,初始化完毕后会启动指定网页入口,页面渲染时将在 里注入一段script脚本,即ws协议的client,用来与后端server通信。
[proxy模式-1]
[proxy模式-2]
4、手动模式:
选择手动模式,browserSync将会提示你手动插入script脚本,方便建立ws长连接。
[Manual模式]
5、browserSync 实现通信方式:
由图可以看到当html页面渲染时,browserSync注入script会将和后端服务建立websocket长连接服务。
[websocket]
6、browserSync UI管理:
UI管理界面很好地给开发人员提供管理界面,其原理就是调用browserSync提供的api,然后通过ws协议让浏览器实时响应。 e.g. 比如向页面注入weinre服务 etc.
[ui-1]
[ui-2]
7、FAQ
这里说的是别人踩过的坑,记录的目的是省得再走弯路。
[bug-1]
[bug-2]
[bug-3]

webpack

后续…

总结

一个优秀技术人员应勤于思考,善于总结。绝不限定自己的思维和能力,通过不断总结完善自我知识体系;不断吸收先进技术培养出大局观是成为技术大牛必经之路!