<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我終于成功登上了JS 框架榜單,并且僅落后于 React 4 名!

          共 9254字,需瀏覽 19分鐘

           ·

          2023-07-19 12:27

          前言

          如期而至,我獨(dú)立開(kāi)發(fā)的 JavaScript 框架 Strve.js 迎來(lái)了一個(gè)大版本5.6.2。此次版本距離上次大版本發(fā)布已經(jīng)接近半年之多,為什么這么長(zhǎng)時(shí)間沒(méi)有發(fā)布新的大版本呢?主要是研究 Strve.js 如何支持單文件組件,使代碼智能提示、代碼格式化方面更加友好。之前也發(fā)布了 Strve SFC,但是由于其語(yǔ)法規(guī)則的繁瑣以及是在運(yùn)行時(shí)編譯的種種原因,我果斷放棄了這個(gè)方案的繼續(xù)研究。而這次的版本5.6.2成功解決了代碼智能提示、代碼格式化方面友好的問(wèn)題,另外還增加了很多錦上添花的特性,這些都?xì)w功于我們這次版本成功支持JSX語(yǔ)法。熟悉React的朋友知道,JSX語(yǔ)法非常靈活。 而 Strve.js 一大特性也就是靈活操作代碼塊,這里的代碼塊我們可以理解成函數(shù),而JSX語(yǔ)法在一定場(chǎng)景下也恰恰滿(mǎn)足了我們這種需求。

          那么,我們?nèi)绾卧?Strve 項(xiàng)目中使用JSX語(yǔ)法呢?我們?cè)赟trve項(xiàng)目構(gòu)建工具 CreateStrveApp 預(yù)置了模版,你可以選擇 strve-jsx 或者 strve-jsx-apps 模版即可。我們使用 CreateStrveApp 搭建完 Strve 項(xiàng)目會(huì)發(fā)現(xiàn),同時(shí)安裝了babelPluginStrvebabelPluginJsxToStrve,這是因?yàn)槲覀冃枰褂?babelPluginJsxToStrve 將 JSX 轉(zhuǎn)換為標(biāo)簽?zāi)0妫笤偈褂胋abelPluginStrve 將標(biāo)簽?zāi)0孓D(zhuǎn)換為 Virtual DOM,進(jìn)而實(shí)現(xiàn)差異化更新視圖。

          嘗試

          我既然發(fā)布出了一個(gè)大版本,并且個(gè)人還算比較滿(mǎn)意。那么下一步我如何推廣它呢?畢竟毛遂自薦有時(shí)候還是非常有意義的。所以,我打算通過(guò)js-framework-benchmark 這個(gè)項(xiàng)目評(píng)估下性能。

          js-framework-benchmark 是什么?我們這里就簡(jiǎn)單介紹下 js-framework-benchmark,它是一個(gè)用于比較 JavaScript 框架性能的項(xiàng)目。它旨在通過(guò)執(zhí)行一系列基準(zhǔn)測(cè)試來(lái)評(píng)估不同框架在各種場(chǎng)景下的性能表現(xiàn)。這些基準(zhǔn)測(cè)試包括渲染大量數(shù)據(jù)、更新數(shù)據(jù)、處理復(fù)雜的 UI 組件等。通過(guò)運(yùn)行這些基準(zhǔn)測(cè)試,可以比較不同框架在各種方面的性能優(yōu)劣,并幫助開(kāi)發(fā)人員選擇最適合其需求的框架。js-framework-benchmark 項(xiàng)目提供了一個(gè)包含多個(gè)流行 JavaScript 框架的基準(zhǔn)測(cè)試套件。這些框架包括 Angular、React、Vue.js、Ember.js 等。每個(gè)框架都會(huì)在相同的測(cè)試場(chǎng)景下運(yùn)行,然后記錄下執(zhí)行時(shí)間和內(nèi)存使用情況等性能指標(biāo)。通過(guò)比較這些指標(biāo),可以得出不同框架的性能差異。這個(gè)項(xiàng)目的目標(biāo)是幫助開(kāi)發(fā)人員了解不同 JavaScript 框架的性能特點(diǎn),以便在選擇框架時(shí)能夠做出更加明智的決策。同時(shí),它也可以促進(jìn)框架開(kāi)發(fā)者之間的競(jìng)爭(zhēng),推動(dòng)框架的不斷改進(jìn)和優(yōu)化。

          那么,我們就抱著試試的心態(tài)去運(yùn)行下這個(gè)項(xiàng)目。

          測(cè)試

          我們進(jìn)入js-framework-benchmark Github主頁(yè),然后 clone 下這個(gè)項(xiàng)目。

                
                git?clone?https://github.com/krausest/js-framework-benchmark.git

          然后,我們 clone 到本地之后,打開(kāi) README.md 文件找到如何評(píng)估框架。大體瀏覽之后,我們得出的結(jié)論是:通過(guò)使用自己的框架完成js-framework-benchmark規(guī)定的練習(xí)項(xiàng)目。

          9f361ea67bfa29c2daf255e961ac22db.webp

          那么,我們就照著其他框架已經(jīng)開(kāi)發(fā)完成的示例進(jìn)行開(kāi)發(fā)吧!在開(kāi)發(fā)之前,我們必須要了解js-framework-benchmark 中有兩種模式。一種是keyed,另一種是non-keyed。在 js-framework-benchmark 中,"keyed" 模式是指通過(guò)給數(shù)據(jù)項(xiàng)分配一個(gè)唯一標(biāo)識(shí)符作為 "key" 屬性,從而實(shí)現(xiàn)數(shù)據(jù)項(xiàng)與 DOM 節(jié)點(diǎn)之間的一對(duì)一關(guān)系。當(dāng)數(shù)據(jù)發(fā)生變化時(shí),與之相關(guān)聯(lián)的 DOM 節(jié)點(diǎn)也會(huì)相應(yīng)更新。而 "non-keyed" 模式是指當(dāng)數(shù)據(jù)項(xiàng)發(fā)生變化時(shí),可能會(huì)修改之前與其他數(shù)據(jù)項(xiàng)關(guān)聯(lián)的 DOM 節(jié)點(diǎn)。因?yàn)?Strve 暫時(shí)沒(méi)有類(lèi)似唯一標(biāo)識(shí)符這種特性,所以我們選擇non-keyed模式。

          我們打開(kāi)項(xiàng)目下/frameworks/non-keyed文件夾,找一個(gè)案例框架看一下它們開(kāi)發(fā)的項(xiàng)目,我們選擇 Vue 吧! 我們根據(jù)它開(kāi)發(fā)的樣例遷移到自己的框架中去。為了測(cè)試新版本,我們將使用JSX語(yǔ)法進(jìn)行開(kāi)發(fā)。

                
                import?{?createApp,?setData?}?from?"strve-js";
          import?{?buildData?}?from?"./data.js";

          let?selected?=?undefined;
          let?rows?=?[];

          function?setRows(update?=?rows.slice())?{
          ??setData(
          ????()?=>?{
          ??????rows?=?update;
          ????},
          ????{
          ??????name:?TbodyComponent,
          ????}
          ??);
          }

          function?add()?{
          ??const?data?=?rows.concat(buildData(1000));
          ??setData(
          ????()?=>?{
          ??????rows?=?data;
          ????},
          ????{
          ??????name:?TbodyComponent,
          ????}
          ??);
          }

          function?remove(id)?{
          ??rows.splice(
          ????rows.findIndex((d)?=>?d.id?===?id),
          ????1
          ??);
          ??setRows();
          }

          function?select(id)?{
          ??setData(
          ????()?=>?{
          ??????selected?=?+id;
          ????},
          ????{
          ??????name:?TbodyComponent,
          ????}
          ??);
          }

          function?run()?{
          ??setRows(buildData());
          ??selected?=?undefined;
          }

          function?update()?{
          ??for?(let?i?=?0;?i?<?rows.length;?i?+=?10)?{
          ????rows[i].label?+=?"?!!!";
          ??}
          ??setRows();
          }

          function?runLots()?{
          ??setRows(buildData(10000));
          ??selected?=?undefined;
          }

          function?clear()?{
          ??setRows([]);
          ??selected?=?undefined;
          }

          function?swapRows()?{
          ??if?(rows.length?>?998)?{
          ????const?d1?=?rows[1];
          ????const?d998?=?rows[998];
          ????rows[1]?=?d998;
          ????rows[998]?=?d1;
          ????setRows();
          ??}
          }

          function?TbodyComponent()?{
          ??return?(
          ????<tbody?$key>
          ??????{rows.map((item)?=>?(
          ????????<tr
          ??????????class={item.id?===?selected???"danger"?:?""}
          ??????????data-label={item.label}
          ??????????$key
          ????????>

          ??????????<td?class="col-md-1"?$key>
          ????????????{item.id}
          ??????????</td>
          ??????????<td?class="col-md-4">
          ????????????<a?onClick={()?=>?select(item.id)}?$key>
          ??????????????{item.label}
          ????????????</a>
          ??????????</td>
          ??????????<td?class="col-md-1">
          ????????????<a?onClick={()?=>?remove(item.id)}?$key>
          ??????????????<span
          ????????????????class="glyphicon?glyphicon-remove"
          ????????????????aria-hidden="true"
          ??????????????>
          </span>
          ????????????</a>
          ??????????</td>
          ??????????<td?class="col-md-6"></td>
          ????????</tr>
          ??????))}
          ????</tbody>

          ??);
          }

          function?MainBody()?{
          ??return?(
          ????<>
          ??????<div?class="jumbotron">
          ????????<div?class="row">
          ??????????<div?class="col-md-6">
          ????????????<h1>Strve-non-keyed</h1>
          ??????????</div>
          ??????????<div?class="col-md-6">
          ????????????<div?class="row">
          ??????????????<div?class="col-sm-6?smallpad">
          ????????????????<button
          ??????????????????type="button"
          ??????????????????class="btn?btn-primary?btn-block"
          ??????????????????id="run"
          ??????????????????onClick={run}
          ????????????????>

          ??????????????????Create?1,000?rows
          ????????????????</button>
          ??????????????</div>
          ??????????????<div?class="col-sm-6?smallpad">
          ????????????????<button
          ??????????????????type="button"
          ??????????????????class="btn?btn-primary?btn-block"
          ??????????????????id="runlots"
          ??????????????????onClick={runLots}
          ????????????????>

          ??????????????????Create?10,000?rows
          ????????????????</button>
          ??????????????</div>
          ??????????????<div?class="col-sm-6?smallpad">
          ????????????????<button
          ??????????????????type="button"
          ??????????????????class="btn?btn-primary?btn-block"
          ??????????????????id="add"
          ??????????????????onClick={add}
          ????????????????>

          ??????????????????Append?1,000?rows
          ????????????????</button>
          ??????????????</div>
          ??????????????<div?class="col-sm-6?smallpad">
          ????????????????<button
          ??????????????????type="button"
          ??????????????????class="btn?btn-primary?btn-block"
          ??????????????????id="update"
          ??????????????????onClick={update}
          ????????????????>

          ??????????????????Update?every?10th?row
          ????????????????</button>
          ??????????????</div>
          ??????????????<div?class="col-sm-6?smallpad">
          ????????????????<button
          ??????????????????type="button"
          ??????????????????class="btn?btn-primary?btn-block"
          ??????????????????id="clear"
          ??????????????????onClick={clear}
          ????????????????>

          ??????????????????Clear
          ????????????????</button>
          ??????????????</div>
          ??????????????<div?class="col-sm-6?smallpad">
          ????????????????<button
          ??????????????????type="button"
          ??????????????????class="btn?btn-primary?btn-block"
          ??????????????????id="swaprows"
          ??????????????????onClick={swapRows}
          ????????????????>

          ??????????????????Swap?Rows
          ????????????????</button>
          ??????????????</div>
          ????????????</div>
          ??????????</div>
          ????????</div>
          ??????</div>
          ??????<table?class="table?table-hover?table-striped?test-data">
          ????????<component?$name={TbodyComponent.name}>{TbodyComponent()}</component>
          ??????</table>
          ??????<span
          ????????class="preloadicon?glyphicon?glyphicon-remove"
          ????????aria-hidden="true"
          ??????>
          </span>
          ????</>

          ??);
          }

          createApp(()?=>?MainBody()).mount("#main");

          其實(shí),我們雖然使用了JSX語(yǔ)法,但是你會(huì)發(fā)現(xiàn)有很多特性并不與JSX語(yǔ)法真正相同,比如我們可以直接使用 class 去表示樣式類(lèi)名屬性,而不能使用 className 表示。

          評(píng)估案例項(xiàng)目開(kāi)發(fā)完成了,我們下一步就要測(cè)試一下項(xiàng)目是否符合評(píng)估標(biāo)準(zhǔn)。

                
                npm?run?bench?non-keyed/strve


          7d7621cdd065d59cf49f0ce0ab1529a6.webp

          測(cè)試標(biāo)準(zhǔn)包括:

          • create rows:創(chuàng)建行,頁(yè)面加載后創(chuàng)建 1000 行的持續(xù)時(shí)間(無(wú)預(yù)熱)

          • replace all rows:替換所有行,替換表中所有 1000 行所需的時(shí)間(5 次預(yù)熱循環(huán))。該指標(biāo)最大的價(jià)值就是了解當(dāng)頁(yè)面上的大部分內(nèi)容發(fā)生變化時(shí)庫(kù)的執(zhí)行方式。

          • partial update:部分更新,對(duì)于具有 10000 行的表,每 10 行更新一次文本(進(jìn)行 5 次預(yù)熱循環(huán))。該指標(biāo)是動(dòng)畫(huà)性能和深層嵌套數(shù)據(jù)結(jié)構(gòu)開(kāi)銷(xiāo)等方面的最佳指標(biāo)。

          • select row:選擇行,在單擊行時(shí)高亮顯示該行所需的時(shí)間(進(jìn)行 5 次預(yù)熱循環(huán))。

          • swap rows:交換行,在包含 1000 行的表中交換 2 行的時(shí)間(進(jìn)行 5 次預(yù)熱迭代)。

          • remove row:刪除行,在包含 1,000 行的表格上移除一行所需的時(shí)間(有 5 次預(yù)熱迭代),該指標(biāo)可能變化最少,因?yàn)樗葞?kù)的任何開(kāi)銷(xiāo)更多地測(cè)試瀏覽器布局變化(因?yàn)樗行邢蛏弦苿?dòng))。

          • create many rows:創(chuàng)建多行,創(chuàng)建 10000 行所需的時(shí)間(沒(méi)有預(yù)熱),該指標(biāo)更容易受到內(nèi)存開(kāi)銷(xiāo)的影響,并且對(duì)于效率較低的庫(kù)來(lái)說(shuō),擴(kuò)展性會(huì)更差。

          • append rows to large table:追加行到大型表格,在包含 10000 行的表格上添加 1000 行所需的時(shí)間(沒(méi)有預(yù)熱)。

          • clear rows:清空行,清空包含 10000 行的表格所需的時(shí)間(沒(méi)有預(yù)熱),該指標(biāo)說(shuō)明了庫(kù)清理代碼的成本,內(nèi)存使用對(duì)這個(gè)指標(biāo)的影響很大,因?yàn)闉g覽器需要更多的 GC。

          最終,Strve 頂住了壓力,通過(guò)了測(cè)試。

          5451594285411131a8b91dda7950800f.webp

          看到了successful run之后,覺(jué)得特別開(kāi)心!那種成就感是任何事物都難以代替的。

          跑分

          我們既然通過(guò)了測(cè)試,那么下一步我們將與前端兩大框架Vue、React進(jìn)行比較跑分,我們先在我自己本地環(huán)境上跑一下,看一下效果。

          性能測(cè)試基準(zhǔn)分為三類(lèi):

          • 持續(xù)時(shí)間
          • 啟動(dòng)指標(biāo)
          • 內(nèi)存分配

          持續(xù)時(shí)間

          3878fc4db98c8958a7db4c74c96bc748.webp

          啟動(dòng)指標(biāo)

          613f5ed1f805a4f4f4db8db9193b8ca1.webp

          內(nèi)存分配

          59a2fda6d0e27f4b2f335c4a518172c3.webp

          總體而言,我感覺(jué)還不錯(cuò),畢竟跟兩個(gè)大哥在比較。到這里我還是覺(jué)得不夠,跟其他框架比比呢!

          提交

          只要框架通過(guò)了測(cè)試,并且按照提交PR的規(guī)定提交,是可以被選錄到 js-framework-benchmark 中去的。

          好,那我們就去試試!

          946a8913cceedab8b2f0a115d9ba41fc.webp

          又一個(gè)比較有成就感的事!提交的PR被作者合并了!

          成績(jī)單

          我迫不及待的去榜單上看下我的排名,會(huì)不會(huì)墊底啊!

          因?yàn)闉g覽器版本發(fā)布的時(shí)差問(wèn)題,暫時(shí) Official results ( 官方結(jié)果 ) 還沒(méi)有發(fā)布最新結(jié)果,我們可以先來(lái) Snapshot of the results ( 快照結(jié)果 ) 中查看。

          我們打開(kāi)下方網(wǎng)址就可以看到JS框架的最新榜單了。

                
                https://krausest.github.io/js-framework-benchmark/current.html

          我們?cè)诔掷m(xù)時(shí)間這個(gè)類(lèi)別下從后往前找,目前63個(gè)框架我居然排名 50 名,并且大名鼎鼎的 React 排名45名。

          8f3afe157bd8a5749af2d37518c2655e.webp

          我們先不激動(dòng),我們?cè)倏聪聠?dòng)指標(biāo)類(lèi)別。Strve 平均分?jǐn)?shù)是1.04,我看了看好幾個(gè)框架分?jǐn)?shù)是1.04。Strve 可以排到前8名。

          92a8aa0b611666d7d348d8ad58e7ab35.webp

          我們?cè)俜€(wěn)一下,繼續(xù)看內(nèi)存分配這個(gè)類(lèi)別。Strve 平均分?jǐn)?shù)是1.40,Strve 可以排到前12名。

          84c3d05b3fe1efb0993cd6b4b518b889.webp

          意義

          js-framework-benchmark 的測(cè)試結(jié)果是相對(duì)準(zhǔn)確的,因?yàn)樗轻槍?duì)同樣的測(cè)試樣本和基準(zhǔn)測(cè)試情境進(jìn)行比較,可以提供框架之間的相對(duì)性能比較。然而,需要注意的是,這個(gè)測(cè)試結(jié)果也只是反映了測(cè)試條件下的性能表現(xiàn)。框架實(shí)際的性能可能還會(huì)受到很多方面的影響。 此外,js-framework-benchmark 測(cè)試結(jié)果也不應(yīng)該成為選擇框架的唯一指標(biāo)。在選擇框架時(shí),還需要考慮框架的生態(tài)、開(kāi)發(fā)效率、易用性等多方面因素,而不僅僅是性能表現(xiàn)。

          雖然,Strve 跟 React 比較是有點(diǎn)招黑,但是不妨這樣想,榜樣的力量是巨大的!只有站在巨人的肩膀上才能望得更遠(yuǎn)!

          Strve 要走的路還有很長(zhǎng),入選JS框架榜單使我更加明確了方向。我覺(jué)得做自己喜歡做得事情,這樣才會(huì)有意義!

          加油

          Strve 要繼續(xù)維護(hù)下去,我也會(huì)不斷學(xué)習(xí),繼續(xù)精進(jìn)。

          Strve 源碼倉(cāng)庫(kù):https://github.com/maomincoding/strve

          Strve 中文文檔:https://maomincoding.gitee.io/strve-doc-zh/

          謝謝大家的閱讀!如果大家覺(jué)得Strve不錯(cuò),麻煩幫我點(diǎn)下Star吧!






          瀏覽 29
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  加勒比在线精品视频 | 日韩精品免费一区二区三区夜夜嗨 | av无码av天天av天天啊 北条麻妃 无码 在线 视频 | 黄色大片视频 | 狼友视频官网免费 |