Next.js與React?兩者為合作關係,而非一種競爭

Next.js與React?兩者為合作關係,而非一種競爭

對於現代網路開發者來說,並不缺乏JavaScript庫和框架。最普遍的庫之一是React,它是Facebook(現在的Meta)建立的,以幫助建立功能豐富的應用程式。React應用程式傳統上在網路瀏覽器中執行,但Next.js框架通過JavaScript執行環境Node.js將React功能擴充套件到伺服器端。

在這篇文章中,我們將瞭解Next.js和React,以便你能決定它們是否適合你的下一個專案。

  1. Next.js和React:升級版本的JavaScript
  2. 什麼是Next.js?
  3. 什麼是React?
  4. Next.js vs React
  5. Next.js和React的特點

Next.js和React:升級版本的JavaScript

2022年的SlashData調查發現,全世界有超過1700萬的JavaScript程式設計師,在包括Python和Java等流行語言在內的隊伍中處於領先地位。JavaScript可以在客戶端和伺服器端使用,這種通用性意味著開發者可以使用一種程式語言建立完整的應用程式。

2022年程式設計師使用程式語言調查報告

Slash/Data對2022年程式設計師使用的語言的調查。(來源:Statista)

React等JavaScript庫和Next.js等框架的引入進一步加強了這種發展。這些庫和框架提供的功能簡化了前端和後端的整合。此外,開發人員可以使用npm(Node.js包管理器)等包管理器來安裝JavaScript庫和工具,擴充套件JavaScript功能。這些資源提供了複雜的功能,減少了你必須自己編寫的程式碼量。

JavaScript的可擴充套件性意味著對其最常用的工具的全面瞭解是你作為一個網路開發者成功的關鍵。

什麼是Next.js?

Next.js最初由Vercel在2016年釋出,是一個開源的React框架,提供了建立高效能網路應用的構建塊。此後,主要公司都採用了它,包括Twitch、TikTok和Uber,等等。

Next.js為構建快速、SEO友好的應用程式提供了最好的開發者體驗之一。以下是Next.js的一些特點,使其成為一個出色的生產框架:

  • 混合渲染能力
  • 自動程式碼拆分
  • 影象優化
  • 內建對CSS前處理器和CSS-in-JS庫的支援
  • 內建路由

這些功能幫助Next.js開發人員節省了大量配置和工具的時間。你可以直接跳到構建你的應用程式,它可能支援以下專案:

  • 電子商務商店
  • 部落格
  • 儀表板
  • 單頁應用程式
  • 互動式使用者介面
  • 靜態網站

什麼是React?

React是一個用於構建動態使用者介面的JavaScript庫。除了建立網頁介面外,你還可以使用React Native構建移動應用程式。

使用React的一些好處包括:

  • 提高效能:React使用一個虛擬DOM,而不是更新DOM中的每個元件,只更新已更改的元件。
  • 重度基於元件:一旦你建立了一個元件,你可以重複使用它。
  • 易於除錯:React應用程式使用單向的資料流–只從父元件到子元件。

Next.js vs React

儘管開發者經常將Next.js和React用於相同的目的,但兩者之間有一些根本的區別。

易於使用

開始使用Next.js和React很容易。兩者都需要在終端使用 npx 執行單個命令,這是Node.js的npm的一部分

對於Next.js,最簡單的命令是:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npx create-next-app
npx create-next-app
npx create-next-app

在沒有額外引數的情況下,create-next-app 的安裝將以互動模式進行。你將被要求提供一個專案名稱(將用於專案目錄),以及你是否要包括對TypeScript和程式碼linter ESLint的支援。

它看起來會像這樣:

使用npx建立next.js應用

在interactive模式下建立Next.js應用程式。

在初始化React例項時,最簡單的命令包括專案的目錄名稱:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npx create-react-app
new-app
npx create-react-app new-app
npx create-react-app 

new-app

這將生成一個包含所有必要的初始配置和依賴性的資料夾:

使用npx建立一個React專案

在終端命令列上建立一個React專案。

雖然兩者都能讓你輕鬆上手,但請記住,Next.js是建立在React之上的。因此,如果不先學習React並瞭解它的工作原理,你就無法學習Next.js。幸運的是,React擁有一個溫和的學習曲線,很適合初學者。

同樣重要的是要注意,React是相對非結構化的。你必須安裝和設定React路由器,並決定如何處理資料獲取、影象優化和程式碼拆分。這種設定需要你安裝和配置額外的庫和工具。

