在的網(wǎng)絡(luò)情況雖然很樂觀,但是
defer和async
當(dāng)瀏覽器碰到 script 腳本的時(shí)候:
<script src="script.js"></script>
沒有 defer 或 async,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,“立即”指的是在渲染該 script 標(biāo)簽之下的文檔元素之前,也就是說不等待后續(xù)載入的文檔元素,讀到就加載并執(zhí)行。
<script async src="script.js"></script>
有 async,加載和渲染后續(xù)文檔元素的過程將和 script.js 的加載與執(zhí)行并行進(jìn)行(異步)。
<script defer src="myscript.js"></script>
有 defer,加載后續(xù)文檔元素的過程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。
然后從實(shí)用角度來說呢,首先把所有腳本都丟到 之前是最佳實(shí)踐,因?yàn)閷τ谂f瀏覽器來說這是唯一的優(yōu)化選擇,此法可保證非腳本的其他一切元素能夠以最快的速度得到加載和解析。
接著,我們來看一張圖咯:
此圖告訴我們以下幾個(gè)要點(diǎn):
preload和refetch
preload通常在頁面中,我們需要加載一些腳本和樣式,而使用 preload 可以對當(dāng)前頁面所需的腳本、樣式等資源進(jìn)行預(yù)加載,而無需等到解析到 script 和 link 標(biāo)簽時(shí)才進(jìn)行加載。這一機(jī)制使得資源可以更早的得到加載并可用,且更不易阻塞頁面的初步渲染,進(jìn)而提升性能。
使用方式
將 link 標(biāo)簽的 rel 屬性的值設(shè)為 preload,as 屬性的值為資源類型(如腳本為 script,樣式表為 style)
<head> <metacharset="utf-8"> <title> preload example </title> <!-- 對 style.css 和 index.js 進(jìn)行預(yù)加載 --> <link rel="preload" href="style.css" as="style"> <link rel="preload" href="index.js" as="script"> <link rel="stylesheet" href="style.css"> </head> <body> <div id="app"></div> <script src="index.js"></script> </body>
prefetch與 preload 一樣,都是對資源進(jìn)行預(yù)加載,但是 prefetch 加載的資源一般不是用于當(dāng)前頁面的,即未來很可能用到的這樣一些資源,簡單點(diǎn)說就是其他頁面會(huì)用到的資源。當(dāng)然,prefetch 不會(huì)像 preload 一樣,在頁面渲染的時(shí)候加載資源,而是利用瀏覽器空閑時(shí)間來下載。當(dāng)進(jìn)入下一頁面,就可直接從 disk cache 里面取,既不影響當(dāng)前頁面的渲染,又提高了其他頁面加載渲染的速度。
使用方式
同 preload 很相似,無需指定 as 屬性:
<head> <meta charset="utf-8"> <title> preload example </title> <!-- 對 style.css 和 index.js 進(jìn)行 preload 預(yù)加載 --> <link rel="preload" href="style.css" as="style"> <link rel="preload" href="index.js" as="script"> <!-- 對資源進(jìn)行 prefetch 預(yù)加載 --> <link rel="prefetch" href="next.css"> <link rel="prefetch" href="next.js"> <link rel="stylesheet" href="style.css"> </head> <body> <divid="app"></div> <script src="index.js"></script> </body>
總結(jié):對當(dāng)前頁面需要的資源,使用 preload 進(jìn)行預(yù)加載,對其它頁面需要的資源進(jìn)行 prefetch 預(yù)加載。
Subresource和Prerender
subresource可以用來指定資源是最高優(yōu)先級的。比如,在Chrome和Opera中我們可以加上下面的代碼:
<link rel="subresource" href="styles.css">
Chromium的文檔這么解釋:和 "Link rel=prefetch"的語義不同,"Link rel=subresource"是一種新的連接關(guān)系。rel=prefetch指定了下載后續(xù)頁面用到資源的低優(yōu)先級,而rel=subresource則是指定當(dāng)前頁面資源的提前加載。
所以,如果資源是在當(dāng)前頁面需要,或者馬上就會(huì)用到,則推薦用subresource,否則還是用prefetch。
prerender是一個(gè)重量級的選項(xiàng),它可以讓瀏覽器提前加載指定頁面的所有資源。
<link rel="prerender" href="/thenextpage.html" />
Steve Souders的文章詳細(xì)解釋了這個(gè)技術(shù):prerender就像是在后臺(tái)打開了一個(gè)隱藏的tab,會(huì)下載所有的資源、創(chuàng)建DOM、渲染頁面、執(zhí)行JS等等。如果用戶進(jìn)入指定的鏈接,隱藏的這個(gè)頁面就會(huì)進(jìn)入馬上進(jìn)入用戶的視線。Google Search多年前就利用了這個(gè)特性實(shí)現(xiàn)了Instant Pages功能。微軟最近也宣布會(huì)讓Bing在IE11上用類似prerender的技術(shù)。
但是要注意,一定要在十分確定用戶回點(diǎn)某個(gè)鏈接時(shí)才用這個(gè)特性,否則客戶端就會(huì)無端的下載很多資源和渲染這個(gè)頁面。
正如任何提前的動(dòng)作一樣,預(yù)判總是有一定風(fēng)險(xiǎn)出錯(cuò)。如果提前的動(dòng)作是昂貴的(比如高CPU、耗電、占用帶寬),就要謹(jǐn)慎使用了。雖然不容易預(yù)判用戶會(huì)點(diǎn)進(jìn)哪個(gè)頁面,但還是存在一些典型的場景:
如果用戶搜索到了一個(gè)明顯正確的結(jié)果時(shí),那么這個(gè)頁面就很有可能被點(diǎn)入
如果用戶在登錄頁面,那么登錄成功后的頁面就很可能接下來會(huì)被加載了
如果用戶在閱讀一個(gè)多頁面的文章或者有頁碼的內(nèi)容時(shí),下一頁就很可能會(huì)馬上被點(diǎn)擊了
利用Page Visibility API可以用來防止頁面在還沒真正展示給用戶時(shí)就觸發(fā)了JS的執(zhí)行。
參考:
defer和async(https://segmentfault.com/q/1010000000640869)
prefetch與 preload(https://segmentfault.com/a/1190000016949393)
prefetch預(yù)加載(https://developer.mozilla.org/zh-CN/docs/Web/HTTP/LinkprefetchingFAQ)
preload當(dāng)即加載(https://developer.mozilla.org/zh-CN/docs/Web/HTML/Preloadingcontent) 加載技術(shù)概述(http://www.alloyteam.com/2015/10/prefetching-preloading-prebrowsing/) dnc fetch(https://developer.mozilla.org/zh-CN/docs/ControllingDNS_prefetching)
Prerender Subresource
END
作者:caoweiju
https://segmentfault.com/a/1190000016955899
如今,當(dāng)我們想要基于 React 創(chuàng)建一個(gè)新的 Web 項(xiàng)目時(shí),我們有許多不同的框架選擇。作為一名開發(fā)人員,您會(huì)發(fā)現(xiàn)自己很難知道應(yīng)該選擇哪一種,或者哪一種最適合您的需求。
您可能知道最常用的框架之一是Next.js,Netflix、Twitch 或 Uber 等公司通常使用它。它被認(rèn)為是增長最快的 React 框架之一。
其他人很難與 Next.js 競爭,因?yàn)樗w了三種不同的頁面渲染策略,但自 2021 年 11 月以來,我們似乎有了一個(gè)新的、新鮮的、強(qiáng)大的框架,稱為Remix。
對不起蓋茨比,我沒有忘記你,我喜歡你在生成靜態(tài)站點(diǎn)時(shí)的工作方式。
為什么需要 Next.js 或 Remix 而不是普通的 React
也許你沒有;這取決于。重點(diǎn)是了解 React 應(yīng)用程序如何工作,您可能會(huì)發(fā)現(xiàn)哪些問題以及 Next.js 或 Remix 等框架如何解決這些問題。
關(guān)于 React 的要點(diǎn)是您可以制作單頁應(yīng)用程序 (SPA),其中僅使用一個(gè) HTML 文件來呈現(xiàn)所有網(wǎng)頁,并且路由保留在客戶端。但這到底是什么意思呢?
當(dāng)發(fā)出初始請求時(shí),瀏覽器會(huì)立即收到一個(gè)包含所有應(yīng)用程序的 HTML 框頁面。
沒有預(yù)渲染的內(nèi)容。
當(dāng)用戶導(dǎo)航觸發(fā)時(shí),JavaScript 僅替換那些與請求的路由相關(guān)的組件和內(nèi)容,但 HTML 文件保持不變。
簡而言之,瀏覽器負(fù)責(zé)管理應(yīng)加載哪個(gè) JavaScript 文件以呈現(xiàn)當(dāng)前頁面。換句話說,客戶端呈現(xiàn) (CSR)。
CSR 可以非常花哨并且有助于創(chuàng)建不需要關(guān)心 SEO、緩存或緩慢的初始渲染的應(yīng)用程序。
SSlow Initial Render——當(dāng)用戶第一次登陸時(shí),可能需要很長時(shí)間才能加載第一個(gè)內(nèi)容頁面。這意味著讓他們得到一個(gè)空白頁面,直到 JavaScript 加載并呈現(xiàn)所有內(nèi)容。
SEO——因?yàn)閮?nèi)容只有一個(gè) HTML 頁面,所以很難讓搜索引擎和社交媒體機(jī)器人對內(nèi)容進(jìn)行索引。
緩存問題——HTML 結(jié)構(gòu)無法緩存,因?yàn)樗诘谝淮武秩緯r(shí)不可用。
在這一點(diǎn)上,您可能認(rèn)為 SPA 是魔鬼,但想想這么多公司使用的所有內(nèi)部應(yīng)用程序或他們銷售的應(yīng)用程序產(chǎn)品。
當(dāng)您想利用 SPA 的工作方式而又不失去我之前提到的三點(diǎn)時(shí),Next.js或Remix就會(huì)出現(xiàn)。優(yōu)點(diǎn)是網(wǎng)站可以在發(fā)送到客戶端之前在服務(wù)器端呈現(xiàn)。
SSR vs SSG vs ISR
我已經(jīng)解釋了 CSR 的含義和工作原理,現(xiàn)在輪到我來談?wù)勂渌ㄉ诘捻撁娉尸F(xiàn)策略。
Next.js是一個(gè)強(qiáng)大的選項(xiàng),因?yàn)樗峁┝巳齻€(gè)開箱即用的不同選項(xiàng),而Remix完全依賴于 SSR(目前)。但這些策略究竟是如何運(yùn)作的呢?
服務(wù)器端渲染 (SSR)
當(dāng)一個(gè)頁面被請求時(shí),它在發(fā)送到客戶端之前在服務(wù)器上完全呈現(xiàn)。對于那些擁有大量動(dòng)態(tài)數(shù)據(jù)和內(nèi)容的網(wǎng)站來說,這是一個(gè)很好的選擇。
靜態(tài)站點(diǎn)生成 (SSG)
該策略在構(gòu)建期間按路由生成所有頁面。出現(xiàn)提示時(shí),只會(huì)將請求的頁面發(fā)送給客戶端。也就是說,這構(gòu)建了一個(gè)典型的靜態(tài)網(wǎng)站。
對于那些幾乎沒有或沒有動(dòng)態(tài)數(shù)據(jù)且頁面不多的靜態(tài)網(wǎng)站來說,它可能是一個(gè)合適的選擇。數(shù)據(jù)中的每個(gè)更改都會(huì)觸發(fā)所有頁面的重新生成。
增量靜態(tài)再生 (ISR)
Next.js 提供了這個(gè)概念,是 SSR 和 SSG 的混合體。
它類似于 SSG,但您可以設(shè)置一個(gè)間隔時(shí)間,讓您知道何時(shí)應(yīng)該重新生成您的頁面。適用于那些具有動(dòng)態(tài)內(nèi)容的靜態(tài)站點(diǎn)。
Next.js 的強(qiáng)項(xiàng)在于它允許您在每個(gè)頁面上的這三個(gè)選項(xiàng)之間切換,因此您可以讓每個(gè)選項(xiàng)遵循不同的策略。
所以也許你會(huì)問自己,“如果 Next.js 只適用于 SSR,我為什么要用 Remix 替換它”。答案很簡單,如今,應(yīng)用程序和網(wǎng)站往往具有動(dòng)態(tài)數(shù)據(jù),并且很少有適合 SSG 或 ISR 場景的示例。
考慮到這一點(diǎn),Remix 提供了一個(gè)較低級別的 API。例如,它公開了 Request 對象,因此您可以在呈現(xiàn)頁面之前輕松修改標(biāo)頭,而在 Next.js 中,您需要中間件來實(shí)現(xiàn)它。
路由
這兩個(gè)框架都使用基于文件的路由系統(tǒng)來呈現(xiàn)頁面。
每個(gè)頁面都保留在不同的文件中。
每個(gè)頁面都與基于其文件名的路由相關(guān)聯(lián)。
最后,每個(gè)頁面都會(huì)呈現(xiàn)一個(gè) React 組件。
混音中的路由
您將在 中添加每個(gè)路由/app/routes,并且在其中創(chuàng)建的每個(gè)文件或文件夾都將被視為一個(gè)路由。
混音路由 1
此外,您會(huì)發(fā)現(xiàn)一個(gè)文件,/app/root.jsx,其中是“根路由”,是整個(gè)應(yīng)用程序的布局。它包含 <html>、<head> 和 <body> 標(biāo)簽,以及其他與 Remix 相關(guān)的內(nèi)容。
Next.js 中的路由
您將在 中添加每條路線/pages,它的工作方式與 Remix 完全相同。
nextjs 路由 1
在這種情況下,您可能有也可能沒有pages/_app.jsand pages/_document.js。其中App用于初始化頁面,文檔包含標(biāo)簽。
Next.js 默認(rèn)使用它們,無需額外配置。但是,如果您需要自定義它們,您可以創(chuàng)建這兩個(gè)文件,以這種方式覆蓋默認(rèn)文件。
索引路線
他們都使用相同的系統(tǒng)來呈現(xiàn)容器路線。
Next.js 示例:
pages/index.js=> /(根頁面)
pages/posts/index.js或者pages/posts.js=>/posts
混音示例:
routes/index.js=> /(根頁面)
routes/posts/index.js或者routes/posts.js=>/posts
嵌套路由
Remix 建立在 React Router 之上,由同一個(gè)團(tuán)隊(duì)開發(fā),所以你可以想象在嵌套路由方面誰是贏家。
其背后的想法是創(chuàng)建一個(gè)活動(dòng)路由來掛載包含多個(gè)嵌套路由的布局,以便每個(gè)路由管理自己的內(nèi)容。
如果我必須用 React 語言來解釋它,我會(huì)告訴你想象每個(gè)嵌套路由都是一個(gè)組件,并且根據(jù) URL 路徑,它們可以被掛載和卸載。
為實(shí)現(xiàn)這一點(diǎn),Remix 使用了<Outlet />React-router 組件。它用在父路由上,告訴它們只要被觸發(fā)就渲染子路由元素。
請記住,所有這些嵌套路由都已預(yù)加載到服務(wù)器上,因此幾乎每個(gè)加載狀態(tài)都可以刪除。聽起來不像是 SSR 和 SPA 的混合體?
另一方面,Next.js 確實(shí)支持嵌套路由,但它們作為單獨(dú)的頁面工作。如果您想實(shí)現(xiàn)類似于 Remix 所做的事情,您可能應(yīng)該自定義您的_app.js.
兩者的示例:
routes/posts/news/index.js=>/posts/news
動(dòng)態(tài)路線
它們通過基于動(dòng)態(tài)的 URL 參數(shù)呈現(xiàn)不同的內(nèi)容來工作,但它使用單個(gè)路由文件。
在這種情況下,兩個(gè)框架都支持此功能,但使用不同的命名約定。
Next.js 示例:
pages/posts/[postId].js=>/posts/some-post-slug
pages/products/[category]/[productId].js=>/products/keyboards/some-keyboard-slug或/products/headphones/some-headphone-slug
它有自己的鉤子,useRouter將為您提供那些動(dòng)態(tài)參數(shù)(postId、類別、productId)的當(dāng)前值。
混音示例:
/app/routes/posts/$postId.js=>/posts/some-post-slug
/app/routes/products/$category/$productId.js=>/products/keyboards/some-keyboard-slug或/products/headphones/some-headphone-slug
您可以使用useParamReact Router hook 來訪問這些動(dòng)態(tài)參數(shù)。
需要加載文件的路由怎么辦?
想象一下,您需要您的網(wǎng)站包含典型文件robots.txt和sitemap.xml文件。
在 Next.js 和 Remix 中,您都可以將它們添加到 /public 目錄。但是 Remix 可以讓你通過路由系統(tǒng)實(shí)現(xiàn)它,只需創(chuàng)建一個(gè)/app/routes/[sitemap.xml].js或/app/routes/[robots.txt].js
數(shù)據(jù)加載
這兩個(gè)框架都是服務(wù)器端的,因此每個(gè)框架都有不同的系統(tǒng)來獲取數(shù)據(jù)和手動(dòng)調(diào)用 API。
對于 Next.js,您可以在兩個(gè)選項(xiàng)中進(jìn)行選擇,具體取決于您要構(gòu)建的頁面類型。
getStaticProps(SSG,如果設(shè)置了重新驗(yàn)證間隔,則為 ISR)——它在構(gòu)建時(shí)獲取數(shù)據(jù)并將其數(shù)據(jù)作為頁面的組件屬性提供。
export async function getStaticProps( {params} ) {
const productList=await getProductList()
return {
props: {
productList,
slug: params.slug
}
}
}
getServerSideProps (SSR) — 它在運(yùn)行時(shí)在服務(wù)器端獲取數(shù)據(jù),并將返回的數(shù)據(jù)作為頁面的組件道具提供。
export async function getStaticProps( {params} ) {
const productList=await getProductList()
return {
props: {
productList,
slug: params.slug
}
}
}
/**
* Here you would have your own getStaticProps/getServerSideProps functions
* depending on what system you choose.
**/
const PageName=(props)=> {
const { productList }=props
// Here you could render the requested data
return (<div>
<pre> {JSON.stringify(productList, null, 4)} </pre>
</div>)
}
Remix 使用不同的方式加載數(shù)據(jù);
它為您提供了一個(gè)loader在每個(gè)路由文件上使用的函數(shù),該文件將在運(yùn)行時(shí)在服務(wù)器端運(yùn)行。
在頁面組件本身上,您將能夠使用useLoaderData掛鉤來收集這些數(shù)據(jù)。
/**
* Here you would have your own getStaticProps/getServerSideProps functions
* depending on what system you choose.
**/
export const async loader=( {params} )=> {
const productList=await getProductList()
return {
productList,
slug: params.slug
}
};
export default function PageName() {
const { productList }=useLoaderData();
// Here you could render the requested data
return (<div>
<pre> {JSON.stringify(productList, null, 4)} </pre>
</div>)
}
數(shù)據(jù)突變
Next.js 沒有內(nèi)置的方式來執(zhí)行突變,你必須手動(dòng)進(jìn)行。
另一方面,Remix 創(chuàng)建了一個(gè)表單組件,并像使用瀏覽器的本機(jī) HTML 表單元素一樣使用它。如果您不輸入任何操作 URL,它將對表單使用相同的路由。
如果方法是GET,loader將觸發(fā)導(dǎo)出函數(shù),如果方法是POST,action將觸發(fā)定義在組件中的導(dǎo)出函數(shù)。
此外,您可以使用提供的 useTransition 掛鉤根據(jù)請求狀態(tài)管理應(yīng)用程序的行為,而無需像往常一樣手動(dòng)管理它。
export const loader=async ({ params })=> {
// Each time this page receive a GET Request, this loader will be executed
const userData=await getSomeUserData(params.slug)
return {
userData // it contains the User Name
}
}
export const action=async ({ request })=> {
// Each time this page receive a POST Request, this loader will be executed
const form=await request.formData()
const content=form.get('content')
return redirect('/')
}
export default function App() {
const { name }=useLoaderData();
return (
<div>
<div>{`Hello there ${name}`}</div>
<Form method="POST">
<label htmlFor="content">
Content: <textarea name="content" />
</label>
<input type="submit" value="Add New" />
</Form>
</div>
)
}
造型
Next.js 帶有開箱即用的內(nèi)置 CSS 支持,因此您可以直接將其導(dǎo)入到 /pages/_app.js 所需的任何 style.css 文件中。
您還可以添加其他 CSS 框架,使用一些配置或插件很容易實(shí)現(xiàn)。
linksRemix 更喜歡通過提供組件和導(dǎo)出功能來專注于對 Web 標(biāo)準(zhǔn)更加友好的解決方案。
import styles from "./styles/app.css";
export function links() {
return [
{ rel: "stylesheet", href: styles },
{ rel: "stylesheet", href: 'https://.....' },
];
}
export default function App() {
return (
<html lang="en">
<head>
<Links />
</head>
<body>
<Outlet />
</body>
</html>
);
}
您可能認(rèn)為僅僅加載一個(gè)樣式表有點(diǎn)過分了,但是如果我告訴您可以在每個(gè)頁面上單獨(dú)使用它,讓您僅在需要時(shí)加載特定樣式/字體怎么辦?
另外,在這里你可以使用其他的 CSS 框架,只需很少的配置,比如 Tailwindcss。
圖像優(yōu)化
Next.js 在這里獲勝,因?yàn)樗凶约旱膬?nèi)置組件next/image,可以實(shí)現(xiàn)圖像優(yōu)化、延遲加載、大小控制和集成加載器。不幸的是,目前 Remix 沒有任何圖像優(yōu)化支持。
搜索引擎優(yōu)化
在本文的開頭,我告訴過您這些框架背后的要點(diǎn)之一是解決 SPA 的 SEO 問題。
它們都有自己的內(nèi)置機(jī)制來動(dòng)態(tài)管理每個(gè)頁面上應(yīng)該使用哪些元數(shù)據(jù),例如關(guān)鍵字、標(biāo)題、描述等。
next/head在 Next.js 中,您可以通過將其導(dǎo)入頁面/路由來使用其內(nèi)置組件。
import Head from 'next/head'
export default function PostPage() {
return (
<div>
<Head>
<title>Post Page Title</title>
<meta name="description" content="Post Page Description" />
</Head>
<p>
All the metadata inside Head component will be injected into the
documents head
</p>
</div>
)
}
另一方面,Remix 為我們提供了一個(gè)meta導(dǎo)出函數(shù),可以接收頁面的請求數(shù)據(jù)以及 URL 參數(shù)。
export const meta=({ data, params })=> {
charset: "utf-8",
viewport: "width=device-width,initial-scale=1",
title: `Post | ${data.title}`,
description: data.description,
};
export default function PostPage() {
return (
<div>
<p>
All the metadata returned on meta function will be injected into the
documents head
</p>
</div>
)
}
錯(cuò)誤處理
Next.js 使您可以在捕獲某些錯(cuò)誤時(shí)定義自定義頁面,例如 400 或 500 錯(cuò)誤。但是除了路由或狀態(tài)錯(cuò)誤之外的任何其他錯(cuò)誤都會(huì)導(dǎo)致頁面中斷。
Remix 讓您盡情發(fā)揮想象力,這樣您就可以覆蓋和自定義您想要的每個(gè)錯(cuò)誤。他們添加了錯(cuò)誤邊界,這是一種處理錯(cuò)誤的獨(dú)特概念——在 React v16 中引入。
您可以通過在您的甚至每個(gè)頁面上使用CatchBoundary, 和ErrorBoundary導(dǎo)出的函數(shù)輕松地覆蓋這些錯(cuò)誤。root.tsx讓我們添加一些視覺示例。
// Here you will catch any controlled error and will tell the framework what information should be shown
const CatchBoundary=()=> {
let caught=useCatch();
switch (caught.status) {
case 401:
// Document is a custom React Component which contains <html>, <head>,<body>, etc
return (
<Document title={`${caught.status} ${caught.statusText}`}>
<h1>
{caught.status} {caught.statusText}
</h1>
</Document>
);
case 404:
return <PageNotFoundComponent />; // Yes, you can also use a React Component
default:
throw new Error(
`Unexpected caught response with status: ${caught.status}`
);
}
};
// Here you will have a more generic advise for when an uncontrolled error has been triggered
const ErrorBoundary=( { error } )=> {
return (
<Document title="Uh-oh!">
<h1>App Error</h1>
<pre>{error.message}</pre>
<p>
Replace this UI with what you want users to see when your app throws
uncaught errors.
</p>
</Document>
);
};
export const loader: LoaderFunction=async ({ params })=> {
const post=await getPost(params.slug);
if (!post) {
throw new Response("Not Found", {
status: 404,
});
}
return json({ post });
};
export default function PostPage() {
const { post }=useLoaderData();
return (
<div>
<pre>
{JSON.stringify(post, null, 4)}
</pre>
</div>
)
}
部署
Next.js 很容易部署在任何支持 Node.js 的服務(wù)器上。它還集成了無服務(wù)器部署到 Vercel 的功能,Netlify 有自己的適配器,因此您可以輕松部署應(yīng)用程序。
Remix 基于 Web Fetch API 而不是 Node.js 構(gòu)建,因此它可以在 Vercel、Netlify、Architect(Node.js 服務(wù)器)以及 Cloudflare 等非 Node.js 環(huán)境中運(yùn)行。
它還會(huì)在您開始項(xiàng)目時(shí)為您提供開箱即用的適配器,因此如果您知道要將項(xiàng)目部署到哪里,就可以直奔主題。
Remix 最重要的事情之一是它不再使用 Webpack。相反,它使用 Esbuild,它在捆綁和部署方面速度極快。
其他提及
每當(dāng)您想選擇 Next.js 或 Remix 時(shí),還有其他要點(diǎn)需要考慮,但我想收集那些在我看來作為開發(fā)人員在開發(fā)項(xiàng)目時(shí)具有更大影響的因素。
但如果您想了解更多,這里有一些我在本文中沒有談到的事情的回顧。
實(shí)時(shí)重新加載。Next.js 使用熱模塊重新加載 (HMR) 并默認(rèn)啟用,而在 Remix 上,您必須在 root.tsx 上添加一個(gè)組件以強(qiáng)制您的應(yīng)用程序在代碼更改時(shí)重新加載。
Remix 支持 Cookie、會(huì)話和身份驗(yàn)證,而 Next.js 不支持——您必須使用外部庫。
Next.js 內(nèi)置了對字體和腳本優(yōu)化的支持,而 Remix 則沒有。
兩者都讓您開箱即用地使用 Typescript。
Remix 無需執(zhí)行 JavaScript 即可完成其大部分功能,而 Next.js 則不會(huì)。
Remix 可以在嵌套路由中包含獨(dú)立路由
兩者都可以使用 Tailwindcss 快速工作,并有自己的指南來實(shí)現(xiàn)它。
Next.js 內(nèi)置了對國際化路由的支持。
Next.js 對 AMP 具有開箱即用的支持,而 Remix 則沒有。
|
|
|
|
|
|
|
|
|
|
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。