
前言
这个系列是关于whistle,但是在正式介绍whistle之前,我想先聊点其他的东西。
在认识whistle之前,我的前端开发环境虽然不至于十分完美,但是完成日常开发和调试的各个环节似乎没有什么问题,因此当我第一次听说到whistle这个工具并且粗略地扫了一眼文档以后,并没有迫切地感受到使用它的必要。
直到后来,加入了新的团队,whitsle在新团队的业务开发中几乎已经是基础设施一样必不可少又充当着重要角色的工具。在渐渐使用和熟悉whistle之后,我开始意识到,在面对一些特定场景时,之前的开发方式的确有可能无能为力,或者处理起来不甚麻烦。另外,即使没有遇到复杂的业务场景,在原有的开发方式中添加whistle这一工具,对开发和调试也是大有裨益。
在正式介绍whistle之前,我想先谈一谈我之前使用的开发模式和可能存在的问题。
基于localhost的开发模式
本地开发项目需要解决的两个要点是
- 进行本地代码调试;
- 接口代理至特定后端机器或域名。
webpack在当前前端的项目开发中,已经是开发和构建的首要使用工具,它也很好地提供了本地开发的必要功能和环境。之前在本地进行项目开发时,惯常的做法是在本地用webpack起一个devServer, 通过热更新实时调试本地的代码,而后借由webpack自身的proxy功能,完成接口的代理转发。
为了方便进行说明,我们以一个create-react-app的项目进行一个简单演示。 首先,假设我们有一个以create-react-app新建的,名为my-app的前端项目。
create-react-app my-app
cd my-app
npm run start
会在浏览器中开启一个localhost:3000的页面

而关于接口转发,采用官方推荐的 http-proxy-middleware 库,进行处理。(此处直接选用官方的操作指南作为说明,实际操作可能已经有了变动,但是不影响我们的说明)
// src/setupProxy.js
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
// 将 /api 前缀的接口 转发到 http://qq.ketang.com/
app.use(proxy('/api', { target: 'http://qq.ketang.com/' }));
};
这样一来,就完成了基本的本地代码调试和接口代理。
基于localhost开发的缺陷和不足
这种在本地localhost下的开发方式的确可以满足基本的开发需要,在过去的开发体验中,一直这样使用似乎也没有什么太大问题,但这种开发方式有什么不足呢?
localhost限制了需要特定域名的功能
页面调试时的一部分功能,需要前端页面的特定域名支持,比如用户的登陆功能,后端接口会校验客户端域名的合法性,只处理特定的域名的请求;又比如特定域名下cookie的读取等等。这些功能在localhost的host下可能会受到限制。

业务代码中耦合了环境判断有关的代码
使用localhost进行本地开发,则业务代码中有可能会引入一些额外的逻辑判断,如针对本地域名和线上域名进行区分等
if (location.host === 'localhost') {
// ...
} else {
// ...
}
当然我们可以通过提取出公共方法的方式减少每次需要书写的代码量,但是本地和线上的处理方式不一致,这的确会给业务的维护以及上线之前的自检带来一些额外工作量。
频繁修改接口代理带来了麻烦
在开发中,常会遇到需要切换接口的请求环境来排查问题的情况。
而我们采用的webpack的proxy配置属于启动时初始化的配置,因此每次需要变更请求的转发规则,都需要修改规则后并重新启动run一次项目,而在大项目中重启往往是比较费时的。这也是把接口转发规则完全交由webpack的不便之处。

如何克服?
既然使用本地localhost开发依然存在一些不足之处,我们有没有一些方法可以克服这些不足,从而搭建一个更友好高效的开发环境呢?
我个人认为,导致这些不足的背后实质上是两个原因:
- 本地开发和线上环境的域名不一致,这就导致了业务代码参杂了环境相关的不纯洁的代码。
- 转发配置与webpack过于耦合,这就致使一旦环境需要变动就不得不进行项目重启。
因此解决的方案也是基于这两点:
- 本地开发时,浏览器中访问的是线上域名,即用线上的域名来开发和调试本地代码,做到本地代码和线上代码完全一致而不需要在代码层面做环境区分。
- 将接口代理功能从webpack中抽离,使用其他工具接管这部分功能,webpack不再需要因修改转发配置而重启。
而这些实际上就是whistle能做并且可以做得很好的工作。
说了这么多,那whistle到底是什么呢?于我而言,whislte本质就是一个代理工具,在开发环境中,它的优势在于可以把本地环境的配置完全抽离出来。业务代码按生产环境的写,浏览器上跑的是线上域名,而接口的转发、静态资源的代理,这些本地开发需要支持的业务无关的环境问题都由whistle来完成。

如同上图左图所示,在以上介绍的基于localhost的开发模式中,开发人员在更改业务代码的同时,还需要手动更改webpack的proxy配置来代理不同的接口环境。
而在使用了whilstle的右图中,whistle接管了所有的代理功能,包括:
- 浏览器使用真实的线上地址,而html,js,css等静态资源代理到本地的开发项目。
- 发送到服务器的接口代理完全由whislte控制,代理到什么环境,哪个域名都可在whistle中设置。
更重要的是,whistle是实时更改生效且无须重启的,也就是说,开发人员只需要关注自己的业务代码,已经修改whislte的配置,就可以灵活高效地搭建本地开发环境。
最后
如果你之前没有用过whistle,如果你的确遇到了以上提及的或者其他一些本地开发环境的问题,又或者你觉得这个东西好像还挺有意思,那我推荐你可以尝试一下whistle,一起感受和探索它的魅力。