前面,刚使用vite搭建完项目,今天就看到一篇介绍next.js,魔力十足哇!!
那我们也来尝试搭建一下项目,过过瘾吧
安装Next.js
系统要求:
- 节点.js 16.8或以后。
- 支持 macOS、Windows(包括 WSL)和 Linux。
自动安装
建议使用create-next-app
,它会自动为您设置所有内容。
包括路由器,tailwindCss,typeScript,路径别名…
要创建项目,请运行:
npx create-next-app@latest
安装时,你将看到以下提示:
太爽了!! Next.js现在默认附带 TypeScript、ESLint 和 Tailwind CSS 配置。您也可以选择使用src
应用程序代码的目录。
提示后,create-next-app
将使用项目名称创建一个文件夹并安装所需的依赖项。
手动安装
若要手动创建新的 Next.js 应用,请安装所需的程序包:
终端
npm install next@latest react@latest react-dom@latest
打开package.json
并添加以下内容scripts
:
包.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
}
这些脚本是指开发应用程序的不同阶段:
dev
:运行next dev
以在开发模式下启动下一步.js。build
:运行next build
以构建用于生产用途的应用程序。start
:运行next start
以启动 Next.js 生产服务器。lint
:运行next lint
以设置 Next.js 的内置 ESLint 配置。
创建目录
next.js使用文件系统路由,这意味着文件的结构决定了应用程序中的路由。
项目结构
这app
目录
对于新应用程序,我们建议使用应用路由器。该路由器允许您使用 React 的最新功能,并且是基于社区反馈的页面路由器的演变。
要使用app
路由器,创建一个app/
文件夹,然后添加一个layout.tsx
和page.tsx
文件。当用户访问应用程序的根目录 (/
).
在内部创建根布局app/layout.tsx
与所需的<html>
和<body>
标签:
app/layout.tsx
打字稿
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
最后,创建一个主页app/page.tsx
有一些初始内容:
export default function Page() { return <h1>Hello, Next.js!</h1>}
温馨提示:如果您忘记创建
layout.tsx
,下一步.js 将在运行开发服务器时使用next dev
.
了解有关使用应用路由器的更多信息.
这pages
目录(可选)
如果您希望使用页面路由器而不是应用程序路由器,则可以创建一个pages/
项目根目录下的目录。
然后,添加一个index.tsx
文件在您的pages
文件夹。这将是您的主页(/
):
export default function Page() { return <h1>Hello, Next.js!</h1>}
接下来,添加一个_app.tsx
文件里面pages/
以定义全局布局。详细了解自定义应用文件).
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
最后,添加一个_document.tsx
文件里面pages/
以控制来自服务器的初始响应。了解有关自定义文档文件的详细信息.
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
了解有关使用页面路由器的详细信息.
温馨提示:虽然您可以在同一项目中同时使用两个路由器,但路由
app
将优先于pages
.我们建议在新项目中仅使用一个路由器,以避免混淆。
这public
文件夹(可选)
您可以选择创建一个public
文件夹,用于存储静态资产,例如图像、字体等。里面的文件public
然后,代码可以从基本 URL 开始引用目录 (/
).
那么,创建完的项目package.json如下:
运行
使用你喜欢的方式运行项目:
我比较喜欢
pnpm dev
当然,你也可以使用如下命令:
1. 运行 `npm run dev`以启动开发服务器。
2. 访问 `http://localhost:3000` 以查看您的应用程序。
3. 编辑 `app/layout.tsx`(或 `pages/index.tsx`)文件并保存它,以便在浏览器中查看更新的结果。
访问打开页面就会看到如下界面,真的是超级炫酷啊!
配置 SourceMap
development 环境是开启sourceMap的,production 环境默认不开启。如果需要在prod 环境中开启,可以在next.config.js 中进行配置,为了不暴露项目源码,不建议进行配置
javascript
复制代码
module.exports = {
productionBrowserSourceMaps: !!isDev,
}
设置页面Title
设置页面的title很简单,修改 src/layout.tsx
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "林寒的歌",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
可以看到
设置错误页面
Next.js 自带了 404、500页面,但是比较简陋,我们可以自定义页面覆盖掉自带错误页面
可以自定义 404.tsx、500.tsx或者 _error.tsx。
环境变量
环境变量还是老配方
- .env.development
- .env.production
- .env.test
CSS预处理及使用
集成Sass
Next.js 允许你导入(import)具有 .scss 和 .sass 扩展名的 Sass 文件。 你可以通过 CSS 模块以及 .module.scss 或 .module.sass 扩展名来使用组件及的 Sass。
复制代码
npm install sass
页面路由
基于文件系统的路由
Next.js 的优势是 基于文件系统的路由,对应的只需要在 src/pages 下创建的对应页面即可。
在pages/ 下创建 /about.tsx 文件,重新启动项目,即可访问 http://localhost:3000/about
next/link
Next.js 项目内的页面跳转使用<Link>
, 该组件会预先加载引用的页面。如果是项目外部链接,则使用<a>
next/router
Next.js 自带的router,通过 useRouter 来获取当前页面的pathname等信息
图片引用
使用原生
标签引入图片
本地图片资源,存放在 public/img/***
下,图片会跟随项目进行打包,图片根路径地址与项目跟路径地址一致
引用方式一
javascript
复制代码
<img
src={`${publicRuntimeConfig.basePath}/img/modelTitle/moreIcon.png`}
width="5"
height="9"
/>
publicRuntimeConfig.basePath
是根据当前环境,获取的 basePath 路径
使用 next/image 引用图片
Next.js 自带的<Image>
可以认为是<img>
的升级版,提供了非常方便的尺寸适配,加载等属性,会根据客户端的情况,进行图片的动态优化处理,但也会自动增加很多样式,会影响原生的<img>
样式,所以要根据情况使用。
如果要使用,需要在<Image>
包裹一个父容器,并为父容器定义样式。<Image>
会自动适配父容器的大小,因为可以不用为<Image>
特意设置宽高。需要注意的是,如果使用<Image>
加载图片,因为 Next.js 的安全机制,还需要在 next.config.js文件中设置图片域属性,例如设置图片域名属性 qq.com
javascript
复制代码
module.exports = {
images: {
domains: ['qq.com'],
path: `${basePath}/_next/image`,
},
}
项目中开始部分网络图片采用<Image>
加载,Next 的确会做懒加载等处理,但是在安卓低端机下存在兼容问题,无法展示,所以后来统一使用原生<img>
标签进行加载。
接口请求
CSR/SSR/SSG三种API请求方式
在Next.js 项目中,API请求有三种方式。但是根据项目的部署方式,最多可以同时有两种,即:
- CSR+SSR
- CSR+SSG
CSR 的API请求,就是常规的前端项目中的请求方式,即:由客户端浏览器发起请求,拿到数据后渲染到页面
SSR的API请求,是由服务端(Next.js的Node.js)发起请求,拿到数据后,组装到HTML里,然后将组装好的HTML返回给客户端浏览器
SSG的API请求,于SSR的API请求类似,也是由服务发起请求并把数据组装到HTML里,然后进行静态化输出。 但由于是完全静态化的,所以当API数据发生变化时,必须重新静态化才能更新页面。
getInitialProps (SSR)
getInitialProps
是在渲染页面之前就会运行的API。 如果该路径下包含该请求,则执行该请求,并将所需的数据作为props传递给页面。
- 只能在pages文件夹内的文件中使用。
getInitialProps
是SSR专用的API,这是误解。 - 直接访问后,
getInitialProps
将在服务器端运行。 - 使用next/link进行客户端路由时,在客户端执行。
getServerSideProps (SSR)
getServerSideProps
每次访问时请求数据
- 方法只会在服务端运行,每次请求都运行一遍 getServerSideProps 方法
- 如果页面通过浏览器端
Link
组件导航而来,Next会向服务端发一个请求,然后在服务端运行getServerSideProps
方法,然后返回JSON到浏览器 getServerSideProps
方法主要是升级了9.3之前的getInitialProps
方法。9.3之前的getInitialProps
方法有一个很大的缺陷是在浏览器中req和 res 对象会是 undefined 。也就是使用它的页面,如果是浏览器渲染你需要在组件内再显示地请求一次,开发体验不太好
getStaticProps(SSG)
所谓的SSG也就是静态站点生成,在build阶段将页面构建成静态的html文件,这样线上直接访问HTML文件,性能极高。
- 不会在客户端上运行,始终在服务器端运行
getStaticProps
是用于在构建时预先执行getInitialProps
进行的处理并预先生成静态文件的API- 如果是动态路由的页面,使用
getStaticPaths
方法来返回所有的路由参数,以及是否需要回落机制
getStaticPaths (SSG)
用于在使用动态路由时生成静态文件。
getStaticPaths
方法返回的fallback很有用:如果fallback是false,访问该方法没有返回的路由会404- 但是如果不想或者不方便在build阶段拿到路由参数,可以设置fallback为true,Next在访问build中没有的动态路由时候,先浏览器loading,然后服务端开始build该页面的信息,然后再返回浏览器渲染,再次访问该路由该缓存就会生效,很强大!!!
- 静态缓存目前没办法很灵活的更新!例如内容在build或者fallback生效之后发生更改,目前没办法很方便的替换缓存。
如何选择SSR还是SSG?
- 如果页面内容真动态(例如,来源数据库,且经常变化), 使用
getServerSideProps
方法的SSR。 - 如果是静态页面或者伪动态(例如,来源数据库,但是不变化),可以酌情使用SSG。
axios
使用 axios,并进行的简单的封装,进行了请求拦截及响应拦截。
开发过程中的优化方案
上面提到的本地图片引用,因为项目采用Docker构建,图片如果跟随项目一起打包,每次更新上线后,图片的缓存会失效,页面会重新加载图片,体验上很不好,后来修改为将本地图片上传至CDN。需修改配置文件中的 assetPrefix
配置为CDN文件路径,需结合next-compose-plugins
,next-optimized-images
使用
修改页面图片引用方式
shell
复制代码
npm install --save next-compose-plugins next-optimized-images
javascript
复制代码
// next.config.js
const withPlugins = require('next-compose-plugins');
const optimizedImages = require('next-optimized-images');
const nextConfig = {
assetPrefix: isDev ? '' : 'https://图片cdn地址',
distDir: 'build', // 项目文件打包路径
basePath: '',
sassOptions: {
includePaths: [path.join(__dirname, 'src/styles')],
},
...
}
module.exports = withPlugins([optimizedImages], nextConfig);
module.exports = nextConfig;
修改图片的目录,原目录在public/img/***
下,修改为src/assets/images/***
页面/组件引用方式修改
javascript
复制代码
// 导入本地图片
import demoImg from '@/assets/image/demoImg.png';
// 使用
<img src={demoImg.src} />
项目构建,执行 npm run build
后,会在项目目录下生成 build
文件夹,该文件夹下就是项目的构建结果。其中 build/static/media
文件夹存放的是项目引用的图片,并且文件名已经经过hash 处理,可通过工具上传至CDN目录。
部署
next.js官方推荐使用vercel部署