JavaScript Weekly #468 - 2019/12/20

Tesseract.js 2.0 颯爽登場

作者另外有寫一篇 Medium 文章解釋 2.0 的內容。

為什麼需要這次改版

  • performance 瓶頸
  • 失敗後難以 debug,找不到原因

更新內容

  • 用新的 emscripten 升級到新的 core
  • 更好懂的 API
  • 支援排程,可以同時跑很多個 OCR 工作
  • 加入 TypeScript 定義檔
  • 重寫文件

新 API 讓你可以提早載入訓練資料,需要使用的時候不用等太久:

const { createWorker } = require('tesseract.js');
const image = 'https://tesseract.projectnaptha.com/img/eng_bw.png';
const worker = createWorker();
let isReady = false;
// Called as early as possible
(async ()=> {
  await worker.load();
  await worker.loadLanguage('eng');
  await worker.initialize('eng');
  isReady = true;
})();
// Do other stuffs
(async (image) => {
  if (isReady) {
    const { data: { text } } = await worker.recognize(image);
    console.log(text);
  }
});

CPU 資源足夠的情況下,用 scheduler 多開 woker 可以巨幅加快辨識速度:

const { createWorker, createScheduler } = require('tesseract.js');
const image = 'https://tesseract.projectnaptha.com/img/eng_bw.png';

const scheduler = createScheduler();

(async () => {
  for (let i = 0; i < 4; i++) {
    const w = createWorker();
    await w.load();
    await w.loadLanguage('eng');
    await w.initialize('eng');
    scheduler.addWorker(w);
  }
  const rets = await Promise.all(Array(10).fill(0).map(() => (
    scheduler.addJob('recognize', image);
  )));
  console.log(rets.map(({ data: { text } }) => text));
  await scheduler.terminate();
})();

State of JavaScript 2019 問卷結果

這邊只挑覺得有趣或意外的部分來講,請搭配頁面中的圖表觀看。

調查人口

  • 大家薪水好多 😠
  • 9 成答卷者是男的 www
  • 職稱「全端工程師」占最多,真是辛苦大家了
  • 看完 CSS ProficiencyBack-end Proficiency 發現原來答卷仔高手雲集

總覽

時間變化圖簡直就是大型掉粉現場 😂

  • 有些今年才出來的只有一個點
  • 從不掉粉仔筆記一下,列入觀察重點

    • Express
    • Jest
    • GraphQL
    • Apollo
    • Storybook
    • Next.js
    • TypeScript

滿意度跟使用率這個部份我覺得首要還是看滿意度,感覺比較能反映出發展性。

  • 70% 以上的看起來都前途不可限量
  • Ionic 意外地落在 AVOID 區…

語言特性

雷聲大雨點小大型展示會。

不過看起來蠻符合我想像中的模樣,沒什麼意外的點。

真要說的話,原來這麼多人用 fetch 的嗎…

axios 才是標配吧= =

整體感覺還是新東西不推出個 3、5 年,是很難廣泛的被採用的。

JavaScript 加強版們

Languages that compile to JavaScript

基本上我是覺得除了 TypeScript 以外,大概都還是會保持小眾。

這個 branch 的很多比較,我都看不出什麼關聯性,484 我太笨了…

當年的老夥伴 CoffeeScript 已經被擺到「其他」裡 😅

前端框架

React 還是最秋的,那我就放心了 (誤)

我在想這問卷如果拿來台灣做不知道有沒有機會被 Vue.js 翻盤…

資料層

等等,apollo 不是跟 graphql 站同邊的嗎?

Relay 相對不夠親民,熱度比較低是可以想的到的。

偷渡一下,我覺得 MobX 是真滴好用,尤其 5.0 以後丟掉了一些過去的包袱,已經可以說是完全體了。

後端框架

  • express 大神還是大神
  • Next.js 只能說現在的 SSR 需求實在是不小,自己搞又非常麻煩…
  • Gatsby 體驗還是算不錯,雖然有一些些限制但瑕不掩瑜

測試

完了,真D沒空寫。

