我看Next.js:一個更現代的海王

作者:狼叔

Next。js是一個用於生產環境的React 應用框架(官方介紹:

The React Framework

for Production),使用它可以快速上手開發 React 應用( enables you to build superfast and extremely user-friendly static websites,),而不需要花很多時間和精力去折騰各種開發工具。所謂的用於生產環境,是指功能和穩定性足夠,有大量的實際應用案例。

在整理編輯大人給的《狼書(卷3):Node。js高階技術》修訂版,給next。js一個明確觀點:“

整體來看,Next.js在Node.js Web開發領域是一個非常優秀的SSR框架,其眾多優秀特性,外加Blitzjs這種周邊生態,對於開箱即用的專案來說是極好的。從架構的角度,筆者以為Next.js是過度設計,從商業的角度,我認同Next.js的做法,易用性應該是開發領域最該重視的核心。"

之所以給出這樣一個觀點,是基於下面5個方面總結出來的。

next。js是什麼?有哪些優點?為啥狼叔覺得它看起來像一個海王?

對比cra,umi和next。js,它們之間的差異是什麼?

next。js生態除了vercel,還有rust和blitzjs,你都瞭解嗎?

實現一個框架有哪4方面的思考?

在服務端渲染領域,對比next。js和ykfe/ssr,有何異同?

內容有點多,大家需要有點耐心。

1、Next是什麼?

針對上面的點評,還需要明確一下next。js的介紹要點,不衝突

基於React,支援csr、ssr、isr、ssg等渲染或用於渲染的生成方式

支援ssr,但只是next。js的一個場景而已

next。js是Node web領域優秀的ssr框架,這只是其一,其實2019年之後,next。js也開始支援serverless了

搭配vercel部署,對serverless支援極好

開箱即用,簡單易用

下面看一下next的基本特性,如下。

我看Next.js:一個更現代的海王

簡單彙總一下。

基礎頁面,資料獲取,佈局,國際化等,都已經是前端領域最佳實踐了,這點上umi和next幾乎一模一樣。各種最佳化手段,圖片,字型,指令碼等,基本上都是最潮最新的好東西。

檔案即路由,從ruby on rails開始,前端也借鑑了,umi大概也是借鑑了next的。ykfe/ssr也是借鑑了的。

自動按頁面拆分程式碼,其實是webpack做的事兒,NextJS 將每個頁面單獨打包,開啟首頁時會載入應用基礎程式碼和首頁程式碼,其它頁面程式碼只會在開啟時才去載入,這對於大型應用來說非常有用。

靜態頁面匯出,可以將整個 NextJS 應用匯出為一個靜態網站,完美的JamStack

CSS-in-JS,內建了 styled-jsx 方案,樣式寫法遵循標準,並且樣式作用域侷限於元件內部而不是全域性,避免了元件之間樣式互相影響。

在今天,習慣Umi類腳手架和react開發的人,基本上會認為這些是標配,事實上,我們是需要感謝next。js團隊的開拓之功的。

1。1、易用極致

nextjs很明顯選擇易用性,像一個海王一樣,太懂使用者的心了。所以它也是for 企業,小客戶和個人開發者的通用方案,從基礎框架,到釋出運維都幫你解決了,是極為方便的技術,以致於很多人都把它作為第一梯隊的選擇。

早期的next。js寫法是非常簡單的,就只有getInitialProps一個靜態方法。

function Page(props) { return

{props。name}
}Page。getInitialProps = async (ctx) => { return Promise。resolve({ name: ‘Egg + React + SSR’ })}export default Page

在egg-react-ssr技術調研期,我們分別看了next。js和easywebpack。

easywebpack在使用上,我不認可使用 egg 的worker來做。easy-team的方案本地開發採用了在Node中啟動webpack編譯bundle的方案,將服務端bundle打包在記憶體中,agent程序透過memory-fs提供的api來讀取檔案內容,並且透過worker與agent程序的通訊,來讓worker程序可以獲取到檔案的字串內容。然後採用了Node的runInNewContext api,類似於eval的方式去執行js字元。

next。js寫法上是完美的。將請求方法抽取成靜態方法,可以複用。另外在服務端渲染,先執行請求方法,是最高效的方式,比Biglet用的物件方法好。

