基于ServerLess的極簡網(wǎng)頁計數(shù)器:源碼分析與實踐

image.png

這幾天基于支持HTML5無感認證的ServerLess平臺開發(fā)了一款博客琐馆、門戶網(wǎng)站等web平臺常用的PV統(tǒng)計工具:page-counter 。主要用到的技術(shù)是js+webpack恒序。

回首看來瘦麸,解決了以下幾個比較有意思的問題:

  • 如何設計代碼,用統(tǒng)一的方式支持多個ServerLess平臺歧胁?
  • 如何架構(gòu)項目滋饲,使得其支持CDN和npm兩種方式引入?
  • 如何精簡源碼喊巍,源碼大小控制在4kb屠缭?
  • 如何借助webpack分離生產(chǎn)和測試環(huán)境?

源碼地址:https://github.com/dongyuanxin/page-counter

npm地址:https://www.npmjs.com/package/page-counter

如果有興趣的同學玄糟,歡迎在閱讀完本文后一起接入其他平臺的開發(fā)勿她; 覺得不錯的同學袄秩,歡迎給個Star哦 阵翎。

??查看全部文章目錄 / 閱讀原文??

項目目錄

image

如上圖所示逢并,bin/backend 目錄是暫時沒用的。幾個比較重要的目錄功能說明:

  • build/ : webpack的配置文件郭卫,分別是公共配置砍聊、開發(fā)模式配置、生產(chǎn)模式配置
  • dist/
    • index.template.html: 開發(fā)模式下配合webpack的html模板文件
    • page-counter.min.js: 打包后的page-counter內(nèi)容贰军,供CDN引入
    • page-counter.bomb-1.6.7.min.js:我手動修改并且打包的Bomb平臺源碼
  • examples/ : gh-pages頁面玻蝌,請看此頁面
  • deploy.sh : gh-pages部署腳本,支持ssh和https協(xié)議
  • index.js : npm的入口文件
  • index.build.js : CDN打包入口文件
  • src/ :
    • serverless/ : 暴露不同平臺的統(tǒng)一接口
    • config.js : 自動讀取全局配置
    • utils.js : 常用函數(shù)方法

抽象接口:支持多Serverless平臺

src/serverless/interface.js 中定義了不同平臺的類的公共父類词疼。雖然js不支持抽象接口俯树,但是也可以通過拋出錯誤來實現(xiàn):

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 等不同平臺的類都要實現(xiàn)這個接口中的這3個方法贰盗。然后通過 src/serverless/index.js 統(tǒng)一暴露出去:

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

這兩種設計许饿,既解耦了不同平臺的代碼,而且還約束了實現(xiàn)規(guī)則舵盈。如果想接入更多平臺陋率,只需要創(chuàng)建新文件,并且暴露一個繼承 ServerLessInterface 接口的指定方法的子類即可秽晚。

快速方便:支持CDN和npm的使用

一個成熟的前端小工具需要考慮到多種引入方式瓦糟,目前主流的就是cdn和npm。例如jquery赴蝇,cdn引入菩浙,jq會被自動掛載在window對象上;npm引入句伶,則作用域只在當前文件模塊有用芍耘。

在考察了多種同類工具后,針對cdn和npm做了不同的處理熄阻。

npm

對外暴露 PageCounter 對象斋竞,其上有3個方法:

  • setData() :將當前頁面信息發(fā)送到云數(shù)據(jù)庫
  • countTotal() : 統(tǒng)計數(shù)據(jù)庫總記錄數(shù)(網(wǎng)站總PV),并且將返回結(jié)果自動放入id為page-counter-total-times的標簽里
  • countSingle() : 統(tǒng)計數(shù)據(jù)庫符合要求的記錄數(shù)(當前頁面PV)秃殉,并且將返回結(jié)果自動放入id為page-counter-single-times的標簽里
import PageCounter from './src'

export default PageCounter

CDN

不會在全局掛載上述對象方法坝初,會自動執(zhí)行上面的3種方法〖鼐考慮到并發(fā)以及pv數(shù)允許1以內(nèi)的誤差鳄袍,沒有保證串行。

import PageCounter from './src'

PageCounter.setData()
PageCounter.countTotal()
PageCounter.countSingle()