不過好像我有稍微用過得還算不少 ㄎ

  • jest 的聲勢大概就跟 React 綁一起的,不太意外,也確實好用
  • cypress 超級推,E2E test 戰鬥力直接爆表
  • storybook 因為我不是什麼嚴謹的 component 人,沒有在用
  • enzyme 我不懂它往下掉的原因是什麼…

明年的前排應該會加上 react-testing-library 了,畢竟它今年漲得實在不少。

Kent 大大太神啦!

手機/桌機 app

  • reactnative 知名度竟然超過 electron XD
  • ionic 一種跟 cordova 一起沉淪感 (所以才推出自己的 capacitor 吧)

我目前有點看好 Flutter (被歸在「其他」裡面了),Flutter 用畫的解決了很多問題(這樣真的好嗎)。而且除了開發 native app,觸手還伸到了 Web 這邊來,可謂是充滿了野心。

相信明年份的調查,Flutter 也會站到前排了吧!

其他工具

加減看看。

Moment 這麼大包竟然還是蠻受歡迎的…

新知來源

看起來我常用的站也有上榜,好家在。

W3Schools 真的是屹立不搖 www

Podcats 倒是真的沒有在聽。

看法

pass

頒獎典禮

是說我怎麼覺得 Svelte 是因為作者比較會引戰所以才得到這麼高的注目…

Polymer 系的也都蠻屌的,不過不太會宣傳這樣。

結論

被 Sporky 騙到,還去 google 了一下,結果是瞎掰的 library。

寫 JavaScript 真是太棒了!

CNDJS 維護團隊(Cloudflare)的真情告白

Cloudflare 團隊想要告訴大家,現在他們相當努力的在保持 CDNJS 的運作及更新。

簡短的介紹 CDN 之後,提到了現在 CDNJS 為什麼是在掛在 cdnjs.cloudflare.com 底下。

眼看當年就要因為流量爆炸被迫關站(付不出錢),CDNJS 團隊聯絡了 Cloudflare,希望他們能夠幫忙。而 Cloudflare 也答應了,於是就出現了 cdnjs.cloudflare.com,而且還不收錢喔 😉

總之接下來的時間一切安好,CDNJS 也不停地繼續壯大(月流量 3PB),不過也因為瀏覽器的獨立 cache 機制,蒙上了一小層陰影: CDN 是不是變得沒什麼卵用了?

一個月前,一直以來負責自動更新 CDNJS 上套件版本的 bot 掛了,那是一個開源專案,然後作者現在已經沒空修了,開源真是太棒了 👍

歷經一番波折之後,現在變成是由 Cloudflare 團隊接手維護 CDNJS 專案了(從下游變成上游),因為他們知道 CDNJS 的重要性。

如果你也對 CDNJS 有熱情,歡迎貢獻一己之力參與討論

如果最近有打算開始做什麼新專案,不如就用 CDNJS 吧!

Cloudflare 團隊向你保證,CDNJS 就是穩到不行 💪

高手都是這樣用 console.log

好像久久就會看到一次類似的文章,不過每次都會多一點點新東西 XD

我想直接看文章最後這個總結的 gist 就好囉!

void 在現代 JavaScript 下的生存之道

在這個 ES6 以後 arrow function 當道的時代,過氣的 void 運算子總算找到了自己的新用法。

先看一下 MDN 上對 void 運算子的介紹

The void operator evaluates the given expression and then returns undefined.

於是文章作者提出了搭配 arrow function 的用法:

在把 arrow function 寫成單行的時候,可以用 void 來達成 return undefined 的效果

這個用法是建立於 想要寫單行的 arrow function,卻不想要 return 任何東西 的情境下。

文章裡面舉了幾個例子,順便還提到了在某些 ESLint config 裡面有包了 no-void 這個 rule,而看起來確實也有人不想要它被內置在裡面。

Vue 3.0 的設計概念

作者現身說法 Vue 3.0 本著什麼樣的理念在設計的。

基本出發點就是先考慮「誰在用」、「怎麼用」,於是衍伸出了需要同時兼顧「好上手」又具有「可延展性」。

