Svelte 筆記(2):編譯器比你聰明多惹

愷開愷開撰寫
💡

如果想問問題或單純回饋的話可以填寫表單

目錄

    今天跑去看 Svelte 原始碼,摸熟架構的同時順便看看有沒有什麼簡單的 issue 可以拿來練手。然後看到了這個 — emits warning

    雖然我覺得以這個 issue 的描述來看,沒有 href 的 a tag 應該是不合法的才對(至少不符合 a11y),後來我去查了一下,在 StackOverflow 上有提到目前的規範有些不統一的地方。

    但基本上 href 可以是空的,只是在這種情況下就不要用 a 而是考慮用 button 之類的標籤取代,這樣對 screen reader 比較友善。

    後來我去看了一下 eslint-plugin-jsx-a11y,發現這個 eslint 會去幫你判斷 href 是否為合法值,裡頭非法值有:

    <a onClick={foo} /> // 可以用 button 取代
    <a href="#" /> // 只有 # 沒有 id
    <a href={"#"} /> // 字面值
    <a href={`#`} /> // 字面值
    <a href="javascript:void(0)" /> // 不應該用 javascript:void(0)
    <a href={"javascript:void(0)"} /> // 字面值
    <a href={`javascript:void(0)`} /> // 字面值

    還有 href 為空的情況:

    <a />
    <a href={undefined} />
    <a href={null} />

    Svelte 會幫你檢查基本的 a11y,像是 missing href 或是 href value invalid 等,因為 Svelte 本身有先過一層編譯器,所以檢查都會在編譯階段做:

    // compiler/compile/nodes/Element.ts
    // L425
    		if (this.name === 'a') {
    			const attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
    
    			if (attribute) {
    				const value = attribute.get_static_value();
    
    				if (value === '' || value === '#') {
    					component.warn(attribute, {
    						code: `a11y-invalid-attribute`,
    						message: `A11y: '${value}' is not a valid ${attribute.name} attribute`
    					});
    				}
    			} else {
    				component.warn(this, {
    					code: `a11y-missing-attribute`,
    					message: `A11y: <a> element should have an href attribute`
    				});
    			}
    		}

    在這個階段,svelte 幫你把語法變成了語法樹(AST),所以檢查起來也很方便。

    不過定睛一看,咦? javascript:void(0) 的 case 好像沒有處理到,目前只會針對 value 為空跟 # 的情況做處理。所以就順手加了一行檢查: if (value === '' || value === '#' || /^\\W*javascript:/.test(value))Pull Request 了。

    另外紀錄一下比較麻煩的是 svelte 現在只會針對值是 is_static 做檢查,所以像是:

    <a href={undefined} />
    <a href={null} />
    <a href={`#`} />
    <a href={"javascript:void(0)"} />
    <a href={`javascript:void(0)`} />

    因為 {} 裡都是 Expression svelte 檢查不到(會直接把 is_static 標記成 false)。想要檢查的話就要另外針對這些 Expression 做處理,有空(黃金週也快到了)再一次全部修修看。

    感覺不是什麼很有用的功能啦,反正是在編譯階段做也不會影響到 bundle size,現在越來越覺得編譯器這條路感覺是行得通的耶,喜歡用什麼樣的方式寫自己決定,反正 compile 完變成 JavaScript 就好。

    雖然這也不是什麼新想法,像是 LiveScript 或是 Elm 等等,或多或少都是這樣的概念,但我覺得 Svelte 能夠被大家注意到(或比較容易被使用)的原因在於它保留了大部分的 JavaScript 語法,template 學習成本幾乎是 0(如果你會 React 或 Vue),寫起來就像 HTML, CSS, JavaScript 寫在一起的 Vue 而已。

    另外就是 svelte 的 Reactive 機制和動畫控制,這些東西是常常是前端在實作頁面時需要特別考慮的,也是其他編譯器沒辦法提供的。大家都想要 Functional Programming,但實際上如果沒有解決到開發者真正的問題,那麼也只是少數愛好者的執念而已。

    如果覺得這篇文章對你有幫助的話,可以考慮下面的連結請我喝一杯 ☕ 可以讓我平凡的一天變得閃閃發光 ✨

    Buy me a coffee