Skip to content

Repository files navigation

sonic-server

Sonic

Image From: https://dribbble.com/shots/2338954-Sonic-Speed

一键式多功能前端本地开发调试环境

Front-End Dev server based on anyproxy & webpack-dev-server.

特性

  1. 轻量级的本地静态资源服务,自动起 Chrome 进程完成代理绑定,支持可配置的虚拟域名,淘系下 *.taobao.com 域名开发(免登、mtop)无痛开发再也不是梦;
  2. 自动按需整合 webpack-dev-server, 零配置支持 HMR(Hot Module Replacement, 热模块替换);
  3. 支持方便的接口 Mock(JSONP 也不在话下)和输出页面 DOM 修改(TMS/EMS 区块嵌入页面,脚本注入 so easy);
  4. https 支持,只需信任 anyproxy 证书,即刻进入 https 的世界;
  5. 轻松 hosts 绑定,指定 hosts 映射表即可,从此远离修改系统 hosts 文件;
  6. TO BE CONTINUED...

安装

命令行使用

npm i sonic-server -g

然后

sonic

作为 lib

npm i sonic-server -S

使用

命令行

命令行下执行 sonic, 会自动将当前作为目录作为内容根目录起本地服务, 如果当前目录下有 webpack.config.js 文件, 会将其作为 webpackConfig, 起 webpack-dev-server, 并会在控制台输出相应配置:

h5 ➤ sonic --https
Proxy for Sonic!
Anyproxy rules initialize finished, have fun!
>> Proxy server started at http://10.62.64.141:8080
GUI interface started at : http://10.62.64.141:8002/
Http proxy started at 10.62.64.141:8080
[internal https]certificate created for 10.62.64.141
>>
-------------- 服务配置 --------------
本地 IP 地址	=> 10.62.64.141
本地代理服务	=> 10.62.64.141:8080
静态资源服务	=> http://10.62.64.141:8081
请求代理监控	=> http://localhost:8002
-------------- 服务配置 --------------
...

如果当前目录下不存在 sonic 配置文件 (sonic.config.js), 则会自动根据模板和当前配置项生成一份, 后续命令行执行会合并命令行参数和 sonic 配置文件配置.

查看全部命令行参数:

h5 ➤ sonic -h
Usage: sonic [options]
Options:
-h, --help 查看帮助
-v, --version 查看版本号
-w, --webpackConfig [value] webpack.config.js 配置文件路径
-s, --serverPort [value] 本地静态资源服务端口号
-p, --proxyPort [value] 代理服务工作端口号
--hosts [value] 需要代理的本地虚拟域名, 请以 ',' 分隔
--https 是否切换到 https

作为 lib