好上手 vs 可延展性

簡單的概括有提到的例子:

  • CDN build -> 菜雞
  • Vue CLI -> 狠角色

😅

  • Options API -> 菜雞
  • Composition API -> 狠角色

😅

  • JavaScript -> 菜雞
  • TypeScript -> 狠角色

    • cons: learning cost
    • cons: slower initial development

這邊說到 Vue 3.0 用 TypeScript 寫只是為了有效提供強力的 IDE hint,因為希望保持好上手、容易維護的本質。3.0 用 JavaScript 或是 TypeScript 寫出來的 Vue component code 會長得差不多。

😅

  • Template -> 菜雞
  • JSX -> 狠角色

Templates allows us to get better performance

由於使用 template 寫法可以給 compiler 更好的 diffing 捷徑,不需要走過整個 tree,Vue 3.0 使用 template 的寫法可以得到更好的效能。

力量越大、包越大

其實這 part 也是延續上一 part 的概念,但切入的角度不同,所以我就把它們分開來寫了。

用不上的功能就不要包近來:

  • ES module export + tree shaking
  • 連 template 寫法裡用上的內建 component,也是透過 complier 自動 import

接著就提到了有點接近於 library vs framework 的議題,這段整理的不錯,所以我打算寫詳細一點。

舉 React 當作 low-level 的範例:

優點

  • 起始概念少
  • 選擇很多 -> 生態蓬勃/造成困擾
  • 從維護角度看,React 開發團隊只需要專注於 library 本體

缺點

  • 需要自己想辦法解決較複雜的問題
  • 約定成俗的規矩沒有寫在官方文件 (e.g. Redux)
  • 生態系動得太快,third-party library 容易被丟包 (open source 萬歲)

接著舉 Ember.js, Angular 做為 framework 範例:

優點

  • 大部分問題的解法都內建
  • 整個生態系不太會有丟包的問題,大家是一起動的

缺點

  • 起手門檻高
  • 內建的問題解法不適用的時候,做得不夠有彈性的話,會無法解決特殊問題
  • 因為包太多東西,想要做大改動比較困難 (e.g. 像 Angular 1 想要大改就掛了)

Vue 想要走的道路是 Progressive

(秀出那張圖,你知道哪張)

  • 分層的功能設計
  • 低起手門檻
  • 官方(文件)有提供常見問題解法

Vue 3 也會保持這個理念,你有需要,在學/用就好。

開放 low-level API 帶來更多彈性

官方提供詳細的 low-level API 用法:

  • 自定 renderer
  • 開放 compiler 使用

TypeScript 的 const assertion

沒在用 TypeScript 也可以大概了解它的作用。

TypeScript 在判斷型別的時候是相當嚴謹的。

一般情況下你用 const 來宣告 literal Object 或是 literal Array 的時候,就算你本意沒有要改變它們內容的意思,對 TypeScript 來說它們的型別沒有辦法被推定到接近 enum 那種的定值。

文中用的例子是 HTTP request 的 method,這邊寫精簡一點只留下四大天王:

const HTTPRequestMethod = {
  DELETE: "DELETE",  // type: string
  GET: "GET",
  POST: "POST",
  PUT: "PUT"
};

// 此動作不會有 type error
HTTPRequestMethod.DELETE = "TIMON";  // type: string

// 正因為可以進行這個操作,
// HTTPRequestMethod.DELETE 才沒有被推定為 "DELETE" type

那麼使用新的 const assertion,就可以達到接近 enum 的效果:

const HTTPRequestMethod = {
  DELETE: "DELETE",  // type: "DELETE"
  GET: "GET",
  POST: "POST",
  PUT: "PUT"
} as const;  // <- 加在這邊

// Error: Cannot assign to 'GET'
// because it is a read-only property.
HTTPRequestMethod.DELETE = "TIMON";

同樣在 literal Array 上也適用,有把 Array 變成 Tuple 的效果:

const ORIGIN = [0, 0] as const;
// 等於 const ORIGIN: readonly [0, 0] = [0, 0]

