基于ServerLess的极简网页计数器:源码分析与最佳实践
栏目: JavaScript · 发布时间: 5年前
内容简介:这几天基于支持HTML5无感认证的ServerLess平台开发了一款博客、门户网站等web平台常用的PV统计工具:回首看来,解决了以下几个比较有意思的问题:
这几天基于支持HTML5无感认证的ServerLess平台开发了一款博客、门户网站等web平台常用的PV统计工具: page-counter 。主要用到的技术是js+webpack。
回首看来,解决了以下几个比较有意思的问题:
- 如何设计代码,用统一的方式支持多个ServerLess平台?
- 如何架构项目,使得其支持CDN和npm两种方式引入?
- 如何精简源码,源码大小控制在4kb?
- 如何借助webpack分离生产和测试环境?
源码地址: https://github.com/dongyuanxin/page-counter
npm地址: https://www.npmjs.com/package/page-counter
如果有兴趣的同学,欢迎在阅读完本文后一起接入其他平台的开发; 觉得不错的同学,欢迎给个Star哦 。
项目目录
如上图所示,bin/backend 目录是暂时没用的。几个比较重要的目录功能说明:
-
build/
: webpack的配置文件,分别是公共配置、开发模式配置、生产模式配置 -
dist/
- index.template.html: 开发模式下配合webpack的html模板文件
- page-counter.min.js: 打包后的page-counter内容,供CDN引入
- page-counter.bomb-1.6.7.min.js:我手动修改并且打包的Bomb平台源码
-
examples/
: gh-pages页面,请看此页面 -
deploy.sh
: gh-pages部署脚本,支持ssh和https协议 -
index.js
: npm的入口文件 -
index.build.js
: CDN打包入口文件 -
src/
:serverless/ config.js utils.js
抽象接口:支持多Serverless平台
src/serverless/interface.js
中定义了不同平台的类的公共父类。虽然js不支持抽象接口,但是也可以通过抛出错误来实现:
export default class ServerLessInterface { constructor () {} ACL () { throw new Error('Interface method "ACL" must be rewritten') } setData () { throw new Error('Interface method "setData" must be rewritten') } count () { throw new Error('Interface method "count" must be rewritten') } }
而 leancloud.js 、bomb.js 等不同平台的类都要实现这个接口中的这3个方法。然后通过 src/serverless/index.js
统一暴露出去:
import LeanCloud from './leancloud' import Bomb from './bomb' class ServerLessFactory { constructor (name) { name = name.toLocaleLowerCase() switch (name) { case 'leancloud': return new LeanCloud() case 'bomb': return new Bomb() default: throw new Error('Serverless must be one of [ leancloud, bomb ]') } } } export default ServerLessFactory
这两种设计,既解耦了不同平台的代码,而且还约束了实现规则。如果想接入更多平台,只需要创建新文件,并且暴露一个继承 ServerLessInterface
接口的指定方法的子类即可。
快速方便:支持CDN和npm的使用
一个成熟的前端小 工具 需要考虑到多种引入方式,目前主流的就是cdn和npm。例如jquery,cdn引入,jq会被自动挂载在window对象上;npm引入,则作用域只在当前文件模块有用。
在考察了多种同类工具后,针对cdn和npm做了不同的处理。
npm
对外暴露 PageCounter
对象,其上有3个方法:
-
setData()
:将当前页面信息发送到云数据库 -
countTotal()
: 统计数据库总记录数(网站总PV),并且将返回结果 自动放入 id为page-counter-total-times的标签里 -
countSingle()
: 统计数据库符合要求的记录数(当前页面PV),并且将返回结果 自动放入 id为page-counter-single-times的标签里
import PageCounter from './src' export default PageCounter
CDN
不会在全局挂载上述对象方法,会自动执行上面的3种方法。考虑到并发以及pv数允许1以内的误差,没有保证串行。
import PageCounter from './src' PageCounter.setData() PageCounter.countTotal() PageCounter.countSingle()
精简源码:巧用package.json和第三方SDK
经过精简,打包后cdn引入的源码只有4kb。npm引入的话,webpack会自动进行tree shaking。因为要对接不同的serverless平台,因此需要使用他们的sdk。
而这些sdk分成2种:
- 类似leancloud:既可以npm引入,也可以cdn引入后自动挂载到window对象
- 类似bomb:无cdn引入,只要npm引入
针对第二种情况,我采取的方案是手动打包编译。比如对于bomb的sdk,专门创建新的工程,然后配合webpack和以下代码,进行打包。
import Bomb from 'hydrogen-js-sdk' window.Bomb = Bomb
打包后的源码放入版本库,这样借助 https://unpkg.com 等常见的CDN平台就可以引入了。这么做的很重要的一点是: 代码中都是通过window上的对象读取对应serverless平台的api,这样就不会被webpack识别,进而发生重复无用打包 。
关于读取配置的文件,都放在了 src/config.js
下。考虑到script标签引入造成的变量挂载时间点不确定,读取采用了动态读取。 为了操作起来更方便,而不是像调用函数那样,借助了 es6类语法中的 setter和getter。
// 举个例子: class Config { constructor() {} get serverless() { if (!window.PAGE_COUNTER_CONFIG) { throw new Error('Please init variable window.PAGE_COUNTER_CONFIG') } return window.PAGE_COUNTER_CONFIG.serverless || 'leancloud' } } const config = new Config() console.log(config.serverless) // 返回当前最新的window.PAGE_COUNTER_CONFIG.serverless
最后讲讲package.json的小技巧。虽然代码中没有使用import语法读取sdk的对象,但是我还是把leancloud、bomb平台的sdk放入了 dependencies
。这样做有什么好处呢?
用户只需要安装page-counter即可,其他sdk自动安装(不需要手动再敲命令)。然后用户就可以使用下面语法美滋滋引入:
import('hydrogen-js-sdk') .then(res => { // 将 Bomb 对象挂载在 window 上 window.Bomb = res.default // 设置应用信息 window.PAGE_COUNTER_CONFIG = { // ... } return import('page-counter') }) .then(res => { const PageCounter = res.default PageCounter.setData() // 发送当前页面数据 PageCounter.countTotal() // 将总浏览量放入 ID 为 page-counter-total-times 的DOM元素中 PageCounter.countSingle() // 将当前页面浏览量放入 ID 为 page-counter-single-times 的DOM元素中 })
Webpack:分离生产和开发环境
不得不说,webpack真的好用呀。脏活累活以及常见工具,它都给你承包了。
webpack.base.conf.js
是两种模式的公共配置,指明入口文件以及代码环境(web)。并且能够识别模式,然后自行拼接配置。
webpack.prod.conf.js
:生产模式,主要为了打包源码,方便CDN引入。
webpack.dev.conf.js
: 开启热更新以及本地服务器方便调试,渲染的前端调试页面的模板文件就是 dist/index.template.html
。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
马尔可夫链:模型、算法与应用
Wai-Ki Ching、Ximin Huang / 陈曦 / 清华大学出版社 / 2015-6 / 39
《马尔可夫链:模型、算法与应用 应用数学译丛》讲述了马尔可夫链模型在排队系统、网页重要性排名、制造系统、再制造系统、库存系统以及金融风险管理等方面的最新应用进展.全书共安排8章内容,第1章介绍马尔可夫链、隐马尔可夫模型和马尔可夫决策过程的基本理论和方法,其余7章分别介绍马尔可夫链模型在不同领域中的应用. 《马尔可夫链:模型、算法与应用 应用数学译丛》可作为自动化、工业工程、统计学、应用数学以及管理......一起来看看 《马尔可夫链:模型、算法与应用》 这本书的介绍吧!