Tips又更新啦吕粗!要來看看嗎~

前言

Tips的重大更新又來了债蜜,如果不知道Tips是什么的你梨州,可以移步這里Tips——將你從頻繁的文案修改中解救出來祖秒,如果看過這篇文章或者使用過這個(gè)平臺(tái)的诞吱,那就可以直接往下看了。今天將向大家介紹Tips的新功能——自動(dòng)埋點(diǎn)竭缝,之前如果想要使用Tips都是手動(dòng)在代碼中埋點(diǎn)房维,現(xiàn)在可以使用我們提供的cli工具,使用簡(jiǎn)單的命令就可以自動(dòng)埋點(diǎn)抬纸,然后就可以去修改你的文案了咙俩。感興趣的你可以繼續(xù)往下看哈,我將從如下幾個(gè)方面來進(jìn)行介紹湿故。

1 設(shè)計(jì)初衷

如果使用過工具或看過之前的文章阿趁,你可能會(huì)因?yàn)槿缦聨讉€(gè)問題而被勸退。

問題一

在平臺(tái)創(chuàng)建了服務(wù)后坛猪,需要手動(dòng)在自己的項(xiàng)目中進(jìn)行埋點(diǎn)脖阵,任何文案都有被修改的可能,所以需要大量的埋點(diǎn)墅茉,無疑該操作是浪費(fèi)時(shí)間的独撇,所以可能因?yàn)槭謩?dòng)埋點(diǎn)這個(gè)操作你放棄了這個(gè)便利的工具。

問題二

你接入平臺(tái)的時(shí)候在第一次可能埋了大量的點(diǎn)躁锁,但是下次需要修改的并不是你之前埋點(diǎn)處的文案,你還需要在自己的代碼中重新埋點(diǎn)卵史,然后發(fā)起上線流程战转,重新打包上線,所以可能覺得這個(gè)平臺(tái)并不能很好的解決目前遇到的問題而放棄使用它以躯。

綜上兩個(gè)原因槐秧,就需要一個(gè)自動(dòng)埋點(diǎn)的工具啄踊,代替手動(dòng)埋點(diǎn),從而進(jìn)一步降低使用成本刁标。

2 工具形態(tài)

首先Tips的使用方式就是在前端HTML標(biāo)簽上綁定特殊屬性data-tip-id-"xxx"颠通,我們要實(shí)現(xiàn)的就是在標(biāo)簽上自動(dòng)加上這個(gè)特殊屬性。如下代碼段所示:

<span>我是一個(gè)按鈕</span>
埋點(diǎn)后變成
<span data-tip-id="xxx">我是一個(gè)按鈕</span>

實(shí)現(xiàn)如上這個(gè)過程膀懈,我想很多人都想到了Babel顿锰,它可以幫我們?nèi)プ鲞@個(gè)工作,也就是需要去實(shí)現(xiàn)一個(gè)Babel Plugin來解析抽象語法樹并修改節(jié)點(diǎn)启搂。但是只有Plugin還是不夠的硼控,我們還要考慮到,如下幾個(gè)問題:

  • 插件應(yīng)該在什么時(shí)候觸發(fā)去執(zhí)行埋點(diǎn)操作

這個(gè)過程應(yīng)該成為用戶可控的胳赌,所以最合理的應(yīng)該是用戶自己去手動(dòng)觸發(fā)牢撼,所以就需要一個(gè)簡(jiǎn)單的命令行工具,用戶執(zhí)行相關(guān)命令去觸發(fā)埋點(diǎn)操作疑苫。

  • 什么樣的文件需要埋點(diǎn)熏版,什么樣的不需要

在項(xiàng)目中文件類型是多種多樣的,就前端項(xiàng)目來說捍掺,我們的代碼都在src目錄下撼短,但是也并不是所有的文件都需要被掃描埋點(diǎn),因次就需要提供一個(gè)config文件來配置用戶自己的埋點(diǎn)規(guī)則乡小,比如埋點(diǎn)的入口和需要忽略的文件阔加。

綜上兩個(gè)原因我們需要的是一個(gè)Babel Plugin + cli這樣的工具。

3 如何實(shí)現(xiàn)

