參考:https://nextjs.org/learn/foundations/from-react-to-nextjs/getting-started-with-nextjs
next.js是react的一個前端框架。react本質上是一個UI庫,用於操作虛擬DOM。next.js是基於react的一個前端框架,類似於springboot,有很多約定俗成的配置。
1 不用腳手架創建next.js項目
在一個空路徑下面創建package.json,內容如下
{
}
執行命令: npm install react react-dom next
然后,我么再查看package.json
{ "dependencies": { "next": "^12.1.2", "react": "^18.0.0", "react-dom": "^18.0.0" } }
同時目錄下多了node_modules文件夾,為下載的依賴
創建pages/index.js
import { useState } from 'react' function Header({ title }) { return <h1>{title ? title : 'Default title'}</h1> } export default function HomePage() { const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'] const [likes, setLikes] = useState(0) function handleClick() { setLikes(likes + 1) } return ( <div> <Header title="Develop. Preview. Ship. 🚀" /> <ul> {names.map(name => ( <li key={name}>{name}</li> ))} </ul> <button onClick={handleClick}>Like ({likes})</button> </div> ) }
package.json中添加
"scripts": { "dev": "next dev" },
啟動
npm run dev
這樣,一個簡單的next.js項目就搭建好了。
2 Next.js是如何工作的
Next.js是一個react框架,包含了很多內置的功能和工具:打包工具webpacked,jsx編譯工具Babel,自動代碼分割,客戶端渲染和服務端渲染,直觀的基於頁面的路由系統,代碼的預加載,高效的開發工具等。
1 開發環境和生產環境
next.js框架,提供了適用於開發和生產的命令
next dev用於在開發模式下啟動項目,會在項目路徑下生成.next文件夾。它附帶了一些旨在改善開發者體驗的特性,比如TypeScript和ESLint的集成、快速刷新等等
在生產部署時,Next.js為最終用戶以及他們使用應用程序的體驗進行優化。它的目的是轉換代碼,使其高效和可訪問
2 編譯
使用JSX、TypeScript和現代版本的JavaScript開發的源代碼瀏覽器是不支持他們的,所以首先要編譯成瀏覽器支持的特定版本的JavaScript。
在Next.js中,編譯發生在編輯代碼的開發階段,並作為生產環境構建的其中一個步驟。這也是為什么我們修改了代碼之后,頁面實時更新的原因
3 最小化代碼規模
我們寫的源碼包含運行代碼所不需要的額外信息,如注釋、空格、縮進和多行等,但是這些信息其實是不需要的,在Next.js中,JavaScript和CSS文件會被自動壓縮。
4 綁定
我們在開發應用程序時,會把應用程序分解為模塊、組件和函數。我們會在源文件中導出和導入這些模塊,以及第三方包中的模塊。
綁定是解析文件間的依賴關系並將文件(或模塊)進行合並的過程,目的是減少用戶訪問網頁時對文件的請求數量。
5 代碼分割
上面我們對代碼進行了綁定,但是bundle.js是一個比較大的文件。很多情況下,頁面上點擊某個鏈接只會加載某個頁面,因此對bundle.js進行適當地分割會比較好。Next.js內置了對代碼分割的支持。在構建過程中,pages/目錄中的每個文件都將被自動分割成一個chunk.js。
編譯階段,項目會被編譯為一些文件:
1 靜態html文件
2 用於服務端渲染頁面的js
3 用於客戶端交互的js
4 css文件
6 渲染
next.js提供了3種渲染方式
服務端渲染,
客戶端渲染,在完成渲染工作之前,用戶將看到一個空白頁面
生成靜態頁面
Next.js默認情況下會預渲染每個頁面。預渲染意味着HTML是提前在服務器上生成的,而不是由JavaScript在用戶的設備上完成。
7 路由
在next中,pages目錄下的組件就是一個頁面
路由默認是pages下的文件名:比如路由"/"對應pages/index.js,路由"/posts/first-post"對應pages/posts/first-post.js
在pages下創建posts目錄,然后創建first-post.js
export default function FirstPost() {
return <h1>First Post</h1>
}
頁面訪問http://localhost:3000/posts/first-post,我們會發現,不需要額外的路由配置,默認路由起作用了。
8 代碼預加載
對於Next中定義的一些組件(比如Link),Next.js會在空閑時間預加載組件(預先請求href,返回數據),這樣當我們點擊Link的時候,頁面反應是瞬時的。
<Link href="/"> <a>Back to home</a> </Link>
9 惰性加載
在Next.js中定義的一些組件(比如Image組件)是惰性加載的。
<Image src="/images/profile.jpg" // Route of the image file height={144} // Desired size with correct aspect ratio width={144} // Desired size with correct aspect ratio alt="szj" />
next/image是對img標簽的替換。
默認情況下,圖片是惰性加載的。這意味着您的頁面速度不會因viewport外的圖像而受到影響。圖像被滾動到viewport中時才加載
3 使用腳手架創建Next.js項目
npx create-next-app nextjs-blog --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
4 再談Next.js的服務端預渲染
默認情況下,Next.js預渲染每個頁面。這意味着Next.js提前為每個頁面生成HTML,而不是全部由客戶端JavaScript完成。預渲染可以帶來更好的性能和SEO。
每個生成的HTML都與該頁面所需的最小JavaScript代碼相關聯。當頁面被瀏覽器加載時,它的JavaScript代碼運行並和UI交互。
如果你的應用是一個普通的React.js應用(沒有Next.js),沒有預渲染,當打開頁面時,我們將會看到如下提示“Sorry, we need js to run correctly!”,並且我們查看response,我們發現我們只得到一個空的div。
<noscript>Sorry, we need js to run correctly!</noscript><div id="root"></div><script src="/umi.js"></script>
正如我們前面提到過的,React項目只會返回一個空的UI。頁面DOM的操作是React在客戶端電腦上通過虛擬DOM實現的。
Next.js有兩種形式的預渲染:編譯時生成靜態html,每次請求時生成html。即靜態頁面和服務端預渲染
我么可以選擇使用哪種預渲染策略。比如頁面一我么使用靜態頁面策略,頁面二我們使用服務端預渲染。具體該使用何種預渲染策略,需要根據實際情況確定,如果頁面數據頻繁的更新,則我們使用服務端渲染,如果是一些歷史訂單等信息,我們使用靜態頁面策略。
4.1 getStaticProps
有時,我們希望頁面在編譯時就編譯為靜態html,后面請求該頁面都請求靜態頁面。但是這個頁面數據需要從后台獲取。這時我們就需要getStaticProps。做法是在這個頁面中export一個async的函數getStaticProps。其工作原理是:
getStaticProps
函數在編譯時運行…- 並且在該函數中請求后台數據,數據以props的形式傳遞給當前頁面
示例:
4.2 getServerSideProps
如果我們希望服務端渲染,而且希望每次請求都獲取后端數據,而不是在編譯時獲取后端數據,則我們使用getServerSideProps。
export async function getServerSideProps(context) { return { props: { // props for your component } } }
5 動態路由
要實現動態路由,主要兩個步驟:
1 創建[id].js
2 [id].js中寫getStaticPaths函數
export async function getStaticPaths() { return ...這里從后台獲取路由數據 }
6 API路由
API路由其功能類似於后端寫的API接口,可以理解為,Next.js替代了部分后端該做的事,或者分擔后端的一些工作
API路由都在pages/api/路徑下,比如,我們再pages/api下創建hello.js
export default function handler(req, res) { res.status(200).json({ text: 'Hello' }) }
其有兩個參數req和res,返回一個json,我們訪問http://localhost:3000/api/hello,將得到一個json數據
{"text":"Hello"}