Next.js 学习笔记
ref: Create a Next.js App
Code splitting 代码拆分
能够自动进行代码拆分,仅在需要加载时加载对应的页面的代码。即首页加载时,其他页面还没初始化呢。
即使页面总量很大,也能保证首页的快速加载。这意味着页面之间是独立的,因此某些报错的页面不会影响正常页面的渲染。
prefetching 预加载
在生产环境构建 production build 的 Next.js,只要包含有 Link
组件出现在视口时,Next.js 会在后台自动预先加载(prefetch)该页面中的内容。当用户点击时,目标页面已经加载完成了,因此页面能瞬间打开。
总结
Next.js 能够自动地优化应用,使用了诸如 代码拆分(Code splitting)、客户端路由(Client-side navigation)以及预加载(prefetching,在生产环境中)。
关于 Link
- Link 只是一个语义化空壳,里面还是要加上一个
<a>
把内容包起来的。 - Link 只适用于组件间的路由转换,如果是外部链接,直接用
<a>
即可。 - Link 上不能够加上属性(如 className、style 等),要加就直接加在里面的
<a>
标签上。
关于 CSS/SASS
- Next.js 自带对 SASS 的支持,直接 import 就可以用了。
- 在 JSX 中直接写入 CSS:styled-jsx,能够让我们直接在 js 文件中的 React 组件中写 CSS,样式的将会是 scoped 的,即不会影响到别的组件。
- Next.js 中自带对 styled-jsx 的支持,能够直接使用。此外也能够使用其他 CSS-in-JS 的库,如:styled-components 或者 emotion
<style jsx>{`
main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
`}</style>
关于静态资源
静态资源(如图片、robots.txt
、谷歌网站验证文件)都被放在了 top-level 目录 /public
里了。在 pages
的 js 页面中引用 public 目录中的资源可以直接像在根目录中引用一样。
<img src="/vercel.svg" className="logo" />
元数据
由于 JSX 本质上还是 JS,所以在处理元数据时需要不能直接用 createElement 方法(即 JSX)生成。因此需要引入元数据 React 组件。
从 next/head
引入的 <Head>
是一个 Next.js 的 React 组件,用来构建页面的头部。里面能够定义页面的 <title>
了。
Layout 组件
- 接收一个 { 对象 } 作为参数,返回一个包起这个对象的 React 组件。类似于 Wrapper 的一个东西。实际上作用就是一个负责布局、添加样式的东西。
- 在使用时只需要将该 Layout 引入,然后再把这个 Layout 包起想要添加布局的组件即可。
CSS Module (.module.css)
实际上就是一个 CSS 文件,只不过后缀从 .css
变成了 .module.css
。
- 使用的时候把
.module.css
文件直接当作一个模块引入到 js 文件中,并把它赋给一个叫 styles 的样式对象。 - 这个 styles 实际上就是一个样式模块,在 JSX 中使用的时候,直接在属性那里写
className = { styles.<在样式模块中对应的样式类名> }
。但是实际上并不需要我们给类起名,CSS Module 会自动给该 JSX 组件生成一个独一无二的类名,并应用上我们指定的 样式模块 中的样式。 - 它的目的是让我们能够为每个页面加载最少的 CSS 文件,从而缩小 包 bundle 的大小。
- Next.js 会在构建时自动提取 JS 包里的 CSS Modules ,并且自动生成对应的
.css
文件。
全局样式 (_app.js)
- 全局样式放在了
pages/_app.js
中,我们在里面定义一个返回值是一个<Component>
(Component 为对应输入的组件对象)的函数 App,它将会是一个 top-level 的组件,在不同的组件中都会使用到它,即使在不同页面中跳转,我们也可以用它来保存 state。 - 全局样式 global CSS 位于 top-level 的
styles/global.css
,在pages/_app.js
中 import 该样式文件即可生效(修改了_app.js
必须 restart 应用)。 - 因为修改全局样式会影响所有的元素,因此在
pages/_app.js
之外不能够引入global.css
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
classnames 用于增删 class
classnames 是一个简单的库,能够让我们增删 class。 用法:
import styles from "./alert.module.css";
import cn from "classnames";
export default function Alert({ children, type }) {
return (
<div
className={cn({
[styles.success]: type === "success",
[styles.error]: type === "error",
})}
>
{children}
</div>
);
}
alert.module.css
.success {
color: green;
}
.error {
color: red;
}
PostCSS
默认 Next.js 使用了 PostCSS 进行 CSS 的编译。需要配置 PostCSS 可以在 top-level 新建一个 postcss.config.js
,这对使用如 Tailwind CSS 很有用。
安装:
npm install tailwindcss postcss-preset-env postcss-flexbugs-fixes
配置 postcss.config.js
:
module.exports = {
plugins: [
"tailwindcss",
"postcss-flexbugs-fixes",
[
"postcss-preset-env",
{
autoprefixer: {
flexbox: "no-2009",
},
stage: 3,
features: {
"custom-properties": false,
},
},
],
],
};
配置 tailwind.config.js
:
// tailwind.config.js
module.exports = {
purge: [
// Use *.tsx if using TypeScript
"./pages/**/*.js",
"./components/**/*.js",
],
// ...
};
使用了 tailwind.js 可以,移除没用到的 css 文件。
使用 Sass
因为默认就配置好了,直接引入 Sass 都是可以的, 包括 .sass 和 .scss 两种拓展名的文件都能直接引入。可以使用组件级的 Sass,即以 .module.scss
和 .module.sass
结尾的。
事前需要先安装好 sass
: npm install sass
预渲染 Pre-rendering
Next.js 最重要的概念之一,默认会对每个页面都进行预渲染(Pre-rendering)。
- 这个在服务端进行的,即 SSR(Server-Side Rendering)。
- Next.js 会提前对每个页面生成一份 HTML 代码,而不是在客户端拿到 raw HTML 让浏览器去解析、渲染整个页面。
- 预渲染能够:提高性能 + 优化 SEO
- 每个生成的 HTML 页面都只包含必须的 JS 代码。当页面被加载完成后,其 JS 代码才会开始运行并使得页面完全可交互的,这个过程叫做 水合(Hydration)。
禁用 JS
如果我们 disable javascript(F12,ctrl+shift+p, "disable javasctipt"),将会看到页面可以在没有 JS 的情况下渲染。这是因为 Next.js 进行了预渲染得出的 HTML。
如果对一个纯粹的 React 页面(没使用 Next.js),我们将什么也看不见(因为 React 本质就是 JS 写 HTML,没 JS 写不了的)。
两种预渲染
- 静态生成 Static Generation:仅在构建时生成 HTML,以后每次请求都复用这个生成的预渲染 HTML。
- 服务端渲染 SSR:对每次请求都用预渲染方法生成一个 HTML。
Next.js 能够让我们自己选择每个页面是通过哪种预渲染方式。我们能创建混合 App,即对大部分页面使用 静态生成,对小部分页面使用 服务器渲染。
什么时候使用
推荐用 静态生成 Static Generation,因为可以只构建一次,然后放在 CDN 上去让用户访问,能够比 SSR 每次都通过服务器响应请求并进行一次预渲染更快。
静态生成 Static Generation 适用于一切能够在用户请求之前就把页面整好的情况,如:
- 电商
- 博客
- 主页
- 帮助、文档
如果页面内容和每次请求都相关,显示更新数据等,应该考虑 SSR,每次都让服务器预渲染一次,虽然慢些,但能使页面保持最新。
使用 getStaticProps
来静态生成
每当我们 export 一个组件时,我们可以同时 export 一个 async
的函数getStaticProps
。
- 它能够在生产环境下(production)构建项目时运行,函数内我们可以进行一些外部数据获取,并把外部数据自动返回给页面组件作为参数。
- 在开发环境下(development),该函数在组件遇到每一个请求时都会运行一遍。
- 如果需要在每次请求时都运行一次数据获取,应该使用 服务器端渲染 SSR
getStaticProps
只能够在一个页面 page 中存在并 export 出去(如pages/index.js
),因为 React 有个限制,就是它需要等到把所有数据都加载完了才能够渲染这个页面。
export default function Home(props) { ... }
export async function getStaticProps() {
// Get external data from the file system, API, DB, etc.
const data = ...
// The value of the `props` key will be
// passed to the `Home` component
return {
props: ...
}
}
getStaticProps
获取的数据来源多种多样
- 从 file system 读取
- fetch 获取外部资源(Next.js 自带实现,不用 import 了)
- 从后端数据库获取(因为
getStaticProps
仅在服务器端运行,因此不用担心它被发送到浏览器执行)
使用 getServerSideProps
来 SSR
当我们需要每次请求都进行一次数据请求(fetch),我们应该使用的就是 SSR,这时请求数据的方法不是 getStaticProps
而是 getServerSideProps
了。
export async function getServerSideProps(context) {
return {
props: {
// props for your component
},
};
}
相对于 getStaticProps
,getServerSideProps
方法多了一个 context
参数,它包含了当前请求的特定参数。
通常情况下,如果不是获取的数据和请求息息相关的,不建议使用 getServerSideProps
。它的首个比特时间(TTFB,Time to first byte)会比 getStaticProps
更慢,是因为每次它都需要服务器进行计算预渲染的结果,并且它在没配置的情况下是不能够被 CDN 缓存的。
数据的客户端渲染 CSR
注意不是页面的客户端渲染。
- 将页面不需要动态数据的部分 静态生成(预渲染)
- 当页面加载时,使用 JS 获取外部数据并补充页面剩余的部分
- 可用于用户 dashboard 页,私人的页面、不需要 SEO、不需要预渲染、经常需要更新
SWR 钩子
如果时在客户端获取数据,使用 Next.js 制作的 swr 钩子能够很好地实现数据 fetch。它能够缓存、重新认证、焦点捕捉、定间隔重新获取等。
全称 stale-while-revalidate,详见官方文档
import useSWR from "swr";
function Profile() {
const { data, error } = useSWR("/api/user", fetch);
if (error) return <div>failed to load</div>;
if (!data) return <div>loading...</div>;
return <div>hello {data.name}!</div>;
}
动态路由
可创建静态路由如 pages/posts/[id].js
,所有用左右中括号括起来的在 Next.js 中都是动态路由。
使用 getStaticPaths
来获取所有可能的博客路径,使用 getStaticProps
来获取一个给定 id 的特定文章。
动态路由匹配多个路径 catch-all routes
pages/posts/[...id].js
能匹配 /posts/a
, /posts/a/b
, /posts/a/b/c
等等。
在 getStaticPaths
中的 id 就需要返回一个数组了,因为这种多层级的路由是以数组形式设定的。
return [
{
params: {
// 能够生成 /posts/a/b/c
id: ["a", "b", "c"],
},
},
];
fallback
在 getStaticPaths
的返回值有一个参数 fallback: false
,意思是当你遇到 getAllPaths
的路径列表之外的页面的时候的处理是怎么样的。
fallback: false
即所有不在getStaticPaths
返回值里的路径都会返回 404 Pagefallback: true
, 那么getStaticProps
的行为就会被改变了:1)所有的getAllPaths
的路径列表里的页面会在构建时渲染成 HTML 2)所有路径列表之外的路径不会导致 404 Page,而是在对此路径的第一个请求时提供页面的“后备”(fallback)版本 3)后台,Next.js 将静态生成请求的路径,后续请求都会对应该生成的后备页面。fallback: blocking
,即新的路径会被 SSR 且使用了getStaticProps
里面的参数,这个结果会被缓存,因此该路径只会被请求一次。
路由
直接使用 Next.js 路由,应该 import 一个 useRouter
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!