相比之下,Next.js 預先安裝和配置了這些工具。有了Next.js,任何新增到 pages 資料夾中的檔案都會自動作為路由。由於這種內建支援,Next.js更容易進行日常工作,使你能夠立即開始編碼你的應用程式的邏輯。

Next.js和React的特點

因為Next.js是基於React的,兩者共享一些功能。然而,Next.js更進一步,包括額外的功能,如路由、程式碼拆分、預渲染和開箱即用的API支援。這些是你在使用React時需要自己配置的功能。

資料獲取

React在客戶端渲染資料。伺服器向瀏覽器傳送靜態檔案,然後瀏覽器從API中獲取資料以填充應用程式。這個過程降低了應用程式的效能,並提供了糟糕的使用者體驗,因為應用程式載入緩慢。Next.js通過預渲染解決了這個問題。

通過預渲染,伺服器在向瀏覽器傳送應用程式之前會進行必要的API呼叫並獲取資料。因此,瀏覽器收到的是可隨時渲染的網頁。

預渲染可以指靜態網站生成(SSG)或伺服器端渲染(SSR)。在SSG中,HTML頁面是在構建時生成的,並在多個請求中重複使用。Next.js可以生成帶或不帶資料的HTML頁面。

下面是一個例子,說明Next.js如何生成沒有資料的頁面:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function App() {
return <div>Welcome</div>
}
export default App
function App() { return <div>Welcome</div> } export default App
function App() {
return <div>Welcome</div>
}
export default App