在打包構建方面,本專案本地開發採用的方案為直接將服務端bundle打包到本地硬碟,透過webpack ——watch的方式,來實現更新,同時本地開發的時候每次載入之前清空require bundle的快取保證重新整理後server端的內容與client端一致。結合webpack-dev-server,上手難度低,實現程式碼更少。

為了適應更多的渲染細化場景,基於getInitialProps都能完成,但next又進行了拆分,讓每個寫法都有特定的應用場景。好處是用的人簡單,缺點是增加學習成本。

我看Next.js:一個更現代的海王

除了核心特性上,做了渲染場景的細化外,next還做了非常多的易用性上的小心思,大家討論最多的,大概就是image了。下面是山月在知乎上寫的關於next image的體驗。

內建 Image Proxy,對圖片進行轉換、壓縮,使得圖片體積最小化。並配合圖片懶載入與 srcset 一系列關於圖片最佳化的小點子最佳化網路體驗 Next 團隊宣傳地也頗為實在

> In order to use images on web pages in a performant way a lot of aspects have to be considered: size, weight, lazy loading, and modern image formats。

舉一個栗子,如果你使用了一張 10000px x 10000px 的 PNG 圖片,放到了 100px x 100px 的小方格里。那麼 next。js 將會做以下操作最佳化效能。

內建 Proxy 服務把它壓縮成 100px 與 200px 兩張圖,大幅度壓縮體積

內建 Proxy 服務把它轉成 webp,一個體積更小的圖片格式 (比 jpg 小 30% 的體積)

內建 Proxy 服務把它轉成 75% 壓縮質量的 webp,一個更小的體積與幾乎無肉眼可見的圖片質量變化

懶載入,看不到圖片不載入

按需載入 (不像 Gatsby 那樣需要在部署專案前耗費大量精力去壓縮圖片)

由於內建 Proxy 執行時處理,可支援非本域名上的圖片處理

優點說完了,這裡說一下它的缺點吧

無法利用 Long Term Cache,瀏覽器二次載入時圖片速度慢,使 CDN 也無法效能最大化

小圖片無法內建為 Data URI,大量的小圖片將造成多次 HTTP 請求影響效能,比如我的這個網站: 開發者武器庫

無法支援多解析度螢幕

CPU,如果部署在 Vercel 可以利用它的伺服器資源做快取服務,如果自部署處理圖片需要消耗 CPU。但這個也不算很缺點,只是引入了複雜狀態,國內可以利用 Ali_OSS 或公司共有 Image Proxy 做圖片快取服務

自定義一個 loader,詳見文件

https://nextjs。org/docs/api-reference/next/image#loader

還有一個算不上缺點的具有迷惑性的點:雖然響應的字尾名是 png,但是返回的 MIME 是 image/webp

感謝山月的分享內容。

avif是下一代圖片 image編解碼格式,AVIF由開源組織AOMedia開發,Netflix、Google與Apple均是該組織的成員。看到沒,幾個大佬都在,因此是一統天下的圖片格式。AVIF是基於AV1的新影象格式,使用HEIF作為容器(和Apple的HEVC一樣)和AV1幀,壓縮質量還真是歎為觀止,而且還支援JS解析。在Next 12版本里,增加了對avif的支援,是不是做的極為貼心?像不像討好開發者的海王?哈哈哈。

1。2、生態體系

justjavac說next和vercel不能分開看,這個觀點我是認同的。從文件裡就可以看出來,結合vercel親爹的first-class支援,真的是用起來特別爽。

我看Next.js:一個更現代的海王

另外,關於for productin裡也有很多最佳化。

我看Next.js:一個更現代的海王

Vercel的核心特性

開發,基於next。js和serverless

預覽,基於serverless和cdn能力快速預覽效果

分發,真實發布

如果把nextjs和vercel整個鏈路放到一起看,你會發現,它整合的是開發和運維,讓開發體驗更流程,這部分內容在講next。js的野心一節細講。

我看Next.js:一個更現代的海王

1。3、重倉rust,改進開發體驗

next12使用 swc 替換掉 babel和ts部分,效能得到非常大的提升。

> In early tests, previous code transformations using Babel dropped from

~500ms to ~10ms

and code minification from Terser dropped from

~250ms to ~30ms

using SWC。 Overall, this resulted in

twice as fast builds

