likes
comments
collection
share

看了就会的Next.js SSR/SSG实战教程

作者站长头像
站长
· 阅读数 18

看了就会的Next.js SSR/SSG实战教程

Next.js是基于React的服务端渲染工具。在传统的React项目中,例如使用Create-React-App创建的项目,最终build生成的静态文件,是基于浏览器渲染的,即所谓的CSR(Client-side Rendering)。CSR往往都是单页面应用,即一个HTML文件和若干个js、css文件。打开build后的HTML文件,发现代码很简单,页面和组件的元素都是放在了js里,由js动态渲染到HTML中。CSR模式是目前前端开发项目中应用最为广泛的。但有些也场景,特别是需要SEO优化的时候,CSR就不太合适了,所以服务端(Server-side Rendering)渲染应运而生,SSR是由服务器将用户请求的页面DOM组装好后,再返回给浏览器,因此通过“查看网页源代码”,是可以看到完整的页面DOM的。而SSG(Static Site Generation),顾名思义就是静态网站生成,也就是常说的“网页静态化”,除了适合SEO,还很方便CDN加速,比较适合内容相对比较固定的资讯发布类网站。

以下是关于CSR、SSR、SSG的简单对比:

CSRSSRSSG
运行端浏览器服务器服务器
静态文件单页面由服务器即时生成多个页面
SEO不适合适合适合
静态文件CDN适合不适合适合
适用场景中后台产品信息展示型网站内容较为固定的资讯类网站

本教程基于Next.js技术框架,通过一个简单的实战项目,将工程搭建、开发、部署、自动化等环节完整讲述。如果你正在做类似CMS的项目,并且需要将网页内容静态化。那本教程将非常适合你。SSR与SSG在开发过程中几乎是完全一样的,只是最终部署的环境有所不同。掌握了SSG,那SSR也同样不在话下。

以我的个人经验来讲,从零基础学习一个新的框架,最佳的方法是结合项目边做边学,官方技术文档比较适合做手册来查阅。脱离了实战项目,只看官方技术手册,很难掌握。因此,本教程就是以实战项目的角度,把官网技术文档的主要内容串起来。相信按照本教程操作一遍之后,就能快速掌握Next.js。再回过头去系统地看一遍官方技术手册,那就会更加深入理解。

先睹为快

先看下目录了解本教程都有哪些内容。

1 创建Next.js项目
1.1 安装Next.js
1.2 设置项目目录
1.3 项目入口文件
1.4 精简项目
2 配置项目
2.1 设置路径别名
2.2 配置SourceMap(不建议设置)
2.3 设置页面title
2.4 设置HTML框架代码
2.5 以SSR模式运行项目
2.6 设置404/500页面
3 CSS预处理及使用
3.1 集成Sass/Scss
3.2 集成Less(选读)
3.3 集成Stylus(选读)
3.4 关于样式命名规范
3.5 配置全局样式
3.6 配置页面(pages)样式
4 页面路由
4.1 优化index页面和样式文件的存放位置
4.1.1 方法一:通过next.config.js配置
4.1.2 方法二:通过组件引入(推荐)
4.2 创建About页面
4.3 使用next/router和next/link构建导航组件
5 图片引用
5.1 方法一:使用原生<img>标签引入图片
5.2 方法二:使用next/image引用图片
6 生成静态化网站(SSG)
6.1 设置SSG的export命令
6.2 设置静态资源的basePath
6.3 设置SSG export输出的目录名称
7 接口请求
7.1 CSR/SSR/SSG 三种API请求方式
7.2 搭建服务端API服务
7.3 构建Profile页面
7.4 getServerSideProps和getStaticProps小节
7.5 搭建Next.js API Routers服务(选读)
8 动态路由
9 使用CLI命令动态生成目录
10 其他说明
11 项目Git源码

本次分享Demo的主要依赖包版本:

Node.js 16.16.0

next 12.2.5

react 18.2.0

react-dom 18.2.0

axios 0.27.2

※注:

代码区域每行开头的:

"+" 表示新增

"-" 表示删除

"M" 表示修改

1 创建Next.js项目

1.1 安装Next.js

npx create-next-app next-ssg

next-ssg是项目名称,可根据需要自行更改。

安装完成后,进入next-ssg,运行:

yarn dev

浏览器打开http://localhost:3000/,项目运行成功。

看了就会的Next.js SSR/SSG实战教程

1.2 设置项目目录

Next.js官方脚手架初始目录结构如下:

├─ /.next              <-- 用于SSR运行的工程,执行yarn dev或yarn build后才会出现
├─ /node_modules
├─ /pages              <-- Next.js指定的页面目录
|  ├─ /api             <-- Next.js指定的API服务目录,可以删除
|  |  └─ hello.js      <-- API服务的hello接口
|  ├─ _app.js          <-- Next.js指定的项目入口文件
|  └─ index.js         <-- 项目首页
├─ /public             <-- 静态目录,放在这里的文件可通过"/"直接访问(没有public这一层级)
|  ├─ favicon.ico
|  └─ vercel.svg
├─ /styles             <-- 项目全局样式
|  ├─ globals.css
|  └─ Home.module.css  <-- Home组件样式
├─ .eslintrc.json
├─ .gitignore
├─ next.config.js      <-- Next.js配置文件
├─ package.json
├─ README.md
└─ yarn.lock

以上目录结构并没有看到src目录,这与日常项目的开发习惯不一致。如果希望保持一致的开发体验,仍然可以使用src做为开发目录。

按照以下步骤重新组织目录结构:

  1. 停止项目运行
  2. 在项目根目录新建src目录
  3. 把pages、styles两个目录放到src目录里
  4. 删除pages里的api目录(后续章节讲到API请求时再创建)

再执行yarn dev,项目依然正常运行。

为什么变更了目录结构,项目还可以正常运行?

Next.js的官方脚手架虽然没有src目录,但考虑到src目录是普遍存在于大多数脚手架工程中,所以Next.js也对src目录做了支持。当然,如果新建的不是src目录,把pages、styles放进去是无法被正确识别的。

关于src目录,官方的规则如下:

  1. 如果根目录下有pages,则src/pages将被忽略。
  2. public目录以及next.config.js、jsconfig.json、tsconfig.json不能放到src目录里。

官方说明:nextjs.org/docs/advanc…

1.3 项目入口文件

按以上目录设置后,项目的入口文件变为了src/pages/_app.js。稍后将结合演示项目进行具体讲解。

1.4 精简项目

修改src/pages/index.js,最简化页面:

function Index() {
    return (
        <h1>This is Index Page.</h1>
    )
}

export default Index

修改src/pages/_app.js,删除首行的全局样式引用:

-   import '../styles/globals.css'
    
    function MyApp({ Component, pageProps }) {
        return <Component {...pageProps} />
    }
    
    export default MyApp

对src目录及文件进行以下调整:

	/src
+	├─ /common              <-- 公用目录
+	|  ├─ /images           <-- 公用图片目录
+	|  └─ /styles           <-- 公用样式目录
+	├─ /components			<-- 公用组件目录
	├─ /pages               <-- Next.js指定的页面目录
+	|  ├─ /api              <-- Next.js指定的API服务目录(不会生成api页面目录)
	|  ├─ _app.js           <-- Next.js指定的项目入口文件(不会生成_app.html)
	|  └─ index.js          <-- index页面(会生成index.html)
-	└─ /styles				<-- Next.js初始的样式目录(删除)
-	   └─ globals.css       <-- Next.js初始的公用样式(删除)

现在,src目录结构如下,非常精简了:

/src
├─ /common            <-- 公用目录
|  ├─ /images         <-- 公用图片目录
|  └─ /styles         <-- 公用样式目录
├─ /components		  <-- 公用组件目录
└─ /pages             <-- Next.js指定的页面目录
   ├─ /api            <-- Next.js指定的API服务目录(不会生成api页面目录)
   ├─ _app.js         <-- Next.js指定的项目入口文件(不会生成_app.html)
   └─ index.js        <-- index页面(会生成index.html)

执行yarn dev,效果如下:

看了就会的Next.js SSR/SSG实战教程

2 配置项目

2.1 设置路径别名

为了避免使用相对路径的麻烦,可以设置路径别名。

在项目根目录下创建jsconfig.json,代码如下:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
    }
  }
}

路径别名官方说明:nextjs.org/docs/advanc…

这样在js代码开头的import路径中,直接使用@表示“src目录”,不用去数有多少个"../"了。

修改jsconfig.json需要重启项目才能生效。

2.2 配置SourceMap(不建议设置)

development环境是开启sourceMap的,production环境默认不开启sourceMap。

如果需要在production环境开启sourceMap,在next.config.js进行以下配置:

module.exports = {
  productionBrowserSourceMaps: true,
}

为了不暴露项目源码,不建议进行以上设置。

2.3 设置页面title

设置页面的title很简单。

修改src/pages/_app.js:

+   import Head from 'next/head'
    
    function MyApp({ Component, pageProps }) {
M       return (
+           <>
+               <Head>
+                   <title>My Next App</title>
+               </Head>
+               <Component {...pageProps} />
+           </>
+       )
    }
    
    export default MyApp

运行项目,发现页面的title已经修改成功。

看了就会的Next.js SSR/SSG实战教程

2.4 设置HTML框架代码

在Next.js项目里有个public目录,但是里面并没有看到类似Create-React-App项目的index.html。那如何设置HTML的内容呢?

新建src/pages/_document.js,代码如下:

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
    return (
        <Html>
            <Head>
                <link rel="icon" href="/favicon.ico" />
                <meta name="description" content="Next.js演示项目" />
            </Head>
            <body>
                <Main />
                <NextScript />
            </body>
        </Html>
    )
}

_document.js也是Next.js的指定文件名,且必须在pages目录下才可生效。

你可能会好奇,既然_document.js可以设置<head>的内容,那为什么<title>却在第2.3章节的_app.js中设置呢?

这是因为_document.js只会在初始时进行预渲染。官方不建议把<title>放到_document.js中。如果你在_document.js中的<head>里设置了<title>,在build的时候会收到warning。

title规则官方说明:nextjs.org/docs/messag…

执行yarn dev,在http://localhost:3000中打开浏览器调试工具,但是并没有看到_document.js设置的内容。

看了就会的Next.js SSR/SSG实战教程

这是因为_document.js设置的内容在build后才会生效。dev模式是看不到刚刚设置的内容的。

_document.js官方说明:nextjs.org/docs/advanc…

2.5 以SSR模式运行项目

执行以下命令,build项目:

yarn build

执行后,在项目根目录下会生成一个.next的目录。这个目录就是用于运行SSR的代码,仅能运行在服务端,不能被浏览器直接运行。

然后再执行以下命令,以SSR模式运行项目:

yarn start

※注: 每次代码更新,在执行yarn start之前,一定要先执行yarn build。否则运行的并不是最新build的项目。

现在打开http://localhost:3000,看到是SSR模式运行的项目。打开调试工具,看到_document.js设置的代码已生效:

看了就会的Next.js SSR/SSG实战教程

yarn start默认是运行在3000端口,如果想运行在4000端口,可以执行以下命令:

yarn start -p 4000

更多Next.js CLI命令,可参阅官方说明。

Next.js CLI官方说明:nextjs.org/docs/api-re…

2.6 设置404/500页面

继续回到dev模式,运行yarn dev。

现在打开一个并不存在的页面路径,例如http://localhost:3000/test,页面显示如下:

看了就会的Next.js SSR/SSG实战教程

这是Next.js自带404页面。如需自定义404页面,新建src/pages/404.js:

export default function Custom404() {
    return <h1>自定义404页面 - Page Not Found</h1>
}

404.js也是Next.js的指定文件名。

再次打开http://localhost:3000/test,自定义404页面显示如下:

看了就会的Next.js SSR/SSG实战教程

同理,500错误页面也可以按照这个方式实现。

自定义错误页面官方说明:nextjs.org/docs/advanc…

🎈后续精彩章节

3 CSS预处理及使用
• 3.1 集成Sass/Scss
• 3.2 集成Less(选读)
• 3.3 集成Stylus(选读)
• 3.4 关于样式命名规范
• 3.5 配置全局样式
• 3.6 配置页面(pages)样式
4 页面路由
• 4.1 优化index页面和样式文件的存放位置
• 4.1.1 方法一:通过next.config.js配置
• 4.1.2 方法二:通过组件引入(推荐)
• 4.2 创建About页面
• 4.3 使用next/router和next/link构建导航组件
5 图片引用
• 5.1 方法一:使用原生<img>标签引入图片
• 5.2 方法二:使用next/image引用图片
6 生成静态化网站(SSG)
• 6.1 设置SSG的export命令
• 6.2 设置静态资源的basePath
• 6.3 设置SSG export输出的目录名称
7 接口请求
• 7.1 CSR/SSR/SSG 三种API请求方式
• 7.2 搭建服务端API服务
• 7.3 构建Profile页面
• 7.4 getServerSideProps和getStaticProps小节
• 7.5 搭建Next.js API Routers服务(选读)
8 动态路由
9 使用CLI命令动态生成目录
10 其他说明
11 项目Git源码

更多内容请到Git站查阅。推荐Gitee,国内网络访问顺畅。

Gitee: gitee.com/betaq/next-…

GitHub: github.com/Yuezi32/nex…