var Sonic = require('sonic-server');
var options = {
// webpack 配置, 可为 webpack.config.js 路径或 webpack 配置对象
webpackConfig: path.join(pwd, 'webpack.config.js'),
// 本地静态资源服务端口号
serverPort: 8081,
// 本地代理服务端口号
proxyPort: 8080,
// Anyproxy 的 web 请求监控页面端口号
webPort: 8002,
// Anyproxy 的 websocket 请求工作端口号
socketPort: 8003,
// 需要代理的 hosts 字符串数组
hosts: [],
// 是否显示 webpack 编译进度
progress: true,
// 是否自动注入 HMR
injectHMR: true,
// 注入 WindVane 脚本路径, 自动在 WindVane 容器下注入 windvane.js, 如不需要设置为 `false` 即可
injectWV: true || 'http://xxx/windvane.js',
// 是否切换到 https
https: false,
// 内容根目录
contentBase: pwd,
// 是否禁用控制台 log 输出
silent: false,
// 是否仅启动静态资源服务, 而不基于 webpack-dev-server
pureStatic: false,
// 是否在浏览器自动打开 Url
openBrowser: true,
// 默认开启的路径
openPath: '/',
// 新起 Chrome 基于的用户目录绝对路径
chromeUserDir: DEFAULT_USER_DIR,
// 浏览器程序路径(mac 下 Chrome)
browserApp: DEFAULT_BROWSER,
// 要 mock 的请求 url 应该匹配的正则表达式
mockRegExp: null,
/**
* 接口 mock 处理函数
* @param requestUrl {String} 请求 URL
* @param response {Object} 服务端响应
* @param response.headers {Object} 响应头
* @param response.body {Object|String} 响应体, 如果是 JSON / JSONP, 自动转为 JSON 对象
* @returns {Object} 返回可 JSON 序列化的对象
*/
mockFunction: (requestUrl, response) => {
return responseBody;
},
// hosts 映射表, 域名 - IP 键值对
hostsMap: {},
/**
* HTML 操作函数
* @param reqUrl {String} 请求 URL
* @param reqHeaders {Object} 请求头
* @param resHeaders {Object} 响应头
* @param $ {Object} jQuery 对象
* @param commentNodes {Array} 注释节点
* @param logger {Object}
* @param callback {Function} 回调
*/
htmlModify: (reqUrl, reqHeaders, resHeaders, $, commentNodes, logger, cb) => {
cb($.html());
},
/**
* 改写发出的请求
*/
modifyRequestObject: (requestObj) => {
requestObj.requestOptions.port = 1234;
return requestObj;
}
};
Sonic(options, /*logger (optional)*/, (server) => {
// 进程退出
process.on('SIGINT', () => {
server.close();
});
});

Options

options.webpackConfig

  • Type: String|Object
  • Default value: path.join(process.cwd(), 'webpack.config.js')
  • Webpack config 文件路径 / Webpack 配置对象

options.serverPort

  • Type: Number
  • Default value: 8081
  • 本地静态服务工作的端口号

options.proxyPort

  • Type: Number
  • Default value: 8080
  • 代理服务工作端口号

options.webPort

  • Type: Number
  • Default value: 8002
  • Anyproxy 的 web 请求监控页面端口号

options.socketPort

  • Type: Number
  • Default value: 8003
  • Anyproxy 的 websocket 请求工作端口号

options.hosts

  • Type: Array
  • Default value: []
  • 需要模拟的虚拟域名

options.progress

  • Type: Boolean
  • Default value: true
  • 是否显示 webpack 编译进度

options.injectHMR

  • Type: Boolean
  • Default value: true
  • 是否对 webpack 编译, 自动注入 HMR

options.injectWV

  • Type: Boolean|String
  • Default value: true
  • 是否在 WindVane 容器内(根据 UserAgent 探测)自动注入 windvane.js, 或者可配置为 windvane.js 脚本路径

options.https

  • Type: Boolean
  • Default value: false
  • 是否切换到 https.

options.contentBase

options.silent

  • Type: Boolean
  • Default value: false
  • 是否禁用掉控制台 anyproxy 输出 log

options.pureStatic

  • Type: Boolean
  • Default value: false
  • 是否仅仅启动本地纯静态文件服务, 而不需要 webpack-dev-server

options.openBrowser

  • Type: Boolean
  • Default value: true
  • 是否在浏览器自动打开 Url

options.openPath

  • Type: String
  • Default value: '/'
  • 本地服务启动后自动加载的路径

options.openUrl

  • Type: String
  • Default value: '/'
  • 本地服务启动后自动加载的页面完整 URL, 优先级高于 options.openPath

options.mockRegExp

  • Type: RegExp
  • Default value: null
  • 需要接口 Mock 的 url 应该匹配的正则

options.mockFunction

  • Type: Function
  • Default value: (requestUrl, response) => { return responseBody; }
  • 接口 Mock 方法

options.mockBeforeFunction

  • Type: Function
  • Default value: (requestUrl) => { return responseBody; }
  • 接口 Mock 方法