從這點上看,Rust作為構建高效能構建工具的語言,是極好的。今天,前端發展到了一個瓶頸,也忍受了很多,比如webpack構建,雖然前端也使用了很多最佳化手段,但js編寫的,你只能利用巧妙的設計來最佳化,這不像rust/go這種系統級語言,天生的效能優勢,於是有了swc和esbuild等編譯工具,這對前端生態來說是極好的。

swc作者今年畢業,從deno轉入職next的母公司vercel。parcel的一個核心維護者也加入了vercel,可謂兵強馬壯。

> We‘re excited to announce DongYoon Kang, the creator of SWC, and Maia Teegarden, contributor to Parcel, have joined the Next。js team at Vercel to work on improving both next dev and next build performance。 We will be sharing more results from our SWC adoption in the next release when it’s made stable。

rust做一些基礎模組改造是很好的,合理利用語言本身的優勢。如果都用rust去做應用,把之前js寫過的170萬+模組都重寫,想想都不現實,今天前端的瓶頸如果是編譯速度,那就真的卷死了。

最近justjavac在postcss-rs,https://github。com/justjavac/postcss-rs 目前已經完成了 tokenizer 功能,效能極好,在單核 CPU 上,資料如下。

js: 0。11s user 0。02s system 126% cpu 0。102 totalrust: 0。00s user 0。00s system 66% cpu 0。006 total# tokenize bootstrap-reboot。css ~45xjs: tokenizer/small(7K) 3。063msrust: tokenizer/small(7K) 0。068ms# tokenize bootstrap。css ~26xjs: tokenizer/fairly_large(201K) 25。672msrust: tokenizer/fairly_large(201K) 0。979ms

這效能也是沒誰了,隨隨便便20倍以上的提升,做cpu密集型任務,rust真的有天然優勢。

正是因為postcss-rs是rust寫的,且效能很好,於是vercel的ceo就主動找justjavac,想收編。

我看Next.js:一個更現代的海王

綜上所述,你看rust寫編譯器,執行時是js,這樣才是最合理最高效的。一個商業公司,將開發體驗作為目標,進一步拉攏開發者,是對商業和開發者都有利的事兒,必然會得道多助的。

1。4、渲染模式大而全

從服務端到瀏覽器,將ssr和csr整個過程梳理完,有5種。

我看Next.js:一個更現代的海王

我們現在所說的react ssr其實是第三者,基於hydration做的混合渲染。

Next。js專案組成員Parabola說的:Next

不是

一個 SSR 框架。SSR 只是它的功能之一,它還支援 CSR、SSG、ISR 以及 API 路由(或是以任何方式組合在一起)。

starkwang在《新一代Web建站技術棧的演進:SSR、SSG、ISR、DPR都在做什麼?》https://zhuanlan。zhihu。com/p/365113639,有更詳細的描述。

先解釋一下文章裡用到的英文縮寫:

CSR:Client Side Rendering,客戶端(通常是瀏覽器)渲染

SSR:Server Side Rendering,服務端渲染

SSG:Static Site Generation,靜態網站生成

ISR:Incremental Site Rendering,增量式的網站渲染

DPR:Distributed Persistent Rendering,分散式的持續渲染

增量式更新(ISR)的概念,這個概念最早由

Next。js 在 9。5 版本中提出

,既然全量預渲染整個網站是不現實的,那麼我們可以做一個切分:

1、

關鍵性的頁面

(如網站首頁、熱點資料等)預渲染為靜態頁面,快取至 CDN,保證最佳的訪問效能;

2、

非關鍵性的頁面

(如流量很少的老舊內容)先響應 fallback 內容,然後瀏覽器渲染(CSR)為實際資料;同時對頁面進行非同步預渲染,之後快取至 CDN,提升後續使用者訪問的效能。

我看Next.js:一個更現代的海王

頁面的更新遵循 stale-while-revalidate 的邏輯,即始終返回 CDN 的快取資料(無論是否過期);如果資料已經過期,那麼觸發非同步的預渲染,非同步更新 CDN 的快取。

我看Next.js:一個更現代的海王

在 Next。js 中,你可以使用

getStaticPaths()

來定義哪些路徑需要預渲染,透過

getStaticProps()

來獲取預渲染需要的資料:

// 定義哪些頁面需要預渲染export async function getStaticPaths() { return { // 只有 /posts/1 和 /posts/2 會被預渲染 paths: [{ params: { id: ‘1’ } }, { params: { id: ‘2’ } }], // 其它頁面,如 /posts/3,都會返回 fallback 頁面,然後 CSR fallback: true, }}// 定義預渲染需要的資料export async function getStaticProps({ params }) { // 拉取對應的文章內容 const res = await fetch(`https://。。。/posts/${params。id}`) const post = await res。json() return { props: { post }, revalidate: 60 // 資料有效期為 60 秒 }}

但 ISR 存在部分缺陷:

對於沒有預渲染的頁面,使用者首次訪問將會看到一個 fallback 頁面,此時服務端才開始渲染頁面,直到渲染完畢。這就導致使用者

體驗上的不一致

對於已經被預渲染的頁面,使用者直接從 CDN 載入,

但這些頁面可能是已經過期的,甚至過期很久的

,只有在使用者重新整理一次,第二次訪問之後,才能看到新的資料。對於電商這樣的場景而言,是不可接受的(比如商品已經賣完了,但使用者看到的過期資料上顯示還有)。

為了解決 ISR 的一系列問題,Netlify 在前段時間發起了一個新的提案:DPR,Distributed Persistent Rendering,感興趣的自己去看。

感謝starkwang的分享。

這是csr和ssr中間折中燈下黑之地,屬於最佳化範圍內的,它很實用,但也有後遺症,一旦加了isr,在api層面必然會增加更多寫法和相容,比如引入getStaticPaths,getStaticProps,我不認為這是明智之舉。

從使用者角度講,當然是直接用最好,從這個角度看,next做好社群需求,這是非常好的。但從框架定位上來看,剋制一點,遵循KISS原因會更好。這種糾結,大概只有我願意講,其實商業公司本質上是逐利,在服務好客戶的前提下做技術,這就好比大公司在kpi體系下做開源是一樣的。next是一門解決使用者問題的不可多得的好技術框架。這就夠了。大家都不容易,next團隊是真心熱愛技術的,像我這樣雞蛋裡挑骨頭的不多。

1。5、blitzjs

blitzjs其實就是在Next。js之上加入訪問資料庫的能力(Everything End-to-End From the Database to the Frontend),最終形成類似Ruby on Rails的一棧式開發框架。

官方簡介

Blitz is a batteries-included framework that‘s inspired by Ruby on Rails, is built on Next。js, and features a ”Zero-API“ data layer abstraction that eliminates the need for REST/GraphQL。

如果說,僅僅是加入了訪問db的能力,從next選一個後端框架,加個orm就可以了。blitzjs是通prisma做到”Zero-API“ Data Layer,在技術選型方面,可謂是很有想法的。

下面是一個簡單的建立專案的程式碼,可謂乾淨,漂亮。

// app/pages/projects/new。tsximport { Link, Routes, useRouter, useMutation, BlitzPage } from ”blitz“import Layout from ”app/core/layouts/Layout“// Notice how we import the server function directlyimport createProject, {CreateProject} from ”app/projects/mutations/createProject“import { ProjectForm } from ”app/projects/components/ProjectForm“const NewProjectPage: BlitzPage = () => { const router = useRouter() const [createProjectMutation] = useMutation(createProject) return (

Create New Project

{ // This is equivalent to calling the server function directly const project = await createProjectMutation(values) // Notice the ’Routes‘ object Blitz provides for routing router。push(Routes。ProjectsPage({projectId: project。id}})) }} />
)}NewProjectPage。authenticate = trueNewProjectPage。getLayout = (page) => {page}export default NewProjectPage

crud也特別乾淨

// app/projects/mutations/createProject。tsimport { resolver } from ”blitz“import db from ”db“import * as z from ”zod“// This provides runtime validation + type safetyexport const CreateProject = z 。object({ name: z。string(), })// resolver。pipe is a functional pipeexport default resolver。pipe( // Validate the input data resolver。zod(CreateProject), // Ensure user is logged in resolver。authorize(), // Perform business logic async (input) => { const project = await db。project。create({ data: input }) return project })

另外,從專案,程式碼質量,社群活躍度上看,這都是一個非常優秀的專案。

我以為他最大的價值是為next。js構建了全棧領域的實踐。

2、next。js的野心