至於為什麼不乾脆用 enum 就好了?因為 enum 就是 TypeScript 額外帶來的東西,有些工程師會希望雖然寫的是 TypeScript,在可能的範圍還是盡量接近 JavaScript。

實際上 TypeScript 的 enum 在 compile 過後也就是 JavaScript Object 這樣。

var HTTPRequestMethod;
(function (HTTPRequestMethod) {
    HTTPRequestMethod["DELETE"] = "DELETE";
    HTTPRequestMethod["GET"] = "GET";
    HTTPRequestMethod["POST"] = "POST";
    HTTPRequestMethod["PUT"] = "PUT";
})(HTTPRequestMethod || (HTTPRequestMethod = {}));

Preact 華麗復活

Preact 初心主打做為短小精悍版的 React 其實相當成功,畢竟容量實在省下太多了…

Fast 3kB alternative to React with the same modern API.

React 會這麼大當然是有原因。React 建立了一套自己的 SyntheticEvent 系統,它把瀏覽器的事件系統打包並經過正規化,提供給了 React 及 React 使用者一些彈性。而 Preact 會小是因為它直接使用瀏覽器的 Event 系統,整整少了一大包。

但從一個 React 使用者的角度,Preact 要吸引你過去當然還是要更大的誘因,畢竟 Preact 小包的前提是它能使用的 API 有限,並且不完全與 React 相容。於是,Preact 團隊推出了 preact-compact,做為銜接 React 使用者的橋樑,只要引入它就可以相容幾乎全部的 React 語法與各種現成的 React component。

前言講完了(挖靠講這麼多才講完前言),可以進入正題啦!

Preact 的這套做法有成功吸引到一群使用者,當年 Addy Osmani 君在講 PWA 的時候也有推過,畢竟容量小 94 屌。

但 React 在進入了版號開放年代(就是 0.15.x -> 16.x)之後,功能爆炸性成長,加上 Fiber 架構的改動,Preact 在功能追趕上面漸漸顯露出疲態

其實我一度覺得 Preact 要涼了。

現在 PreactX (版號10.x) 推出就是 Preact 回歸的一劑強心針:

  • Fragments
  • Hooks
  • componentDidCatch
  • createContext

然後他們也認清了 Preact 終究是離不開 preact-compact 這個 package,於是直接把它併入 preact package 裡面去了,之後只要 import React from 'preact/compact'; 就可以使用囉!

React 近年的爆炸性發展真的是很難跟上… Preact 真是辛苦你了。但如果每每都需要等 Preact 跟上才能使用 React 新功能的話,我想 Preact 使用者大概會漸漸跳回來吧…

之前我光等 react-apollo 官方支援 hooks 就望眼欲穿了 😫

阿 Svelte 不是很邱?

這是一篇超長的 React vs Svelte 戰文,本文作者是支持 React 那邊的。

他在看完 Svelte 官網跟 Svelte 社群發的文章之後,忍無可忍(?)跳下來開戰。

主因是 Svelte 太愛帶風向了 😆

列舉了兩個帶風向的大分類,作者都用自己的角度給予反擊。這邊我建議大家對 Svlete 跟 React 有些瞭解之後再來詳細看作者的論述。

  • React 最愛重繪了
  • 根本不需要什麼 vDOM

接著提了 Svelte 隨著時間可能可以解決的弱點:

  • TypeScript 支援
  • 還不夠成熟,相關 package 太少

最後收尾直接嘴爆:

Despite above described limitations, I think Svelte actually brings up an invaluable idea. Yes, you cannot fully express a modern app through templates without sacrificing flexibility and code reusability.

To be honest, I don’t believe Svelte in its current form can defeat React and conquer the world.

Svelte 風向仔下去~

最後段也有稍微提到一下 code 可讀性的問題,文章作者是 JSX 派的,那麼我想對 Svelte 的不喜歡應該是從一開始就埋在骨子裡了 😎

畢竟他可是愛 JSX 愛到從 Vue 跳到 React 呢!