上面已經(jīng)確定了工具的形態(tài)满钟,接下來的重點(diǎn)就是如何實(shí)現(xiàn)了胜榔。下面將按照用戶的使用流程來慢慢展開。其實(shí)也很簡(jiǎn)單湃番,就是兩步夭织。

工具初始化
// 初始化配置文件
 fs.writeFileSync(
   './tips.config.js',
   prettier.format(
     `module.exports = ${JSON.stringify({
        entry: 'src',
        exclude: [],
      })}`,
      {
       parser: 'typescript',
       singleQuote: true,
       trailingComma: 'es5',
     }
   ),
   'utf8'
 );

在上面的示例代碼中我們創(chuàng)建了一個(gè)名為tips.config.js的文件,在文件中配置了簡(jiǎn)單的埋點(diǎn)入口和忽略文件選項(xiàng)吠撮,然后將它寫入當(dāng)前項(xiàng)目中尊惰。這樣就完成了初始化操作,用戶可以去修改這個(gè)文件來配置簡(jiǎn)單的埋點(diǎn)規(guī)則泥兰。

開始埋點(diǎn)
const prettier = require('prettier');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse');
const generate = require('@babel/generator');
const buryPointPlugin = require('../plugin');

function buryPoint(filePath, options) {
  const fileContent = fs.readFileSync(filePath, 'utf-8');
  const ast = parser.parse(fileContent, {
    sourceType: 'module',
    plugins: [
      'typescript',
      'jsx',
    ],
  });
  traverse(ast, buryPointPlugin());
  let { code } = generate(ast, {});
  code = prettier.format(code, options.prettier);
  fs.writeFileSync(filePath, code, { encoding: 'utf-8' });
}

在上述代碼中:

  • 首先用@babel/parserparse方法弄屡,并結(jié)合現(xiàn)成的babel plugin,來將需要轉(zhuǎn)換的代碼文件轉(zhuǎn)換為AST(抽象語法樹)鞋诗;
  • 然后用@babel/traverse來遍歷該語法樹膀捷,并利用buryPointPlugin來修改AST,將它改為想要的樣子削彬,也就是在JSX節(jié)點(diǎn)上加上data-tip-id屬性全庸;
  • 最后使用@babel/generator來將AST轉(zhuǎn)化為最終的代碼秀仲。
buryPointPlugin做了什么
const t = require('@babel/types');
// 構(gòu)造屬性節(jié)點(diǎn)
function buildAttribute(t, id) {
  return t.jsxAttribute(t.jSXIdentifier('data-tip-id'), t.stringLiteral(id));
}

// 構(gòu)造openElement節(jié)點(diǎn)
function buildTipsIdAttributeOpeningElement(path, t, id) {
  let buildTagAttributes = path.node.attributes;
  return t.jSXOpeningElement(
    path.node.name, // object: JSXMemberExpression | JSXIdentifier
    buildTagAttributes,
    path.node.selfClosing // 是否自閉合,不設(shè)的話默認(rèn)為false壶笼,需要根據(jù)標(biāo)簽原有特性去設(shè)置
  );
}

module.exports = function() {
  return {
    JSXOpeningElement: (path) => {
      const children = path.parent.children;
      const tipsUniqId = `${getSeconds()}-${_.uniqueId()}`;
      const newOpeningElement = buildTipsIdAttributeOpeningElement(path, t, tipsUniqId);
      path.replaceWith(newOpeningElement);
    },
  }
}

上述是最核心的一部分代碼神僵,也就是構(gòu)造帶有data-tip-id的新節(jié)點(diǎn)去替換原來的節(jié)點(diǎn)。有同學(xué)可能要問了覆劈,我怎么知道自己構(gòu)造的節(jié)點(diǎn)類型需要哪些屬性保礼,其實(shí)這些都可以去babel官網(wǎng)查看。所以寫插件時(shí)的重點(diǎn)工作應(yīng)該是確定插件要做的事墩崩,然后將源語法樹氓英,修改為目標(biāo)語法樹,在這里推薦一個(gè)很好用的工具鹦筹,可以很方便的查看語法樹的結(jié)構(gòu):查看工具铝阐。

4 如何定制規(guī)則