我在知乎上回答了《2021前端會有什麼新的變化?》,單篇39。8萬的閱讀量,還是不錯的,這裡再講我對Node。js相關內容的看法。如果是今年選Node。js Web框架,大概只有Midway、Nest和next。js了

Node。js Web框架2021年8大類分析

我看Next.js:一個更現代的海王

我看Next.js:一個更現代的海王

這裡講next。js最有野心的原因,原因從2013年到2017年,前端快速發展,整體難度是變大了很多,從2018年之後,創新放緩,慢慢的大家都在做沉澱和降低成本的事兒。從cra和umi,固化webpack最佳實踐,可以看出前端自身的簡化方面做出的努力。next。js除了前端簡化外,還在ssr等做了場景上的增強,打通從開發到部署的一站式開發,你只需要透過git提交程式碼,自動部署。站在前端和Node基礎上,整合開發釋出鏈路,它為未來端開發指明瞭發展方向,這是趨勢領導者。

定位開箱即用,滿足絕大部分場景,我的就是最好的,你不需要定製,所以它說提供了能力,但你定製起來極難,只要上了賊船,基本上下不來。

易用性做到極致,你想要的功能它都有,比如image,資料分析,動態分隔等,真的是不能再貼心了。這也是為啥我覺得它像海王的原因。這是好話,懂使用者的技術產品才是好產品。

特定場景沒有深耕,無傷大雅。當然,易用性之外再提深度,容易捱打。

這就是典型的入口和平臺思維。構建了核心能力,易用性上讓你上癮,即使現在貼錢做市場也是值得的。另外整合研發鏈路,簡化流程,進一步鎖客。我想,這才是next。js的真正的商業價值。

3、ssr降級問題

編寫一套程式碼,可以在ssr崩潰是做兜底,就需要csr也可以支援。於是有了ssr可以無縫降級csr的特性。這是在真實大流量場景下,才需要考慮的事兒,之所以要做這個功能是真實需求裡誕生的。

按照next。js的邏輯,它可以ssg,然後在閘道器層把ssr和csr做降級處理,理論上也可以實現,只是不那麼優雅和絲滑,不符合它之前在易用性做的那麼好的一貫認知。事實上,從getInitialProps上分裂那麼多細分方法,就註定這條路被堵死了。大概這也是框架設計者的取捨吧。

要做到無縫降級,最需要處理的就是資料獲取的問題,什麼時候應該在哪個端去載入資料。這塊的邏輯應該是在框架層去做的。Next。js 透過 next/router 的方式劫持開發者的 push/pop 操作,在其中做非常多黑盒複雜的邏輯,我認為這非常的不優雅。事實上,在我們的專案中我們僅編寫了一個高階元件來完成這個功能。

在寫法上,可以支援csr和ssr,在構建上更加簡單,結合我們在使用的egg。js,就誕生了egg-react-ssr。後面加了外掛化和serverless,就有了ykfe/ssr。這裡不展開講,避免有蹭熱度之嫌。

不過next已經不只是ssr框架,這方面做得不夠完美,其實也還好。

4、對比三巨頭:cra、umi和next

前端框架和基本探索穩定後,大家就開始想如何更好的用,更簡單的用。各家大廠都在前端技術棧思考如何選型和降低成本,統一技術棧。

關於 Webpack 的封裝實踐有很多,比如知名的 af-webpack,ykit,easywebpack。

af-webpack 是支付寶定製的Webpack,把 webpack-dev-server 等Node。js模組直接打包進去,同時對配置做了更好的處理,以及外掛化

ykit 是去哪兒開源的Webpack,內建 Connect 作為Web server,結合dev和hot中介軟體,對於多專案構建提效明顯,對版本檔案釋出有不錯的實踐

easywebpack 也是外掛化,但對解決方案,boilerplate 等做了非常多的整合,比如egg的ssr是有深入思考的,儘管不贊同這種做法。

在 create-react-app(cra)專案裡使用的是 react-scripts 作為啟動指令碼,它和 egg-scripts 類似,也都是透過約定,隱藏具體實現細節,讓開發者不需要關注構建。在未來,類似的封裝還會有更多的封裝,偏於應用層面。

umi是一個和cra類似的具有螞蟻特色的腳手架,它借鑑了next。js和cra的優點,同時基於af-webpack,便於定製webpack配置,同時對antd經典ui庫支援最好,使得umi在螞蟻內部以及開源社群有相當大的使用者量。umi同時支援csr和ssr,ssg等,功能還是非常強大的。

