快速入門:使用 Next.js 來開發 React 的同構應用

提及 服務端渲染(ssr) 和 SPA,相信你總能說個一二:css

  • 與 服務端渲染(ssr) 相比,SPA 這樣的架構設計可讓先後端開發並行進行,職責清晰。
  • 與 SPA 相比,服務端渲染(ssr) 首屏等待更短
  • 與 SPA 相比,服務端渲染(ssr) 是服務端直接返回完整的 html 內容,有利於網站的 SEO

這二者的優缺點都很明顯,因此隨着時代的進步和技術的演變,誕生了 SSR + SPA 的新模式。而且在 react/vue 等前端框架相結合 node (ssr) 下,能夠最大限度的重用代碼(同構),減小開發維護成本。html

什麼是同構應用

未命名文件 (5).jpg

web 應用能夠分爲 瀏覽器端服務器端 兩部分,對於同構應用來講,分爲 初次發送請求( SSR )後續操做( SPA )前端

  • 初次發送請求 時,服務器端負責渲染頁面的所有內容,而後返回給瀏覽器端,瀏覽器只須要直接顯示返回的內容,因此首屏渲染的速度會很是快;
  • 瀏覽器端的 後續操做 則再也不須要服務器端的介入,也不會引發頁面的刷新,全部的 UI 操做在前端完成。

基於 React 能夠在服務端渲染的能力,Next 提供了一套完整且方便的同構應用解決方案。vue

開始 Next.js

Next.js,這是一個 React 的同構應用開發框架。node

建立一個 Next.js 應用

咱們用 CLI 工具 -- Create Next App 來快速建立 Next.js 應用,經過配置參數 -e, --example [name]|[github-url] 能夠直接以 Next.js Repo中的模版建立應用:react

npx create-next-app nextjs-auth0 --example "https://github.com/vercel/next.js/tree/master/examples/auth0"
複製代碼

咱們今天使用 Next.js 的入門模版(默認):git

npx create-next-app my-nextjs
複製代碼

運行成功後,進入 my-nextjs 目錄,運行啓動命令,應用默認運行在 3000 端口:github

cd my-nextjs
npm run dev
複製代碼

http://localhost:3000/, 查看頁面源代碼,能夠發現全部的內容都是服務器端返回的: next-source.pngweb

Pages 頁面

Next.js 在開發時遵循了必定的約定:npm

  • 全部的頁面必須放在 pages 目錄下,頁面做爲一個組件。
  • 頁面與基於其文件名的路由相關聯。
    • pages/index.js 關聯的路由是 /
    • pages/posts/first-post.js 關聯的路由是 /posts/first-post
  • page 具備靜態方法 getInitialProps,能夠獲取接口數據做爲組件的 props

建立頁面

page/index.js 已經存在,咱們新建一個 pages/posts/first-post.js :

export default function FirstPost() {
  return <h1>First Post</h1>;
}
複製代碼

這時候,你訪問 http://localhost:3000/posts/first-post, 應該能夠看到:

頁面間的導航

<Link> 組件能夠在客戶端實現頁面間的導航,和 React Router 同樣實現的是前端路由,不會引發頁面的刷新:

import Link from "next/link";
複製代碼

使用時,將 Link 包裹在 a 標籤外,好比在 posts/first-post 添加一個回首頁的連接:

import Link from "next/link";

export default function FirstPost() {
  return (
    <> <h1>First Post</h1> <h2> <Link href="/"> <a>Back to home</a> </Link> </h2> </>
  );
}
複製代碼

Link 組件默認在後臺預取目標頁面。 經過設置 prefetch={false} (默認爲 true ) 能夠禁止頁面預取。當 prefetch 被設置爲 false 時,鼠標懸停在 上時仍然會觸發預取。預取功能只在生產環境中開啓。

<Link href="/posts/first-post" prefetch={false}>
  <FirstPost />
</Link>
複製代碼

Link 組件的默認行爲是將新 URL 推送到 history 堆棧中,可使用 replace 來替換 URL,而不是新增,這樣發生跳轉後,將沒法後退到上一個頁面。

<Link href="/about" replace>
  <a>About us</a>
</Link>
複製代碼

Next.js 支持具備動態路由的 pages(頁面)。例如,若是你建立了一個命名爲 pages/posts/[id].js 的文件,那麼就能夠經過 posts/1posts/2 等相似的路徑進行訪問。

靜態文件服務

若是你添加了一張圖片到 public/me.png 路徑,經過 /me.png 能夠直接訪問到它:

import Image from "next/image";

function Avatar() {
  return <Image src="/me.png" alt="me" width="64" height="64" />;
}

export default Avatar;
複製代碼

public 目錄映射靜態文件,包括 robots.txtfavicon.ico、Google 站點驗證文件以及任何其它靜態文件(包括 .html 文件)。

注意:

  • 請勿爲 public 更名。此名稱是寫死的,不能修改,而且只有此目錄能過夠存放靜態資源並對外提供訪問。
  • 請確保靜態文件中沒有與 pages/ 目錄下的文件重名的,不然這將致使錯誤。

動態加載頁面(Lazy loading)

動態加載(Lazy loading)是一種僅在資源須要時加載它們的策略。Next.js 也提供了 import dynamic from "next/dynamic" 幫助咱們實現動態加載策略。

普通 import 一個組件:

import Link from "next/link";
import Hello from "../../component/Hello";

export default function FirstPost() {
  return (
    <> <h1>First Post</h1> <Hello /> <h2> <Link href="/"> <a>Back to home</a> </Link> </h2> </>
  );
}
複製代碼

動態加載一個組件:

import Link from "next/link";
import dynamic from "next/dynamic";
// import Hello from "../../component/Hello";

const DynamicComponent = dynamic(() => import("../../component/Hello"));

export default function FirstPost() {
  return (
    <> <h1>First Post</h1> <DynamicComponent /> <h2> <Link href="/"> <a>Back to home</a> </Link> </h2> </>
  );
}
複製代碼

從 network 能夠看出,動態加載的狀況下,Hello 組件被做爲了單獨資源: 未命名文件 (6).jpg

相關文章
相關標籤/搜索