2025 年爬十億個頁面的成本

上禮拜看到的文章,作者在 AWS 上面只用 25.5 個小時就爬了 1B 個頁面,在 tune 過效能後的成本是 US$462:「Crawling a billion web pages in just over 24 hours, in 2025 (via)」。

作者在文章裡面有提到一篇 2012 年的「How to crawl a quarter billion webpages in 40 hours」,當時用了 39.5 個小時左右,花了 US$580 爬了 250M 個頁面:

For some reason, nobody’s written about what it takes to crawl a big chunk of the web in a while: the last point of reference I saw was Michael Nielsen’s post from 2012.

這次是純 HTML (沒有 JavaScript),在 2012 年的文章沒有特別提,應該也是沒有在管 JavaScript:

HTML only. The elephant in the room. Even by 2017 much of the web had come to require JavaScript. But I wanted an apples-to-apples comparison with older web crawls, and in any case, I was doing this as a side project and didn’t have time to add and optimize a bunch of playwright workers.

裡面有提到幾個有趣的問題,一個是 parsing 的部分其實很吃 CPU,會是瓶頸之一,主要的原因是現在頁面比 2012 年大許多了,中位數與平均數都大很多:

Profiles showed that parsing was clearly the bottleneck, but I was using the same lxml parsing library that was popular in 2012 (as suggested by Gemini). I eventually figured out that it was because the average web page has gotten a lot bigger: metrics from a test run indicated the P50 uncompressed page size is now 138KB, while the mean is even larger at 242KB - many times larger than Nielsen’s estimated average of 51KB in 2012!

他的解法是換 parsing library,從 lxml 換成 selectolax,效能有巨大的提升:

I switched from lxml to selectolax, a much newer library wrapping Lexbor, a modern parser in C++ designed specifically for HTML5. The page claimed it can be 30 times faster than lxml. It wasn’t 30x overall, but it was a huge boost.

另外一個就是 HTTPS 的 handshake overhead 了:

That said, one part of fetching got harder: a LOT more websites use SSL now than a decade ago. This was crystal clear in profiles, with SSL handshake computation showing up as the most expensive function call, taking up a whopping 25% of all CPU time on average, which - given that we weren’t near saturating the network pipes, meant fetching became bottlenecked by the CPU before the network!

Chrome 的 telemetry 可以看出來 HTTPS 的成長速度,這邊比較重要的時間點是 Let's Encrypt 在 2015 年十月的時候透過 IdenTrust 的簽名讓現有的瀏覽器支援 Let's Encrypt:

所以現在的硬體與技術對於 raw data 的取得已經不是太大的問題了 (甚至 2012 年的時候就已經是可行的了...)。

直接用 uBlock Origin 做 Always Active Window 的效果

本來是用 Always active Window (Always Visible) 這個套件,但發現常常失效,結果在 review page 上看到有人用 uBlock Origin 做到:

這邊的 aeld 其實是出自 Resources Library 的功能 addEventListener-defuser.js

Prevents attaching event listeners.

這邊要 apply 到所有站台的話可以用 *,所以會是這樣:

*##+js(aeld, /blur|visibilitychange/)

/blur|focus|afterblur|mousemove|visibilitychange/ 擋下去感覺有不少網站掛掉,先擋這兩個看起來還夠用,另外進階語法可以指定 html 元素,之後也可以參考。

Cloudflare 買 Astro

上個禮拜就看到 Cloudflare 買下 Astro 的消息了,雙方都有發新聞稿:「The Astro Technology Company joins Cloudflare」、「Cloudflare Acquires Astro to Accelerate the Future of High-Performance Web Development」。

目前官方的新聞稿上面是提到 javascript 對內容產業的缺點,而 Astro 補這塊:

Search engines prioritize fast-loading, clean pages, and consumers today expect seemingly instant load times from the web pages they visit. Websites that rely heavily on JavaScript for initial rendering often struggle to deliver this speed, hurting search rankings and customer conversions. With Astro, each web page loads only the most critical code that is needed to display a page in a browser. This makes Astro the preferred choice for building high-performance, content-driven websites optimized for speed.

雖然是這樣說,但不確定是不是 talent acquisition,因為想不太出來 Cloudflare 買下來的切入點...

jQuery 20 年,同步推出 4.0.0

jQuery 二十年了:「jQuery 4 (jquery.com)」,這邊提到的二十年是從 John Resig 當年在 BarCamp 上提出來的時間開始算的:

On January 14, 2006, John Resig introduced a JavaScript library called jQuery at BarCamp in New York City.

當年一堆 JavaScript 的 library 以及 framework 廝殺 (像是 prototype.js 以及 YUI),最後 jQuery 算是碾壓式的勝出,尤其是 John Resig 在寫文章說明效能改善的部分算是很棒的。

這次的 jQuery 4.0.0 另外一個重要的進展是把很多作古的瀏覽器支援拿掉 (像是 IE10,但還是支援 IE11),依照維基百科的資料,這次 minified size (還沒壓縮) 降到 78.8KB 了,這已經是 1.4 等級了 (76.7KB,1.5 版變成 83.9KB)。

這個大小以前 (2010 的時候) 都會說很肥大,還有不少替代方案 (像是 Underscore.js),但以現在用 MB 在算的 framework 來看跟本是小兒科。

在 Firefox 的 DevTools console 可以用 $$$('selector') 拉出包括在 shadow root 的元素

Mastodon 上看到 https://mastodon.social/@firefoxwebdevs/115847499973384654 這篇:

Mozilla 的官方的文件裡面有提到這些東西:「Web Console Helpers」,包括常用的 $ (類似 querySelector) 與 $$ (類似 querySelectorAll)。

$$$ 可以連同 shadow root 下的元素也一起找,就不用先找到 shadow root 元素再 querySelectorAll 了。

Fabrice Bellard 又弄了一套 JavaScript Engine,主打極低的記憶體用量

Lobsters 上看到 Fabrice Bellard 又生了一個 JavaScript Engine 出來:「MicroQuickJS」,主打極低的記憶體用量:

MicroQuickJS (aka. MQuickJS) is a Javascript engine targetted at embedded systems. It compiles and runs Javascript programs with as low as 10 kB of RAM.

上面支援的語法很少,但至少實作 ES5 大多數的規格,這應該是考慮到可以用 Babel 轉出來:

MQuickJS only supports a subset of Javascript close to ES5. It implements a stricter mode where some error prone or inefficient Javascript constructs are forbidden.

效能上有提到跟他自己寫的另外一套 QuickJS 算是能拿出來比較 (這邊註明一下,QuickJS 有支援到 ES2023),我猜應該就是堪用的程度,考慮到記憶體很少的 embedded system 速度大概也不快,要有預期用比較複雜一點的套件還是會慢的前提:

The speed is comparable to QuickJS.

yt-dlp 發佈支援 JavaScript runtime 外掛的版本了

先前在「yt-dlp 為了解 YouTube 的 challenge,要引入 JavaScript runtime 了」提到 yt-dlp 在開發透過 JavaScript runtime 解 YouTube challenge 的事情,現在推出第一版可以吃 JavaScript runtime 外掛的版本:「[Announcement] External JavaScript runtime now required for full YouTube support (via)」。

從文章的說明看起來支援好幾套 JavaScript runtime,最常見的應該還是 Node.js,另外居然支援 QuickJS?是因為 API 好接嗎...

升級到 2025.11.12 後試著拉了兩個影片,看了一下訊息沒看到 js 相關的,也許之後再看看...?

yt-dlp 為了解 YouTube 的 challenge,要引入 JavaScript runtime 了

看到「[Announcement] Upcoming new requirements for YouTube downloads #14404 (via)」這個消息,yt-dlp 也走到需要 JavaScript runtime 解 challenge 的這一步了...

看起來目前是選用 Deno 處理 JavaScript 的程式碼,這邊的貓抓老鼠進入到另外一個層級了...

一般使用者應該是不會有太多影響 (理論上 Deno 會隨著下載的包裝裡面附上),主要是對打包的人比較麻煩 (像是各家 package manager 以及 CI/CD 的流程)。

Tailwind Plus 支援純 JavaScript 的版本

Hacker News 上的「Vanilla JavaScript support for Tailwind Plus (tailwindcss.com)」這邊看到的,原文在「Vanilla JavaScript support for Tailwind Plus」。

Tailwind Plus 前身叫做 Tailwind UI,今年改名的:「Tailwind UI is now Tailwind Plus」,是個付費的套件,對於很多元件沒有特別要求的情況下可以直接套來用。

因為互動的關係,會需要 JavaScript 的程式碼,而以往會配合 framework 的設計所以會有列出支援的 framework (像是 React 或是 Vue),現在則是支援 vanilla JavaScript。

付費項目會特地去支援 "legacy" technology 應該是有市場需求... 應該是很多付費使用者希望也可以在老專案裡面用的呼聲?像是萬年不死的 jQuery...

不使用前端 JavaScript 架構架設網頁的方式

前幾天 JavaScript broke the web (and called it progress) (via) 這篇在 Hacker News 上有一些討論。

作者在抱怨現在的前端 JavaScript 框架最主要的目的是 DX (Developer experience),而且會發現代價是犧牲了 UX (User experience),以及帶給 Architecture 與 DevOps 更複雜的事情。

我想說看一下目前不使用 JavaScript 架構前端網頁的方式 (另外一方面也在玩最近很熱門的 Claude Code),我把寫出來的東西丟到 GitHub 上的 https://github.com/gslin/test-cc-20250621,這邊用 Express.js + EJS 去搭。

先嘗試了幾個與 CSS 相關的部分,首先是常常被罵,但大家還是很愛用的 Tailwind CSS,可以利用 command line 指令去掃出來有用到的 class,然後生成固定的 css 檔案掛到業面上,所以靜態類的 class name 看起來都沒問題。

第二個是 icon 的需求,我一開始是找到 Font Awesome,可以搭配 Tailwind CSS 放大:

<i class="fas fa-home text-2xl"></i>

後來另外也有找到 material-icons 這些選擇可以用,看起來方法都類似,都是透過 css 的 class name 掛 before element。

第三個是 hot reload 的需求,我測了 browser-sync 算是還 OK?

這樣看起來 DX 其實都有接近目前前後端分離框架提供的等級,不過如果前端需要各種 UI component 的話,需要回頭去看以前的各種元件,像是已經進入 maintenance mode 的 jQuery UI?(2021 的時候寫過:「jQuery UI 與 jQuery Mobile 進入維護模式」)

目前想到比較明顯的缺點應該會是在支援 mobile app 的時候,app 需要呼叫的 API 就要另外開發,但這樣也降低了 API 內垃圾資料的大小 (這邊指的是,因為 app 與 web 的 user story 不同,在同一隻 API 回傳中,有些資料只有 web 會用到,以及有些資料只有 app 會用到)。