next。js早期和umi很像,但新版不斷迭代,在易用性上做的非常好,外加vercel(以前的now。sh)搭配,真的是上手簡單,釋出更簡單。

我看Next.js:一個更現代的海王

next。js的過度設計問題,我的思考如下。

cra、umi、next。js的除錯問題,webpack配置封裝在框架裡,要麼eject,要麼自己扒原始碼,那個過程還是非常痛苦的。

定製問題:next。js裡按照它的方式做,是極好用的。可是想定製點啥,你發現很難實現。除了程式碼量很大外,很有可能牽一髮而動全身

黑盒:比如

next/dynamic這種單獨封裝,其實就react-loadable,用的時候如果文件裡沒有,能找死。

甜心:像內建的元件封住,是很好用的,比如image,但很明顯這是前端react程式碼裡要處理的,如果內建了,是有益處,但也會面臨一個慣性,後面各種前端的最佳化是不是next都要整合,一旦整合就會有csr和ssr等場景相容問題。類似於

Next。js Analytics,這種統計類的功能,它很貼心,但從職責上看,放到框架是否合適,我理解這也是需要考慮的。

我說它是過度設計,是因為最初做某c端專案選型的時候認真的考慮過,但經過分析,它確實不適合我們的場景。如果大家在next。js自身推薦的場景外,想深度定製的話,必然會遇到上面的。

之所以說next是過度定製,是因為我想深度定製。其實,next本身是不建議深度定製的,它希望的是開箱即用,這樣才是它推薦的使用方式。

5、我眼中好的框架設計

如果想要實現一個框架,在今天看起來,還是挺難的,如下圖。

我看Next.js:一個更現代的海王

你需要考慮4個問題:

解決的場景:csr還是ssr,還是都有?

支援的前端框架:react or vue2 or vue3,還是像next一樣只支援react

構建:webpack和vite,你總要選一樣,至於esbuld或swc是可選的,或者想next一樣能用rust重寫工具鏈

服務端執行時:傳統Node。js web應用or Node Faas,好像有一種不支援都不好意思說自己的框架還不錯

如果以next。js為例,你會發現它除了vue,都內建了。易用性做到極致,打通開發和釋出鏈路,構建已Rust為核心的開發體驗,這才是真的現代。

如果不考慮易用性,我會說:“好的框架是剋制的,unoption的,技術棧無關的”。如果站在易用性的角度上看,約定大於配置也許是更好的選擇。

6、總結

透過上面的講解,相信大家能夠理解我說的:“從架構的角度,我以為Next。js是過度設計,從商業的角度,我認同Next。js的做法,易用性應該是開發領域最該重視的核心”。Next。js是一款優秀的更Modern的框架,值得大家學習和使用。

此時,我們再回頭看上面提出的5個問題:

next。js是什麼?有哪些優點?為啥狼叔覺得它看起來像一個海王?

易用性極佳,對使用者需求理解的極好

重視開發和釋出體驗

使用Rust解決開發體驗

對比cra,umi和next。js,它們之間的差異是什麼?

cra是react開發簡化的代表

umi借鑑了next和cra,同時對antd支援極好,國內最佳react腳手架

next不只是ssr框架,支援多種渲染模式,它的野心極大,想變成未來開發者的唯一入口

next。js生態除了vercel,還有rust和blitzjs,你都瞭解嗎?

rust生態,提升開發體驗,但僅限於工具鏈。js依然是應用層最受歡迎的語言

blitzjs是基於next,但加入了訪問資料的能力,全棧型框架

實現一個框架有哪4方面的思考?

場景、前端框架選型、服務端執行時,構建

好的框架是剋制的,unoption的,技術棧無關的

如果站在易用性的角度上看,約定大於配置也許是更好的選擇

在服務端渲染領域,對比next。js和ykfe/ssr,有何異同?

易用性和通用性next更好,ssr細分領域專業程度ykfe/ssr更好,此處留在下一篇講ykfe/ssr的時候在講

你理解多少呢?

說明

- 引用了Starkwang、Parabola、山月的部分知乎內容,文中已標出

- 感謝justjavac(postcss-rs以及rust部分知道)、張宇昂(ykfe/ssr部分)糾錯