深度解讀字節跳動Web Infra發起的 Modern.js 開源項⽬

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"7⽉,字節跳動 Web Infra 做過⼀次主題爲 "},{"type":"text","marks":[{"type":"strong"}],"text":"《邁⼊現代 Web 開發(字節跳動的現代 Web 開發實踐)》"},{"type":"text","text":" 的分享,在分享中他們梳理了「傳統前端技術棧」的典型組成部分,展示了其中每個部分都存在的瓶頸問題。也介紹了在這些問題的驅動下,業界正在發⽣從「傳統 Web 開發範式」到「現代 Web 開發範式」的「範式轉移」。在這個分享的最後預告了 Modern.js 開源項⽬。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"10 ⽉ 27-28 ⽇舉辦的 "},{"type":"text","marks":[{"type":"strong"}],"text":"稀⼟開發者⼤會"},{"type":"text","text":" 上,字節跳動 Web Infra 正式發起 "},{"type":"link","attrs":{"href":"https:\/\/xie.infoq.cn\/article\/33788df9613aef714809f08af","title":"xxx","type":null},"content":[{"type":"text","text":"Modern.js "}]},{"type":"text","text":"開源項⽬。在專場分享《介紹 Modern.js——"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s?__biz=MzUxMzcxMzE5Ng==&mid=2247510615&idx=1&sn=3f6d6098e6e1f906e6b0c54247d9aba1&chksm=f9521f14ce259602d4410c3129dd72448881cdf7c2b21bbd9c9da1ec69a973ac38c36004bb00&scene=27#wechat_redirect","title":"xxx","type":null},"content":[{"type":"text","text":"現代 Web ⼯程體系"}]},{"type":"text","text":"》中,⾸先介紹了業界和字節內部的前端開發、 Web 開發在發⽣哪些影響深遠的變⾰,從這些變⾰的⻆度,展示了基於 Modern.js 的現代 Web 開發。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"這些變⾰包括:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"更多「前端開發者」成爲「應⽤開發者 \/ 產品開發者」"}]}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先討論了什麼根本因素在驅動這種轉變,\"Frontend Focused\" 的意義,指出服務器端開發⻔檻不斷降低的⻓期趨勢、原有基建的缺陷,⽤ Modern.js 演示了「⼀體化、⽆服務器化的全棧開發」、「以客⼾端爲中⼼的 Web 開發」"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從「前後端分離」到「前後端⼀體化」"}]}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分析了「前後端分離」產⽣的兩種前端項⽬,爲什麼其中⼀種是「假分離」,另⼀種「不完整」,⽤ Modern.js 演示了「前後端⼀體化」在哪些地⽅帶來改變"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Meta Framework 取代傳統「前端三劍客」"}]}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分析了四代「前端三劍客」,以及每⼀代都被下⼀代的成員「吞併」的規律,結合字節內部的 真實案例,講解了 Meta Framework 的⻆⾊"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"形成基於「前端技術」的成熟 GUI 軟件研發體系"}]}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先明確了「前端技術」的定義, 結合 Modern.js 的功能和設計,討論瞭如何實現「充分抽象」,才能 解決 DX 和 UX 的⽭盾"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"智能化、平臺化、低碼化"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來系統介紹了 "},{"type":"text","marks":[{"type":"strong"}],"text":"Modern.js 的六⼤要素"},{"type":"text","text":",包括:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"普及:現代 Web 開發範式"}]}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"回顧了這種範式的 9 ⼤主要特徵"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"核⼼:現代 Web 應⽤(MWA)"}]}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從 Universal App、⼀體化、應⽤架構、Runtime API 這四個⻆度來了解 MWA。"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在應⽤架構部分介紹了 Modern.js 中 Model 的設計和背景"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"內置:前端⼯程最佳實踐◦ 列舉了⼏個典型的最佳實踐,包括 Post-Webpack Era 的新⼯具趨勢、Modern.js 的 Unbundled 開發,Modern.js 推薦的「CSS 三劍客」,Modern.js 微前端項⽬跟直接使⽤ Garfish 的微前端項⽬對⽐、模塊⼯程⽅案和 Monorepo ⼯程⽅案中的最佳實踐。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"包含:Web 開發全流程"}]}]}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"演示了 Modern.js 在「編碼」環節的微⽣成器功能、在「調試環節」的微前端調試"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"提供:⼯程標準體系"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⿎勵:定製⼯程⽅案"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"末尾介紹了除已經發布的開源項⽬,還有哪些對現代 Web 開發者有幫助的事情在發起和推進中。介紹了 Modern.js 當前⾼優的社區計劃。"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"分享實錄"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⼤家好,我是來⾃"},{"type":"text","marks":[{"type":"strong"}],"text":"字節跳動 Web Infra"},{"type":"text","text":" 的宋振偉,在字節跳動,我們部⻔負責打造和發展「Web 技術中臺」和「前端研發體系」。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/40\/40622193d107ab32eecc86cd4d28d9ce.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"今年 7⽉,我們做過⼀次主題是 "},{"type":"text","marks":[{"type":"strong"}],"text":"《字節跳動的現代 Web 開發實踐》"},{"type":"text","text":" 的分享,在分享中我們梳理了 「傳統前端技術棧」的典型組成部分,展示了其中每個部分都存在的瓶頸問題。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ad\/ade4c4b471d7a7ced40be78584520bb0.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也介紹了在這些問題的驅動下,業界正在發⽣從「傳統 Web 開發範式」到「現代 Web 開發範式」的 「範式轉移」。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個分享的最後也預告了 "},{"type":"text","marks":[{"type":"strong"}],"text":"Modern.js"},{"type":"text","text":" 開源項⽬。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/2f\/2f410668eb7967cb386814dce2fcab0a.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"昨天上午的主題演講中,字節跳動正式發佈了 "},{"type":"text","marks":[{"type":"strong"}],"text":"Modern.js"},{"type":"text","text":"。今天的專場分享,我想結合字節內部的變⾰和實踐,介紹基於 Modern.js 的現代 Web 開發,和所帶來的實際效果。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"議程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"今天的分享可以分成三個部分。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"昨天的主題演講有說到,整個業界和字節內部的前端開發、Web 開發,都在發⽣着影響深遠的變⾰,我們⾸先從這些變⾰的⻆度,看下基於 Modern.js 的現代 Web 開發是什麼樣⼦,有什麼區別。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後,我們整體看下 Modern.js 有哪些要素和收益。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後再看下除了已經發布的開源項⽬,還有哪些對現代 Web 開發者有幫助的事情在發起和推進中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們先來看"},{"type":"text","marks":[{"type":"strong"}],"text":"第⼀部分「現代 Web 開發」"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"⼀、基於 Modern.js 的現代 Web 開發"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1. 更多「前端開發者」成爲「應⽤開發者 \/ 產品開發者」"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/60\/600532d2cee74317f20bfd5e9352ee7b.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以從這五個⽅⾯的變⾰,來展示「現代 Web 開發」是什麼樣⼦。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這五個變⾰之間是承前啓後的關係。⾸先最根本的推動⼒,不是來⾃技術側,不是前端開發者⼀廂情願的發展⾃⼰主觀的技術偏好,⽽是在互聯⽹和 IT ⾏業、市場需求、⽤⼾產品這⼀側的⼤趨勢,需要更多「前端開發者」成爲「應⽤開發者」或「產品開發者」,⿎勵和倒逼着技術領域,不斷產⽣更有利於這種需求的技術形態和基礎設施。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當傳統技術範式遇到瓶頸,不再能進⼀步適應需求,就會發⽣「範式轉移」,出現從⼀開始就針對這種需求重新設計的、新⼀代的技術範式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種轉變推動前端技術領域出現了「從分離到⼀體化」、新⼀代「前端三劍客」的變⾰。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種變⾰帶來的新⼀代技術標準和基礎設施,開始形成完全基於「前端技術」的成熟 GUI 軟件研發體系,並且進⼀步朝着平臺化、低碼化的⽅向發展。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"\"Frontend Focused\" 的意義"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/e1\/e15b91e59755987cd5d74892bfd0bc1b.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們剛纔⼀直在說「前端」,「前端」這個概念似乎⼀直是隻有開發者才關⼼的技術細節,但最近⼏年,卻變成了商業領域、投資機構也都很關⼼的事情,全球市場上湧現出越來越多的新⼀代雲平臺和研發⼯具產品,多數都涉及前端研發特有的需求和模式,其中還有很多像 Vercel 這樣明確「專注於前端」的產品。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像幻燈⽚上這張圖,雲計算和研發產品最初是從最接近機器的底層開始發展,從虛擬化,到容器編排,到基於容器技術的各種平臺化、服務化的研發⼯具形態,這個階段是後端技術主導的,整個趨勢 是越來越向上層發展,越來越接近市場和商業價值最終所在的地⽅——也就是⾯向⽤⼾的產品,因此 必然會發展到前端技術主導的抽象層,讓應⽤開發和產品開發能更專注於⽤⼾需求,⽽越來越不需要關⼼服務器端的複雜性和專業技術細節。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/04\/04f8dcf51254bc02e575a113b5a40022.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以市場需求會趨向於推動應⽤開發⽅式往「專注於前端」的⽅向的發展,專注於前端就是專注於用戶,⽽專注於⽤⼾是多數企業、產品的根本利益所在。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"最⼤的開發者羣體"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/fa\/fae5429a5359a525fbc0c7114df71eff.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"另⼀⽅⾯,從進⼊移動互聯⽹時代開始就不斷⼤幅增加的應⽤開發需求,現在不但沒減弱,反⽽還在加強,⽐如幻燈⽚上 IDC 的預測,要滿⾜這麼龐⼤的應⽤開發需求,傳統開發⽅式和⼈才儲備是很不夠的,需要讓儘可能多的開發者能獨⽴、完整的開發這些應⽤,⽽前端技術棧的開發者,正是最⼤的開發者羣體和技術社區。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以在用戶、產品、市場這⼀側,⼀直有趨勢和壓⼒,需要更多「前端開發者」成爲「應⽤開發者」 或「產品開發者」,⿎勵和倒逼着技術領域,不斷產⽣更有利於這種需求的技術形態和基礎設施。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"服務器端開發⻔檻不斷降低"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/59\/597362cda7d9c96eec5219cf7258dcbb.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這種客觀趨勢的推動下,基於 Web 技術的應⽤開發中,服務器端的佔⽐和⻔檻⼀直在不斷下降, 國內⼤⼚的中臺建設,提供了⼤量不跟特定客⼾端捆綁、專注於數據需求和底層業務邏輯的 API,讓 產品開發更聚焦在上層的客⼾端業務邏輯。還有 BaaS 和基於雲函數的後端雲 Serverless,也進⼀步降低服務器端的⻔檻,讓前端開發者能更獨⽴的、端到端的完成產品開發。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但要進⼀步降低⻔檻,提⾼效率,這些基礎設施的⼀個缺陷就暴露出來,就是他們都把應⽤依賴的 API,放在應⽤項⽬之外維護,跟前端研發是割裂的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有⼀個缺陷是它們不解決 API 之外的服務器端需求,⽐如路由、SSR 等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有⼀個字節內部的典型例⼦,前端開發者在⾃⼰實現的 SSR 項⽬中,始終⽤ HTTP ⽅式請求外⽹域 名的 API 來獲取數據,導致 SSR 頻繁超時,HTML 響應慢嚴重影響⽤⼾體驗。可以給前端開發者做培訓,讓他們具備⾜夠的服務器端開發思維和知識,知道要在 SSR 環節切換成內⽹的請求⽅式,還要考慮緩存機制等,但更根本的解決⽅法是屏蔽這種服務器端問題和實現細節,⾃動處理這些問題。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"⼀體化、⽆服務器化的全棧開發"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1e\/1e037cca4a0ad5305998b52bf383b3a5.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此服務器端⻔檻不斷降低的趨勢,⾃然會發展到「⼀體化、⽆服務器化的做全棧開發」的階段,讓前端開發者直接開發 「接近純前端的項⽬」⽽不是 「Node.js 框架項⽬」,感覺就像沒有服務器⼀樣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"幻燈⽚上是這次分享中第⼀個 Modern.js 的 demo, 左側是⼀個 Modern.js 應⽤項⽬的完整⽬錄結構,src\/ ⽬錄下的應⽤主體,可以像調⽤普通函數⽂件⼀樣訪問 api\/ ⽬錄下的 BFF 函數,不需要了解網絡細節,Modern.js 會⾃動基於 BFF 函數的路徑、參數等⾃動⽣成 REST API,在 CSR 過程中⾃動請求。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/fa\/fa5a49fa7b273106dc7bf223e4a6a226.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來我們在 package.json 的 modernConfig 配置⾥啓⽤ SSR、「差異分發」和「⾃動 Polyfill」,可以看到這些功能不要增加代碼邏輯,只需要靜態開關配置。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/34\/34df14d1609db4d61be89b558c51d8af.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"構建後,幻燈⽚左側可以看到產物⾥的 HTML 和 JS 都有 es6 和 es5 兩個版本,⽤⼾訪問時應⽤的時候,Modern.js 的 Web Server 會根據瀏覽器 UA 選擇分發 es6 版本還是 es5 版本,也就是「差異化分發」。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"右邊上⾯的圖是現代瀏覽器的訪問結果,不會返回任何 polyfill 代碼, 下⾯的圖是低版本瀏覽器的訪問結果, Web Server 會⾃動提供這個 UA 需要的 polyfill 代碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到 Modern.js 不但⽀持⼀體化的開發 BFF,也滿⾜ BFF 之外的服務器端需求,儘可能⾃動利⽤⾃帶的 web server 去做性能優化和提供產品級的兼容性,同時開發體驗仍然是⽆服務器化的。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/e9\/e9482ee4e3562d6858b81a39d65dd9d4.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之前我們啓⽤了 SSR, 左側圖上⾼亮的 HTML ⽚段,已經包含了通過 BFF 請求到的數據,會根據應⽤運⾏的⽅式⾃動選擇最⾼效的請求⽅式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種⾃動優化不會阻礙開發者對技術細節的掌控,右邊這張圖展示了 BFF 函數也會⽣成標準的 REST API,可以⼿動調⽤。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"以客⼾端爲中⼼的 Web 開發"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9d\/9db8a7487817ca54164213016aa952fa.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種⼀體化、⽆服務器化的全棧開發進⼀步發展,⾃然會得到⼀種客⼾端爲中⼼的 Web 開發⽅式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⽐如在傳統 Web 開發中,要實現常⻅的權限識別和重定向,除了前端⻚⾯的邏輯,還需要在服務器端的路由中,添加實現跳轉的業務邏輯。⽐如圖上,在訪問 home ⻚⾯的時候根據 cookie 的值決定 要不要重定向到登陸⻚⾯。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/d0\/d04738e7d3a59fc7088c443c0fc4745c.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同樣的需求,在以客⼾端爲中⼼的 Web 開發⽅式中,可以⼀體化的在客⼾端代碼⾥實現,⽐如前⾯已經啓⽤ SSR 的 Modern.js 項⽬,只需要添加 Redirect 組件,就可以實現和剛纔完全相同的權限識別和重定向效果,訪問⻚⾯時會根據 cookie 決定要不要返回 302 狀態碼。整個實現過程是客⼾端思維的。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0c\/0cc493376fb440ccf3218535eb32f627.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以客⼾端爲中⼼,不代表不能掌控服務器端,不能直接寫服務器端業務邏輯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果已經習慣 Node.js 框架的開發⽅式,可以 server ⽬錄的鉤⼦⽂件⾥,對框架⾃帶的 Web Server 添加⾃定義邏輯,⽐如⾃由添加中間件,可以在這個局部,⽤⾃⼰熟悉的傳統 Web 開發⽅式實現權限識別和重定向。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2. 從「前後端分離」到「前後端⼀體化」"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Web 項⽬的技術棧也在轉變,相當於是先發展出「前後端分離」,然後⼜⽤新⽅式迴歸了 「前後端⼀體化」。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"「前後端分離」"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/fe\/fee12f45cdd725fa12456fbcdf3d6eb5.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以前的 Web 開發就像圖上這個 Ruby on Rails 項⽬,粉⾊的前端代碼,「寄居」在 "},{"type":"text","marks":[{"type":"strong"}],"text":"綠⾊的"},{"type":"text","text":" 後端 Web 框架項⽬中的,前端和後端會互相⼲擾互相拖累,做⼯程建設也⽐較⿇煩。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/69\/6968937d4f8ebdcde67ac676772aeac8.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之後 Web 開發普遍轉變到「前後端分離」的模式,分離後的前端項⽬和後端項⽬,都傾向特定的類型。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"後端項⽬不傾向包含 Web 的功能,⽽這時的前端項⽬可以歸納爲兩種類型。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/bf\/bfd469d6110960ed01a5394da108bd22.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MERN 這種項⽬類型相當於⼜回到了分離前的狀態,整個項⽬是基於 Node.js 框架的,前端被嵌在⾥ ⾯。這種結果其實反映出「前後端分離」實現的更多是分⼯上的分離,⽽不是技術架構上的分離,在技術架構上仍然沒有擺脫以服務器端框架爲中⼼的 Web 開發。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/a1\/a1d7af80b611febc6beb3977b6337a3a.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從 MERN 項⽬的結構可以看到,它不但是假分離,⽽且也不算⼀體化,React 代表的前端部分和 Node.js 框架代表的後端部分,在項⽬⾥是涇渭分明的,沒有真正融合到⼀起去。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使⽤ Node.js 框架的項⽬,多數屬於這個類型。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/88\/88518c5a942fb5650d72e6884f38da6e.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"「前後端分離」模式中另⼀種前端項⽬類型,我們稱作「⽼⼀代 JAMstack」,這種類型沒有假分離問題,就是純粹的前端項⽬。可以實現 SPA 和 MPA,也能基於編譯⼯具實現 SSG(靜態⽹站⽣成)。靠靜態託管來運⾏,⿎勵在 CSR 中調⽤ API 滿⾜動態的應⽤需求。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/93\/93683ec42d3f4908483174310772cf8c.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"「⽼⼀代 JAMstack」最⼤的問題是,雖然分離成了獨⽴的項⽬,卻不⾜以承擔完整的應⽤開發,只能產出靜態⽂件,依靠外部的 Web 服務器去運⾏,⽆法實現 SSR,三⼤組成部分⾥的 API,也需要 在項⽬之外,⽤雲函數、獨⽴後端項⽬等⽅式來實現,不能跟着項⽬⼀起迭代。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⽤ CRA 或直接⽤ webpack 搭建的項⽬,多數屬於這個類型。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"「前後端⼀體化」"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/5a\/5a1eadfc5490d4e600300d880b1b25da.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在前⾯說的需要更多「前端開發者」成爲「應⽤開發者」的背景下,新⼀代的 JAMstack 項⽬⽤「客⼾端爲中⼼」的「前後端⼀體化」⽅式,解決了上⾯說的問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"新⼀代 JAMstack 的三⼤組成部分雖然沒變,對應的內容卻有很⼤變化,JS 部分更加函數化和組件化、以 JS 爲中⼼,HTML 可以完全不在項⽬中出現,⾃動⽣成。BFF API 變成項⽬⾃包含。和之前簡單的靜態託管相⽐,基於前端 Serverless 平臺可以實現 SSR、SPR 等動態能⼒,即使是靜態⻚⾯,也可以獲得很多好處,⽐如前⾯展示的 「差異化分發」。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1d\/1ddb2ac9ab97663615e0890690959b81.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖上是⽤ Modern.js 的 demo 來展示新⼀代 JAMstack 項⽬。在開發中只需要聚焦在 JS 代碼上,不 論是 SPA 還是 MPA,HTML 都是⾃動⽣成的。不論是 SSR 渲染的代碼,還是 API 邏輯,構建之後按照規範輸出到 dist 下的不同⽬錄,構建產物規範是 Serverless 友好的,⽀持把 Web、SSR、BFF 等 拆分成不同服務器。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/56\/566a17da30207af5851e9178beb7fe55.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前⾯提到 Modern.js 傾向於 JS 爲中⼼、⾃動⽣成 HTML。但不阻礙開發者⾃⼰掌控 HTML。圖上是 Modern.js 渲染 HTML 的默認模板。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/cd\/cd76939101e24dbf98c73888b7423d04.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⼀體化 BFF 的調⽤,在前⾯的例⼦演示過,這⾥可以看到 BFF 函數的⽂件路徑是有約定的,可以實 現任意設計的 REST API。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0f\/0f2b3e01d789e6ca8532958dda4e1ec8.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"構建產物會針對 BFF、Web、SSR 分別⽣成獨⽴可運⾏的 Server,這是對前端 Serverless 平臺更友好的,Serverless 平臺可以⾃主選擇讓 BFF、Web、SSR ⽤不同⽅式在獨⽴進程中運⾏,不會互相⼲擾。⽐如在 SSR 環節遇到 app 代碼的的內存泄露導致 SSR 超時,Web Server 不受影響,可以⾃動降級到 CSR 模式,返回靜態的 HTML 給⽤⼾作爲兜底,⽤⼾的 HTML 請求始終不會超時或掛掉。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9b\/9b1abad2099c22d7e0b150e6b9aac1e2.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於 SSR,同樣可以前後端⼀體化的開發,圖⾥⾼亮的 useLoader 函數中的代碼,同時適⽤於 SSR 和 CSR,如果這個 Loader 在 SSR 中已經預加載,CSR 就會⾃動跳過,否則會執⾏。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/64\/64c15cc5df8566df3c4483469e51f4e8.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SPR 相當於有緩存機制的 SSR,在 Modern.js ⾥也可以⼀體化的開發,只要使⽤這個預渲染組件。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/5a\/5a647984ff415cb0029f0cde9785b546.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SSG 實際上就是在編譯時運⾏的 SSR,在 Modern.js ⾥只要配置 SSG 路由,就會⾃動啓⽤這種編譯邏輯,給路由⽣成靜態 HTML。CSR、SSR、SSG 都是⽤同⼀份代碼。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3. 新⼀代「前端三劍客」和 Meta Framework"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了在技術棧層⾯向「前後端⼀體化」轉變,在⼯程層⾯,傳統的「前端三劍客」也在轉變成元框架這種新的⼯程基建。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"傳統「前端三劍客」"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9e\/9e5b9f16afc148e9bdf5bf50fbeb2b7d.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先來回顧下傳統的「前端三劍客」,第 1 代和第 2 代如圖上所示,也被⼤家熟知。⽽第 3 代「前端 三劍客」由視圖框架、Node.js 命令⾏、Node.js 框架三個⽅向組成。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ac\/acce2eb03192e8d3f74684a7f55d7679.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中 Node.js 命令⾏代表了⼯程化,其中最典型的是像 Webpack 這樣的打包⼯具,以及 Babel、 PostCSS 這樣的編譯⼯具。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"視圖框架和 Node.js 框架很好理解,就是之前討論的 MERN 項⽬中的前端和後端部分。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"第 4 代「前端三劍客」"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/77\/77a85cb2b5f5ad8e6ab71549a2c93737.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隨着現代 Web 開發範式的發展,第 4 代「前端三劍客」的輪廓已經越來越明顯,由元框架、前端 PaaS、低代碼三個⽅向組成。其中低代碼⽅向在昨天晚上稀⼟⼤會的低碼專場已經介紹過,⽽ Modern.js 就屬於元框架這個⽅向。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/6a\/6aecce87eb95763fc9565b6be9abfbff.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從這張圖可以清楚的看到,每⼀代前端三劍客中,都有⼀個⽅向,把上⼀代前端三劍客完整包含在⾃⼰⾥⾯,變成不需要太關⼼的底層,讓⾃⼰取代他們成爲前端開發的新地基。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第 3 代中的視圖框架,就扮演這樣的⻆⾊,把第⼆代的 HTML、CSS、JS 封裝在⾃⼰⾥⾯,⽽第 4 代中的元框架,⼜對視圖框架、Node.js 框架、Node.js 命令⾏做了整合和抽象,成爲前端開發和⼯程建設性起點,元框架扮演了過去 Webpack、React 扮演的⻆⾊。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1b\/1bb9cef94e87cc45e67a48d5b4f7ed7f.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這張 JS 框架的 S 曲線圖,也能體現這種轉變。在左邊這個時期,發展的前沿、開發的起點,都是 React、Vue、Svelte 這樣的視圖框架,新的視圖框架項⽬也層出不窮。現在已進⼊右邊這個時期, 前沿收斂到基於 React 發展更上層的元框架。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/57\/57b76044cbcce095d220e7723ad52a1b.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 作爲現代 Web ⼯程體系,是由元框架組成的,提供三⼤⼯程類型,⿎勵開發者基於⼯程類型建設⾃⼰的業務⼯程⽅案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以字節內部的「⽕⼭引擎⼦應⽤⼯程⽅案」爲例,初始化的⽬錄結構沒有什麼變化,只在配置中默認加載了⾃⼰的框架插件,插件中通過 server 提供的 hook 修改渲染後的 HTML ,在原來的 HTML 上套了層殼,也就是右下⻆截圖中⽕⼭引擎統⼀的頂欄和左側導航欄。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣建設出來的⼯程⽅案,既能滿⾜垂直場景的需求或⾃⼰的偏好,⼜能保持跟三⼤⼯程類型的兼容,⾃動獲得 Modern.js 的能⼒和收益"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4. 基於「前端技術」的成熟 GUI 軟件研發體系"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在「前端開發者」成爲「應⽤開發者」的⼤背景下,技術棧、⼯程基建的發展,開始形成基於「前端技術」的成熟 GUI 軟件研發體系。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"什麼是「前端技術」"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/97\/97d6744707c6f0f8353b03f762a5bb3e.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先明確⼀下我們⼀直說的前端技術,不是指做 UI 的技術,⽽是由 Web 原⽣語⾔、Web Runtime、 Web 技術⽣態組成的技術棧,不是隻在瀏覽器⾥纔有前端技術,⽽是有 Web Runtime、有 Web 語⾔的地⽅,就有前端技術。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"DX 和 UX 同樣重要"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ff\/ff431d6be0c5d84c3cd4387398f7b8ec.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"傳統前端開發不是成熟的軟件研發體系,缺乏⾜夠的抽象和基建,導致 DX 和 UX 始終存在⽭盾,此消彼漲。以往的產品開發中,習慣更重視 UX,這有兩⽅⾯的原因,⼀來是因爲產品是由產品主導,因此更重視 UX,不會過多關注開發者體驗,再就是缺乏⾜夠的抽象和基建,導致 DX 和 UX 之間必須犧牲⼀個。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在新⼀代更成熟的研發體系的⽀持下,已經可以實現 DX 和 UX 的同時最⼤化了,也從「更重視 UX」 轉變爲「DX 優先」的⽅式。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/5c\/5c90479e7b87c426a76053025390e204.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要實現 DX 和 UX 的同時最⼤化,需要充分的抽象。⽐如前⾯提到的 Modern.js 的這個例⼦,項⽬⾥只有三個⽂件,就具備全⾯的能⼒,包括⾃動 Polyfill、差異化分發、SSR 等,既具備產品級的 UX,有保持了 DX 的簡單、開箱即⽤等。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"充分抽象"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/d3\/d3f7a24e39c4a29f41caf9f8922fc406.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要實現充分抽象,需要讓項⽬從基於「庫、⼯具」發展成基於「框架」,這兩者的區別在圖上表現的 ⽐較好。藍底⽩邊部分是項⽬開發者⾃⼰寫的代碼。左邊是傳統前端項⽬,由開發者⼿寫整個應⽤, 把庫和⼯具當做積⽊來組裝,填補項⽬⾥的空⽩。⽽右邊是 Modern.js 項⽬,整個應⽤是框架本⾝,開發者⼿寫的代碼,是按照框架的要求填充到框架預留的位置上。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/a1\/a11eeaaa96c832fcdc161bca3e4fd8f1.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要實現充分抽象,也需要在儘可能多的環節實現最⼤化的抽象,圖上體現了 Modern.js 除了像常規 的框架⼀樣,在運⾏時和編譯時做抽象,也會在 IDE 編寫代碼的環節,和部署產物的環節,引⼊最⼤化的抽象。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/2d\/2d986645d6b6109df055ca4fd1278780.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要實現充分抽象,也需要解決前端模板的問題,Modern.js 把各種研發場景、項⽬類型,收斂和標準 化成了始終固定的三個⼯程類型,其中「應⽤」⼯程⽅案,也就是 MWA,⽀持所有需要部署和運⾏的項⽬,「模塊」⼯程⽅案⽀持所有需要實現代碼復⽤的項⽬。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"5. 智能化、平臺化、低碼化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 代表的現代 Web 開發,也在繼續朝着智能化、平臺化、低碼化的⽅向發展。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/e5\/e5721f9edab76ca4aa35bf152aedecc6.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"智能化⽅⾯,當前可⽤的功能,是⽤ Modern.js 的初始化⼯具創建的項⽬,會開箱即⽤的在 VSCode ⾥做好配置,啓⽤⼏千條規則組成的 ESLint 全量規則集,加上按最佳實踐內置在 ESLint ⾥的 Prettier,期望儘可能多⾃動修正問題,⽽不是僅僅提示問題。也追求儘可能多的讓 IDE 負責⽣成真正的源碼,讓開發者⼿寫的代碼變成跟 IDE 溝通的語⾔。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/5e\/5e55e32441eb59a8751352ac7959dbce.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在平臺化⽅⾯,Modern.js 的⽬標之⼀就是形成「⼯程標準」,讓各種前端 PaaS 平臺可以圍繞標準實現⾼級能⼒,⽐如圖上粉⾊部分列出的產品級 Web Server、差異化分發、SSR 兜底、ESR、微前 端等,都需要結合代碼層⾯的⼯程標準。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/24\/24818f38648a9ef23ea32b12c83dfaf2.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了部署運⾏環節⽅⾯的平臺,有了⼯程標準之後,研發環節也可以引⼊更多低碼提效。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⽬前我們內部使⽤的研發平臺,可以直接在圖形界⾯上簡單操作完成項⽬的創建、開發、部署。圖上右側可以看到圖形界⾯上展示了當前項⽬的的狀態: ⼊⼝數量、項⽬配置等,藍⾊框內添加應⽤的⼊⼝,⼀鍵從 「單⼊⼝」 轉變爲 「多⼊⼝」 。右側在 Web IDE 中也能看到 src ⽬錄結構下的變化。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9a\/9a5c745061634ea2dccbde1d43db37b8.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"低碼化有兩個⽅向,⼀個是剛纔說的跟研發⼯具結合,另⼀個就是研發從某些⼯作中解脫出來的低碼搭建,昨天的低代碼專題中有介紹。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/75\/7529d83aea44c4b73fa20294e711b0d6.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到⽬前爲⽌,我們從這些變⾰的⻆度,展⽰了很多 Modern.js 的 demo 和效果。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"⼆、Modern.js 的六⼤要素"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來我們系統的看⼀下 Modern.js 是什麼,Modern.js 提供了什麼。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1. 普及:現代 Web 開發範式"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/c8\/c85df9859485bd459b8560e1a510dfce.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以⽤這六⼤要素來說明 Modern.js 。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⾸先這個項⽬是希望能推動現代 Web 開發範式的普及,發展完整的現代 Web ⼯程體系,突破應⽤開發效率的瓶頸。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1d\/1d3f98e9762cd4d2bd0d300ee473b7fe.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前⾯討論「現代 Web 開發」的時候,已經展示過這種範式的 9 ⼤主要特徵。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中 Serverless 範式、平臺化、低碼化這三個特徵,在當前版本的 Modern.js ⾥還沒什麼體現,需要後續會跟⼀些平臺配合提供。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2. 核⼼:現代 Web 應⽤(MWA)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"繼續看第⼆個要素。Modern.js 三⼤⼯程類型中最核⼼的就是 「現代 Web 應⽤」,簡稱 MWA,或 直接叫「應⽤」。"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"從 Universal JS 到 Universal App"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前⾯提到過,「應⽤」⼯程⽅案⽀持所有需要部署和運⾏的項⽬,把這些項⽬收斂成⽤同⼀套框架、 同⼀套約定、同⼀套模板、同⼀套架構、⼀套 API 來開發。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"反過來,我們也可以從 Universal App、⼀體化、應⽤架構、Runtime API 這四個⻆度來了解 MWA。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/b9\/b94281e787d774194a78cc4967d31370.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Universal JS 指同⼀份 JS 代碼,既能在瀏覽器端運⾏,也能在服務器端運⾏,Universal App 是它 的進⼀步發展,同⼀份 App 代碼可以在不同環節運⾏,也可以⽤不同的模式來運⾏。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1c\/1c7a2ffd8ea438dcc8aa7485f301cf70.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⾸先是常⻅的 MPA 和 SPA 的需求,本質上是「服務器端路由」和「客⼾端路由」的需求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 Modern.js ⾥它們可以隨意組合。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們之前的例⼦都是單⼊⼝應⽤,只需要把 App.tsx 組件、pages ⽬錄這樣的⼊⼝標識放到 src 的⼦ ⽬錄⾥,就能變成多⼊⼝的 MPA,會⽤⼊⼝名⾃動⽣成服務器端路由,⽐如圖上的 admin-app 和 landing-page 兩個⼊⼝。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這兩個⼊⼝也分別都是 SPA,根據⼊⼝標識不同,⼀個使⽤基於組件的客⼾端路由,⼀個使⽤基於⽂件系統的客⼾端路由。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/3e\/3e24bb6e1c9b5d2a6c03684d37630d09.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後是⽀持「動靜⼀體」。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前⾯展示過⼀個靜態的、CSR 的項⽬如何直接開啓 SSR、SPR、SSG 功能。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 也⽀持 CSR 和 SSR\/SSG 混⽤,⽐如圖上右側紅⾊⾼亮部分會在服務端渲染到 html 中, 藍⾊區域的⽇期時間,在 CSR 階段動態展示在⻚⾯上。也就是整體 SSR + 局部 CSR。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"整體 CSR + 局部 SSR 的能⼒後續會加⼊。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/5b\/5b0f4e4ce2e645cbd848bf6e27756c75.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 BFF ⽀持⽅⾯,Modern.js 中還提供了類型友好的⽅式,可以通過 Type Schema 實現運⾏時⾃動 校驗接⼝的參數和返回值。⽐如右下⻆請求時,參數 text 類型爲 number 時,response 中會⾃動提示相應的錯誤。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/db\/db54fb44b71bcf75d078c4122c8046cd.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後 Modern.js 還⽀持不同類型的應⽤開發,上圖就是之前例⼦中介紹 Web 開發模式。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/b6\/b664b19e5ed67ae0ed1a8d427ec79168.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後是不同的運⾏模式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"微前端在 Modern.js 中是原⽣⽀持的,底層解決⽅案是 Web Infra 之前開源的 Garfish 微前端解決⽅案。⼀個 MWA 可以隨時變成微前端主應⽤,在配置中指定⼦應⽤列表的加載地址,Modern.js 就會 ⾃動在 Web Server 中預加載⼦應⽤數據,注⼊到運⾏時,在 Runtime API 的幫助下,可以像普通 React 組件⼀樣使⽤⼦應⽤。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MWA 也可以分別作爲獨⽴的 Web 和微前端⼦應⽤的運⾏和部署。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/22\/2272a97e618ee5dc6a714a2ed9354025.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MWA 在啓用 Electron 支持之後,能作爲桌⾯應⽤來運⾏,項目裏會新增 electron ⽬錄用於寫主進程相關代碼。除了開箱即⽤的 Electron 構建等能力,也提供運⾏時 API ⽀持 Electron 的常⻅需求和最佳實踐,進⼀步提升開發效率。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"前後端⼀體化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第⼆個看待 MWA 的⻆度是 「前後端⼀體化」。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/69\/69f8659bc1ea90cdf80c426f74007af6.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之前的例⼦只展示了⽤ BFF 函數,api\/ ⽬錄下每個⽂件就是 BFF 路由,當服務器端邏輯更重的時候,可以增加 Node.js 框架元素,⽬前⽀持了 4 種不同的框架,還可以⾃⼰開發 Modern.js 插件⽀持更多框架。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/82\/82950e9b9f2c040edfe9ab6be8c76a87.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前⾯提到過,以客⼾端爲中⼼,不代表不能掌控服務器端,不能直接寫服務器端業務邏輯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"⽐如前⾯提到的⽕⼭引擎⼯程⽅案的例⼦,除了⽤框架插件,也可以在項⽬⾥創建 server ⽬錄和鉤 ⼦⽂件,添加修改 HTML 渲染結果的邏輯。在框架插件⾥和直接在項⽬下定製 Server,能⼒是對等的。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ac\/ac2c10c92557a543dcf8f1c79109c247.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在只有 src ⽬錄,或有 api ⽬錄的情況下,MWA 類似 JAMstack 項⽬。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果增加了 server 等鉤⼦⽂件的情況下,MWA 像傳統 Node.js App ⼀樣能直接寫服務器端業務邏 輯,使⽤ Node.js 框架插件、中間件等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果刪掉 src ⽬錄,MWA 就是⼀個純 REST API 的項⽬。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們把這三種模式之間的隨意遷移,稱作「三位⼀體」。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"應⽤架構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來看下應⽤架構⻆度。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1b\/1beb5d61fc800090be51fcbfd749faf0.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"傳統 Web 開發中的應⽤架構,等同於服務器端應⽤架構,前端部分的架構要麼缺失,要麼需要項開發者⾃⼰摸索、搭建,缺乏 API ⽀持和⼀致的抽象,難以跨項⽬復⽤業務邏輯。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/cc\/cc76800eebad81dfb6fd9d9d148bb245.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MWA 提供的開箱即⽤的、客⼾端爲中⼼的應⽤架構。類似圖上那樣,可以⽤標準化的 Runtime API,輕易實現 React 開發中⽋缺的 Model 層和 Controller 層。Model 作爲封裝 UI ⽆關業務邏輯的積⽊,跟 UI 組件⼀樣可以復⽤和組裝。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0b\/0bc1e923d1e05644ea8f7c7ec435dfa5.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之前 Web Infra 舉辦的 React 核⼼開發者在線訪談⾥,Redux 作者 Dan 提到,狀態管理最重要的是理解狀態的類型,根據需要處理的狀態是什麼種類,來選擇對應的⽅案。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/fb\/fbfe9a245e84db53a79e9ea380338b4d.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常⻅的狀態管理⽅案,都有適合的狀態類型和場景,很多時候需要混合使⽤,⽽不是⼀把錘⼦錘所有釘⼦,要麼所有狀態都放到全局應⽤狀態⾥,要麼所有狀態都在局部狀態⾥。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/d8\/d8db4d50321048d77165144f7d62b286.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很多開發者不⽤ Redux,是因爲 Redux 本⾝只能算底層 API,需要手動創建和維護store,業務邏輯被reducer,action等分散在不同的地方,提高了維護成本。其實 Redux 社區⼀直有解決⽅案,比如 Ducks Modular 設計模式會把業務邏輯聚集在⼀起,Redux官方支持的主流庫RTK也爲解決這樣的問題而生。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 的 Model 基於 Redux 進⼀步提⾼抽象程度,保留了 Redux 在不可變數據、數據流等⽅⾯ 的收益,對整個 Redux ⽣態兼容,讓使⽤和不使⽤ Redux 的開發者都能受益。⽀持多種狀態類型,也⽀持不同的 Model 寫法。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Runtime API 標準庫"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後看下 MWA 的 Runtime API 標準庫。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/88\/8884b47b79e788c393b5240d31332e00.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這套 API 相當於對「應⽤」層級的基礎 API,不⽌能在 MWA ⾥使⽤,在 Modern.js 的模塊⼯程⽅案⾥,同樣可以使⽤這些 API,開發可復⽤的業務組件,⽀持獨⽴調試和測試。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖上最上⾯藍⾊⽅塊是業務開發中常⽤的 api,⽐如 useLoader,useModel 等 API。中間橙⾊部分 就是前⾯提到定製 server 需要⽤到的 API, 最底下就是我們的插件 API,可以擴展框架、定製⼯程⽅案。右側也提供了⼀些⼯具函數 API, ⽐如⽤於代碼分割的 loadable API。最右邊 測試相關的⼯具 API 保證了 runtime 不論在應⽤、模塊還是 API 服務中 都可以進⾏單元測試和集成測試。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/9f\/9fd628ffa4c1faf2469cf4b0ec497946.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當應⽤中的組件需要拆分成獨⽴的模塊復⽤時,使⽤的 Runtime API 怎麼辦,還能繼續調試、測試嘛,答案是肯定的,這套 API 相當於「應⽤」領域的 API 標準庫,不⽌能在 MWA ⾥使⽤,在 Modern.js 的模塊⼯程⽅案⾥,同樣可以使⽤這些 API,開發可復⽤的業務組件,⽀持獨⽴調試和測試。上圖右側是模塊⼯程的⽬錄結構。左側 TableList 組件中使⽤了 useLoader API,調試時只需要 提供對應的 story ⽂件,模塊⼯程⽅案⽀持我們在 storybook 調試⽤到了 Runtime API 的組件。測試⽤例也是⼀樣⽀持。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"3. 內置:前端⼯程最佳實踐"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於第三個要素,簡單列舉⼏個 Modernjs 內置的前端⼯程最佳實踐。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Post-Webpack Era"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/2c\/2c402493ace03c79a5c2706c3aa8a6c0.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"傳統前端⼯程建設都是基於 Webpack 的配置封裝, Webpack 不論是配置還是速度的問題,⼤家應該都有⽐較深的感受, 但是從去年開始業界湧現很多新的⼯具,完全不涉及 webpack,⽐如 snowpack、 vite、wmr、等等,有⼈把它稱爲 JS 第三紀元。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/ff\/ff42cad9a7c5b05c1d6eb0538a5698e5.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從第三紀元開始, esbuild 、swc 這種編譯打包⼯具使⽤⾮ JS 的系統編程語⾔開發,顯著提⾼構建速度。編譯時間的縮減也意味着不打包,按需編譯的 ESM 場景可以實現, Snowpack、Vite 這樣的⼯具就是在 esbuild 的基礎上實現的開發者體驗優先的不打包開發調試模式。在 Modern.js 中不打包的模式⽬前已經被⽤於公共庫的構建、業務項⽬的開發調試等真實場景。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/1d\/1dcce366545cacb0a685bdc59bc4c3b4.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 中也內置類似 Snowpack、Vite 的不打包開發調試模式,左側啓⽤該功能之後,運⾏效果就像圖上右側那樣,開發服務器在秒級啓動。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/7b\/7b052c41af56232971827739b57c6431.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼可以做到速度這麼快?主要是因爲業務代碼只有在請求時使⽤ esbuild 按需編譯,第三⽅依賴⾃動從 Goofy PDN 加載已經預編譯好的產物。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"CSS 最佳實踐"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/fa\/faea89bd781250cb0785532fb12552a8.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 CSS 開發⽅⾯,Modern.js 默認推薦圖上「CSS 三劍客」搭配使⽤,有需要也可以開啓 LESS\/SASS 等預處理器和 CSS Modules ⽀持。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"默認零配置、樣板⽂件最⼩化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/48\/483a41f0d221a85167458660475705d7.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"和以前把功能作爲樣板⽂件塞到項⽬⾥相⽐, 現代 Web 開發範式下的最佳實踐要求默認零配置的,同時樣板⽂件儘可能簡潔最⼩化。之前我們也通過例⼦看到 Modern.js 項⽬⼿動創建⾮常簡單,只需要應⽤根組件和 package.json。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跟直接使⽤ Garfish 開發微前端⼦應⽤的項⽬做對⽐,上圖可以看到直接使⽤ garfish 的項⽬,需要⼿動運⾏ Garfish 框架、處理公⽤模塊、路由等邏輯。除了運⾏時,還需要編譯環節⾃定義⼀⼤堆配置。直接使⽤還是有⼀定的成本。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/21\/21c402ae313dd1c250aeaa1870db2f61.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 Modern.js 中使⽤微前端,之前的例⼦已經說過,只需要在 web 應⽤的基礎上啓⽤微前端功能, 提供⼦應⽤列表即可,每個⼦應⽤加載後就是組件、路由可以⾃⼰靈活組織。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"構建產物規範"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/56\/564fe5436b7b50dcf1dbcf8b546a7ab6.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 的模塊⼯程⽅案,會並⾏編譯出多種符合社區主流規範的構建產物。模塊的編譯也是不打包的,更容易引⼊速度更快的⼯具⽐如 esbuild、swc 等。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Monorepo ⼯程⽅案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/43\/43737d9a0ad22fe9e378fe7532da883a.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"應⽤和庫如果分散在不同項⽬開發的話,通過 link 調試也⽐較⿇煩,業界的主流⽅案就是 monorepo, Modern.js 本⾝就是基於 pnpm monorepo 開發的,同時也將這部分最佳實踐收斂到 monorepo ⼯程⽅案。初始化的 monorepo 默認使⽤pnpm,左側是他的⽬錄結構,apps 對應的是 MWA 應⽤ 、features\/packages 對應是可復⽤的模塊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"右側內部模塊指的是不會發布到 npm、僅在當前倉庫下復⽤的庫。它本⾝不需要構建,同倉庫下的應⽤直接使⽤它的源碼即可。monorepo 我們也提供了 new 命令,可以選擇創建應⽤或者模塊。"}]},{"type":"heading","attrs":{"align":"center","level":5},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"更多"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/64\/644c26681e684df0db82eb16d64c3fb9.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了上⾯提到的⼀些最佳實踐,Modernjs 還提供了單元測試、集成測試、Visual Testing 等、ESlint 全量規則集等最佳實踐。這⾥不⼀⼀展開介紹。可以在⽂檔上了解和使⽤。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4. 包含:Web 開發全流程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modernjs 不僅是上⾯介紹過的 運⾏、構建、調試等⽅⾯,本⾝包含了 Web 開發全流程。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/33\/334d6fda179701a69d493de05f1e351b.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在編碼環節,也可以通過微⽣成器啓⽤某個功能或者添加⼊⼝,從 SPA 到 MPA, 和前⾯提到的通過研發平臺「低碼提效」類似,還可以像圖上那樣在項⽬⽬錄下執⾏ new 命令選擇要啓⽤的功能。這個命令會⾃動重構我們的代碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過微⽣成器按需⾃動啓⽤的⽅式,可以放⼼的將⼀些功能作爲插件提供,也可以控制 Modern.js 初始化項⽬的體積。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/a3\/a38d3a208ea3fc7f2447939c6082f446.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在微前端⼦應⽤開發時,通常情況下主應⽤已經部署上線了,這時候開發⼦應⽤就需要結合線上的主 應⽤⼀起調試,之前的⽅式通常是通過全局代理⼦應⽤ js 到本地,⽐較⿇煩。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 中只需要主應⽤像右下⻆那樣啓⽤ DEBUG 模式,之後打開主應⽤線上鏈接,在 header 中設置需要開發的⼦應⽤信息,server 會⾃動替換注⼊到 html 中的⼦應⽤列表數據。這樣也就可以讓線上主應⽤加載本地⼦應⽤。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/fa\/fa9538aa50f2170f9eb58ff25188bc4b.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在運⾏環節,傳統的 Web 開發模式,通常是沒有提供⽣產環境運⾏項⽬的⽅式,MWA 項⽬本⾝⾃ 帶產品級的 Server,⾃⼰就能產品級的運⾏⾃⼰,⽐如圖上的⾃動 Polyfill 服務。之前也提過,結 合 serverless 平臺,可以⾃動做⼀些優化。也可以在本地運⾏模擬⽣產環境的效果。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"5. 提供:⼯程標準體系"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 不只是⼀個現代 Web 應⽤開發框架,⽽提供了整套現代 Web ⼯程體系。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/8b\/8b20477c3d207aee6d86cdb5c8da4e59.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前⾯已經介紹過,我們將前端開發中涉及的場景收斂到 3 種,就是圖上應⽤、模塊和 monorepo。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不僅解決了業務模板數量爆炸的問題。融合後的⼯程類型,⽐如 MWA 不是多個場景簡單疊加,導致 ⼯程變的⼤⽽全,通過抽象可以做到很輕量,也能更容易交付⼀些之前不好實現的功能。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"6. ⿎勵:定製⼯程⽅案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js ⿎勵業務結合⾃⾝場景定製垂直的⼯程⽅案。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/15\/1570826d1f8dd5bb5f554ac36b10f3b7.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像前⾯提到的⽕⼭引擎例⼦⼀樣,封裝插件、微⽣成器、定製出⾃⼰的業務⼯程⽅案。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/8e\/8ee7fac86d6d8eacb8472df252d8aea7.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關於 Modern.js 六⼤要素的更多解釋和例⼦,可以在官⽹上看到。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"三、Modern.js 社區和現代 Web 研發體系"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後我們⼀起看下除了已經發布的開源項⽬,還有哪些對現代 Web 開發者有幫助的事情在發起和推進中。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/c9\/c90333e9b6060dc4ad6d91ac4cab504a.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 開源項⽬現在是剛起步的狀態,昨天上線的官⽹,以及最新發的 1.0 版,都是公測狀態, 還需要更多意⻅、測試和實踐,希望⼤家多參與社區建設。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Modern.js 的起點是字節內部的現代 Web ⼯程體系項⽬,現在⼤部分代碼已經完全轉到 Github 上開發,⼯作流還在建設中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雙⽉計劃、每週計劃、缺陷管理等,也都會全⾯轉到 Github 上公開推進。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當前版本還沒有包含 Roadmap 上⼀些重要功能,希望儘量以每週發版的節奏,把這些功能補上。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/19\/198239775bf6082dfecdb99785b7bd88.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"昨天的分享介紹了 「現代 Web 研發體系」中的其他部分,這些部分⼏乎也都算的上是 Modern.js 的 重要功能,後續會陸續對外開放,歡迎⼤家關注。"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/fc\/fcd2b8a9a5704266a42451d013008290.webp","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後,屏幕上右下⻆⼆維碼是 Modern.js 官⽹的地址,可以在官⽹上通過快速上⼿和實戰教程瞭解 更多 Modernjs 的細節使⽤部分。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"謝謝⼤家。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"官⽹:"},{"type":"link","attrs":{"href":"https:\/\/modernjs.dev\/","title":"xxx","type":null},"content":[{"type":"text","text":"https:\/\/modernjs.dev\/"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Github:"},{"type":"link","attrs":{"href":"https:\/\/github.com\/modern-js-dev\/modern.js","title":"xxx","type":null},"content":[{"type":"text","text":"https:\/\/github.com\/modern-js-dev\/modern.js"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章