用過Tips的都知道,我們?cè)诰庉嬑陌傅臅r(shí)候會(huì)在頁面上看到紅色的編輯按鈕铐拐,如果不做埋點(diǎn)控制徘键,那么打開開關(guān)你將會(huì)看到滿屏的紅色按鈕,那體驗(yàn)簡(jiǎn)直是災(zāi)難性的遍蟋。所以在掃到的代碼中吹害,并不是所有的標(biāo)簽都需要埋點(diǎn),所以需要定義一些特殊的規(guī)則虚青,避免埋太多的無用點(diǎn)它呀。這些規(guī)則考慮到通用性和實(shí)現(xiàn)的復(fù)雜度的問題,并沒有開放在用戶的配置文件中棒厘。

如下是所有的不埋點(diǎn)情況:

  • 1 標(biāo)簽的子節(jié)點(diǎn)只有JSXElement
<div>
  <span>我的父元素不埋點(diǎn)</span>
  <span>我的父元素不埋點(diǎn)</span>
</div>
  • 2纵穿、標(biāo)簽的子節(jié)點(diǎn)只有CallExpression
<div>{render()}</div>
  • 3、標(biāo)簽的子節(jié)點(diǎn)只有ConditionalExpression
<div>{a ? <span>我是真</span> : <span>我是假</span>}</div>

4奢人、標(biāo)簽的子節(jié)點(diǎn)只有LogicalExpression

<div>
  {
    a && <span>我是真</span>
  }
</div>
  • 5谓媒、標(biāo)簽有特殊屬性tips-bp-ignore的不埋點(diǎn)
<div tips-bp-ignore>
  我是被忽略的標(biāo)簽,不埋點(diǎn)
</div>

5 如何使用

說了這么多何乎,那究竟如何使用呢句惯?請(qǐng)往下看。

下載
npm i tips-burypoint-cli --save-dev
初始化
tips-bp init

初始化生成tips.config.js文件支救,可進(jìn)行相關(guān)配置抢野。

開始埋點(diǎn)
tips-bp start

6 總結(jié)

在上述總結(jié)了Tips自動(dòng)埋點(diǎn)工具的整個(gè)實(shí)現(xiàn)過程, 也附上了一些插件的實(shí)現(xiàn)源碼各墨,可以看到具體的coding并不難指孤,難的是整個(gè)設(shè)計(jì)和思考的過程,感謝團(tuán)隊(duì)小伙伴給的改進(jìn)建議欲主,文章就寫到這里邓厕,目前工具已經(jīng)上傳在npm上,希望有需要的你可以試著用用哈扁瓢。

具體如何使用详恼,請(qǐng)戳這里:https://github.com/didi/Tips

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市引几,隨后出現(xiàn)的幾起案子昧互,更是在濱河造成了極大的恐慌,老刑警劉巖伟桅,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敞掘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡楣铁,警方通過查閱死者的電腦和手機(jī)玖雁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盖腕,“玉大人赫冬,你說我怎么就攤上這事±A校” “怎么了劲厌?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)听隐。 經(jīng)常有香客問我补鼻,道長(zhǎng),這世上最難降的妖魔是什么雅任? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任风范,我火速辦了婚禮,結(jié)果婚禮上椿访,老公的妹妹穿的比我還像新娘乌企。我一直安慰自己,他們只是感情好成玫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布加酵。 她就那樣靜靜地躺著,像睡著了一般哭当。 火紅的嫁衣襯著肌膚如雪猪腕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天钦勘,我揣著相機(jī)與錄音陋葡,去河邊找鬼。 笑死彻采,一個(gè)胖子當(dāng)著我的面吹牛腐缤,可吹牛的內(nèi)容都是我干的捌归。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼岭粤,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼惜索!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剃浇,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤巾兆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后虎囚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體角塑,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年淘讥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了圃伶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡适揉,死狀恐怖留攒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嫉嘀,我是刑警寧澤炼邀,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站剪侮,受9級(jí)特大地震影響拭宁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瓣俯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一杰标、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧彩匕,春花似錦腔剂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绪爸,卻和暖如春湾碎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奠货。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工介褥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓柔滔,卻偏偏與公主長(zhǎng)得像溢陪,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子睛廊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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