这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天
Next.js实战项目
CSR、SSR、SSG
CSR
客户端渲染(Client-Side Rendering)。常见B端 WEB应用开发模式,前后端分离,服务器压力相对更轻,渲染工作在客户端进行,服务器直接返回不加工的 HTML用户在后续访问操作。
SSR
SSR(Server-Side Rendering)。不是什么新鲜的概念,从原先的JSP/ PHP就已经体现了服务器端渲染。
SSG
静态站点生成(Static Site Generation),在构建的时候直接把结果页面输出html到磁盘,每次访问直接把html返回给客户端,相当于一个静态资源。
SSR、SSG的优势
1.利于SEO
浏览器的推广程度,取决于搜索引擎对站点检索的排名,搜索引擎可以理解是一种爬虫,它会爬取指定页面的HTML,并根据用户输入的关键词对页面内容进行排序检索,最后形成我们看到的结果。
2.更短的首屏时间
SSR / SSG只需要请求一个HTML文件就能展现出页面,虽然在服务器上会调取接口,但服务器之间的通信要远比客户端快,甚至是同一台服务器上的本地接口调取。因为不再需要请求大量js文件,这就使得SSR / SSG可以拥有更短的首屏时间。
什么是Next.js
Next.js是一个构建于Node.js之上的开源Web 开发框架,支持基于React 的 Web应用程序功能,例如服务端渲染和生成静态网站。
特点:
上手快,能力集全,而且覆盖了足够多的性能优化和生态。
对于新同学掌握前后端一体化的开发模式很友好,所以说,Next.js 更像是一个框架,包含了路由、优化、SSR 等一系列功能。
Next.js的实现
(参考文章:十分钟上手 Next.js - 知乎 (zhihu.com))
起步
和 create-react-app 一样,Next.js 一样有个 create-next-app 的脚手架。
create-next-app demo
使用上面命令后就可以创建一个 Next.js 框架的 React 项目。
路由
Next.js 也提供了路由系统,采用名字约定路由
pages/index.js对应/pages/xxx/first.js对应/xxx/first
使用 Link 组件来做路由跳转
function FirstPost() {
return (
<>
<h1>First Post</h1>
<h2>
<Link href="/">
<a>Back to home</a>
</Link>
</h2>
</>
)
}
有的时候需要跳转到外链,可以使用 <a> 标签就可以。
静态资源
静态资源用的最多的就是 图片 了,Next.js 提供了 Image 组件来替代 img。
Image 组件的好处就是可以提高网页加载图片的性能,可以自动按需加载,当图片进入视图时再加载图片。
除了相对路径引入,还可以将图片放在 public/images/ 下,然后用 “绝对路径” 引入。
export default function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src="/profile.jpg"
alt="Picture of the author"
width={500}
height={500}
/>
<p>Welcome to my homepage!</p>
</>
)
}
MetaData
网页的 Meta Data 主要是指 <head> 元素里的内容,Next.js 直接提供了一个 <Head> 组件来包裹这些 Meta Data。
<Head>
<title>First Post</title>
</Head>
好处就是可以在不同的页面组件里写不同的 Meta Data。
CSS
样式这一块和 create-react-app 差不多,使用 CSS module,命名为 xxx.module.css 就可以了,否则别的 CSS 文件都需要 import 'xxx.css' 来引入 CSS 样式。
需要注意的是全局样式引入只能在 pages/_app.js 的根文件里引入。
上述操作 Sass 同理。
预渲染(略)
动态路由
所谓动态路由就是可以生成 posts/:id 这样的路由,:id 可以为 post 的 id。文件命名只需要写成 [id].js 就可以了。
在页面组件文件里,可以通过前面说到的 getStaticProps 和 getServerSideProps 获取 params:
export async function getStaticProps({ params }) {
const postData = getPostData(params.id)
return {
props: {
postData
}
}
}
其中,pages/posts/[...id].js 会匹配 /posts/a/b 路由和 /posts/a,... 为全匹配。
API
除了正常写页面外,有时候我们还需要提供 API 接口,可以在 pages/api 下添加文件,文件名则为 API 名。
注意:不能在 getStaticProps 和 getStaticPaths 里添加 fetch 数据,因为他们只在 server side 运行,不会在 client side 运行,应该使用 helper function 来获取数据。
API 代码将不会在 client side 的 bundle 里。
核心功能讲解
(1)首页功能实现
- 页面&动画&多媒体适配
- BFF
- Strapi
(2)功能页功能实现
- 页面&动画&多媒体适配
- BFF
- Strapi分页:/api/articles?/pagination[page]=1&pagination[pageSize]=10(按10个/页分页,返回第一页的数据)
- 多媒体格式的转换
-
- markdown转Html:npm install showdown --save
-
- html转dom: dangerouslySetInnerHTML
-
- 公共样式的定义
(3)主题化功能实现
- 基础样式和背景的抽离
- 主题化context全局注入
- 从注入数据中取出theme和setTheme
- 多进程间的主题同步
如有错误,请多指教~