精簡源碼:巧用package.json和第三方SDK

經(jīng)過精簡吏恭,打包后cdn引入的源碼只有4kb拗小。npm引入的話,webpack會自動進行tree shaking樱哼。因為要對接不同的serverless平臺哀九,因此需要使用他們的sdk剿配。

而這些sdk分成2種:

  • 類似leancloud:既可以npm引入,也可以cdn引入后自動掛載到window對象
  • 類似bomb:無cdn引入阅束,只要npm引入

針對第二種情況呼胚,我采取的方案是手動打包編譯。比如對于bomb的sdk息裸,專門創(chuàng)建新的工程蝇更,然后配合webpack和以下代碼,進行打包呼盆。

import Bomb from 'hydrogen-js-sdk'
window.Bomb = Bomb

打包后的源碼放入版本庫年扩,這樣借助 https://unpkg.com 等常見的CDN平臺就可以引入了。這么做的很重要的一點是: 代碼中都是通過window上的對象讀取對應serverless平臺的api访圃,這樣就不會被webpack識別常遂,進而發(fā)生重復無用打包

關(guān)于讀取配置的文件挽荠,都放在了 src/config.js 下克胳。考慮到script標簽引入造成的變量掛載時間點不確定圈匆,讀取采用了動態(tài)讀取漠另。為了操作起來更方便,而不是像調(diào)用函數(shù)那樣跃赚,借助了 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() // 發(fā)送當前頁面數(shù)據(jù)
    PageCounter.countTotal() // 將總瀏覽量放入 ID 為 page-counter-total-times 的DOM元素中
    PageCounter.countSingle() // 將當前頁面瀏覽量放入 ID 為 page-counter-single-times 的DOM元素中
  })

Webpack:分離生產(chǎn)和開發(fā)環(huán)境

不得不說汁雷,webpack真的好用呀净嘀。臟活累活以及常見工具,它都給你承包了侠讯。

webpack.base.conf.js 是兩種模式的公共配置挖藏,指明入口文件以及代碼環(huán)境(web)。并且能夠識別模式厢漩,然后自行拼接配置膜眠。

webpack.prod.conf.js :生產(chǎn)模式,主要為了打包源碼,方便CDN引入宵膨。

webpack.dev.conf.js : 開啟熱更新以及本地服務器方便調(diào)試架谎,渲染的前端調(diào)試頁面的模板文件就是 dist/index.template.html

更多文章

專注前端與算法的系列干貨分享柄驻,歡迎關(guān)注(???)


image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狐树,一起剝皮案震驚了整個濱河市焙压,隨后出現(xiàn)的幾起案子鸿脓,更是在濱河造成了極大的恐慌,老刑警劉巖涯曲,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件野哭,死亡現(xiàn)場離奇詭異,居然都是意外死亡幻件,警方通過查閱死者的電腦和手機拨黔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绰沥,“玉大人篱蝇,你說我怎么就攤上這事』涨” “怎么了零截?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長秃臣。 經(jīng)常有香客問我涧衙,道長,這世上最難降的妖魔是什么奥此? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任弧哎,我火速辦了婚禮,結(jié)果婚禮上稚虎,老公的妹妹穿的比我還像新娘撤嫩。我一直安慰自己,他們只是感情好蠢终,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布非洲。 她就那樣靜靜地躺著,像睡著了一般蜕径。 火紅的嫁衣襯著肌膚如雪两踏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天兜喻,我揣著相機與錄音梦染,去河邊找鬼。 笑死,一個胖子當著我的面吹牛帕识,可吹牛的內(nèi)容都是我干的泛粹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼肮疗,長吁一口氣:“原來是場噩夢啊……” “哼晶姊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起伪货,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤们衙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碱呼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒙挑,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年愚臀,在試婚紗的時候發(fā)現(xiàn)自己被綠了忆蚀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡姑裂,死狀恐怖馋袜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舶斧,我是刑警寧澤欣鳖,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站捧毛,受9級特大地震影響观堂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呀忧,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一师痕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧而账,春花似錦胰坟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咐吼。三九已至吹缔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锯茄,已是汗流浹背厢塘。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工茶没, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晚碾。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓落午,卻偏偏與公主長得像皮官,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子畔濒,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容