對於消耗外部資料的靜態頁面,使用 getStaticProps() 函式。一旦你從一個頁面匯出 getStaticProps(),Next.js將使用它返回的props對頁面進行預渲染。這個函式總是在伺服器上執行,所以當頁面使用的資料在構建時是可用的,就使用 getStaticProps()。例如,你可以用它來從CMS中獲取部落格文章。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const Posts= ({ posts }) => {
return (
<div className={styles.container}>
{posts.map((post, index) => (
// render each post
))}
</div>
);
};
export const getStaticProps = async () => {
const posts = getAllPosts();
return {
props: { posts },
};
};
const Posts= ({ posts }) => { return ( <div className={styles.container}> {posts.map((post, index) => ( // render each post ))} </div> ); }; export const getStaticProps = async () => { const posts = getAllPosts(); return { props: { posts }, }; };
const Posts= ({ posts }) => {
return (
<div className={styles.container}>
{posts.map((post, index) => (
// render each post
))}
</div>
);
};
export const getStaticProps = async () => {
const posts = getAllPosts();
return {
props: { posts },
};
};

在頁面路徑依賴於外部資料的情況下,使用 getStaticPaths() 函式。因此,要根據帖子的ID建立一個路徑,從頁面匯出 getStaticPaths() 。

例如,你可以從pages/posts/[id].js匯出 getStaticPaths(),如下所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export getStaticPaths = async() => {
// Get all the posts
const posts = await getAllPosts()
// Get the paths you want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
return { paths, fallback: false }
}
export getStaticPaths = async() => { // Get all the posts const posts = await getAllPosts() // Get the paths you want to pre-render based on posts const paths = posts.map((post) => ({ params: { id: post.id }, })) return { paths, fallback: false } }
export getStaticPaths = async()  => {
// Get all the posts
const posts = await getAllPosts()
// Get the paths you want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
return { paths, fallback: false }
}

getStaticPaths() 經常與 getStaticProps() 配對使用。在這個例子中,你會用 getStaticProps() 來獲取路徑中的ID的詳細資訊。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export const getStaticProps = async ({ params }) => {
const post = await getSinglePost(params.id);
return {
props: { post }
};
};
export const getStaticProps = async ({ params }) => { const post = await getSinglePost(params.id); return { props: { post } }; };
export const getStaticProps = async ({ params }) => {
const post = await getSinglePost(params.id);
return {
props: { post }
};
};

在SSR中,資料在請求的時間被獲取並被髮送到瀏覽器。要使用SSR,從你要渲染的頁面中匯出 getServerSide() 道具函式。伺服器在每次請求時都會呼叫這個函式,這使得SSR對於消耗動態資料的頁面非常有用。

例如,你可以用它來從一個新聞API中獲取資料。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const News = ({ data }) => {
return (
// render data
);
};
export async function getServerSideProps() {
const res = await fetch(`https://app-url/data`)
const data = await res.json()
return { props: { data } }
}
const News = ({ data }) => { return ( // render data ); }; export async function getServerSideProps() { const res = await fetch(`https://app-url/data`) const data = await res.json() return { props: { data } } }
const News = ({ data }) => {
return (
// render data
);
};
export async function getServerSideProps() {
const res = await fetch(`https://app-url/data`)
const data = await res.json()
return { props: { data } }
}

這些資料在每次請求時被獲取,並通過props傳遞給新聞元件。

程式碼拆分

程式碼拆分是將程式碼分成幾塊,讓瀏覽器可以按需載入。它減少了初始載入時傳送到瀏覽器的程式碼量,因為伺服器只傳送使用者需要的內容。Webpack、Rollup和Browserify等捆綁程式支援React中的程式碼分割。

Next.js支援開箱即用的程式碼拆分。

使用Next.js,每個頁面都是程式碼拆分的,嚮應用程式新增頁面不會增加捆綁程式的大小。Next.js還支援動態匯入,允許你匯入JavaScript模組,並在執行時動態載入它們。動態匯入有助於提高頁面速度,因為捆綁是懶得載入的。

例如,在下面的Home元件中,伺服器不會在初始捆綁中包括英雄元件。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const DynamicHero = dynamic(() => import('../components/Hero'), {
suspense: true,
})
export default function Home() {
return (
<Suspense fallback={`Loading...`}>
<DynamicHero />
</Suspense>
)
}
const DynamicHero = dynamic(() => import('../components/Hero'), { suspense: true, }) export default function Home() { return ( <Suspense fallback={`Loading...`}> <DynamicHero /> </Suspense> ) }
const DynamicHero = dynamic(() => import('../components/Hero'), {
suspense: true,
})
export default function Home() {
return (
<Suspense fallback={`Loading...`}>
<DynamicHero />
</Suspense>
)
}

相反,懸念的回退元素將在英雄元件載入之前被渲染。

Next.js對React的API支援

Next.js的API路由功能使您能夠在同一程式碼庫中編寫後端和前端程式碼。任何儲存在/pages/api/資料夾中的頁面都會被對映到/api/*路由中,Next.js會將其視為API端點

例如,你可以建立一個 pages/api/user.js 路由,像這樣返回當前使用者的名字:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export default function user(req, res) {
res.status(200).json({ username: 'Jane' });
}
export default function user(req, res) { res.status(200).json({ username: 'Jane' }); }
export default function user(req, res) {
res.status(200).json({ username: 'Jane' });
}

如果你訪問 https://app-url/api/user 連結地址,你會看到使用者名稱物件。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
username: 'Jane'
}
{ username: 'Jane' }
{
username: 'Jane'
}

當你想掩蓋你正在訪問的服務的URL或想保持環境變數的祕密而不需要編寫整個後端應用程式時,API路由很有幫助。

效能方面

Next.js在以簡化的程式建立效能更好的應用程式方面無疑是卓越的。SSR和SSG Next.js應用程式比客戶端渲染(CSR)React應用程式效能更好。通過在伺服器上獲取資料併傳送瀏覽器需要渲染的所有內容,Next.js消除了對API的資料獲取請求的需要。這意味著更快的載入時間。

此外,由於Next.js支援客戶端路由。瀏覽器不需要在使用者每次導航到另一個路由時從伺服器獲取資料。此外,Next.js的影象元件能夠自動優化影象。圖片只在進入視口時才載入。在可能的情況下,Next.js還以WebP等現代格式提供影象。

Next.js還提供字型優化、智慧路由預取和捆綁優化。這些優化在React中並不自動可用。

支援

由於React比Next.js存在的時間長,它有一個更廣泛的社羣。然而,許多React開發人員正在採用Next.js,所以該社羣正在穩步增長。開發人員更容易找到他們遇到的問題的現有解決方案,而不是從頭開始構建解決方案。

Next.js還具有優秀的文件,有全面的例子,易於理解。儘管它很受歡迎,但React的文件卻沒有那麼容易瀏覽。

小結

選擇Next.js還是React要看應用程式的要求。

Next.js通過提供改善效能的結構和工具,增強了React的能力。這些工具,如路由、程式碼分割和影象優化,都內建於Next.js中,這意味著開發人員不必手動配置任何東西。由於這些功能,Next.js很容易使用,開發者可以立即開始對業務邏輯進行編碼。

由於有不同的渲染選項,Next.js適用於伺服器端渲染的應用程式或結合靜態生成和Node.js伺服器端渲染的應用程式。另外,由於Next.js提供的優化功能,它非常適合於需要快速的網站,如電子商務商店。

React是一個JavaScript庫,可以幫助你建立和擴充套件強大的前端應用程式。它的語法也很簡單,特別是對於有JavaScript背景的開發者來說。此外,你可以控制你在應用程式中使用的工具,以及你如何配置它們。

評論留言