options.hostsMap

  • Type: Object
  • Default value: {}
  • hosts 映射表, 和本地绑 hosts 一样的原理

options.htmlInterceptReg

  • Type: RegExp
  • Default value: /$^/(不匹配任何 URL)
  • 需要页面 Mock 的 url 应该匹配的正则

options.htmlModify

  • Type: Function
  • Default value: (reqUrl, reqHeaders, resHeaders, $, commentNodes, logger, cb) => { cb($.html()); }
  • 对本地虚拟域名下加载的 html 页面进行自定义操作(如插入脚本, tms/ems 区块自动注入等)

options.assetsComboRegExp

  • Type: RegExp
  • Default value: /$^/(不匹配任何 URL)
  • 需要拆分 js/css 资源 combo 的 url 应该匹配的正则

options.assetsComboMapLocal

  • Type: Function
  • Default value: (comboUrl, comboParts) => { return comboParts; }
  • 输入远程 js/css 资源 combo 的 url 和拆分后的各个单独资源文件请求, 返回对应应该映射到本地的文件路径(相对于当前工作目录)。
  • 如某个映射本地文件不存在会自动加载线上。

options.webpackStatsOption

options.modifyRequestObject

options.corsInject

  • Type: Boolean
  • Default value: true
  • 是否自动注入 CORS 响应头.

接口 Mock

接口 Mock 脚本 Demo

/** * 接口 mock 处理模块 * @param requestUrl {String} 请求 URL * @param response {Object} 服务端响应 * @param response.headers {Object} 响应头 * @param response.body {Object|String} 响应体, 如果是 JSON / JSONP, 自动转为 JSON 对象 * @returns {Object} 返回可 JSON 序列化的对象 */module.exports=function(requestUrl,response){varurl=require('url');varparsedReqUrl=url.parse(requestUrl,true);varparams=parsedReqUrl.query;varresponseBody=response.body;switch(params.api){// case 'mtop.xxx':// responseBody.test = 123;// break;default:
responseBody.default=true;break;}returnresponseBody;};

原理图

原理图

  1. 开发者从虚拟域名(如 dev.waptest.taobao.com)请求本地目录页面;
  2. 本地代理服务对浏览器各个请求分别做不同的代理分发:
  3. 如果是虚拟域名下的资源请求 dev.waptest.taobao.com/*,统一定向到本地 webpack-dev-server 的静态资源服务;
  4. 如果是请求 url 匹配上接口 mock url 规则,将接口服务器的响应做代理,执行用户定义的响应数据重写逻辑后,再通过代理服务传递回浏览器端;
  5. 其他类型的资源请求(如线上图片、埋点等),代理服务器透明代理,不做处理

常见问题

  • Q: 接口代理未生效?

    • A: 有可能站点证书已过期, 参见 Anyproxy issue #1, 删除掉旧证书(路径默认在 ~/.anyproxy-certs)刷新即可重新生成新的证书.
  • Q: 切换到 https 时站点或接口访问有问题?

    • A: 尝试 rm -rf ~/.anyproxy-certs, 然后重新启动服务, 将 anyproxy 证书加入系统钥匙串, 然后重试.
    • A: 更多 https 配置可参考: HTTPS相关教程
  • Q: 移动端如何绑定 HTTP 代理?

  • Q: 移动端(手机、Pad 等)如何访问 https?

    • A: 在桌面浏览器打开控制台输出的 请求代理监控 => http://localhost:8002 部分的监控页面 url,点击『QRCode of rootCA.crt』,在新打开的 http://localhost:8002/qr_root 页面中通过移动端扫码应用扫码即会自动进入证书安装流程(建议最好使用系统原生浏览器打开二维码 url)

周边

Credits

Release History

  • [1.0.0]
    • initial version

License

Copyright (c) 2016 弘树. Licensed under the MIT license.

About

Front-End Dev server based on anyproxy & webpack-dev-server.

Resources

Stars

13 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages