动手练一练,使用 React 和 Next.js 做一个简单的博客网站(下)

前端达人

共 7041字,需浏览 15分钟

 ·

2021-04-13 11:48

作者:Craig Bucklere
原文:Build a Blog with React and Next.js(sitepoint) 
字数:2500 字 (非直译)
阅读:  5分钟

大家好,在《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(上)》《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)》这两篇文章里,我们一起完成了一个基于 MakeDown 文档为内容页源的博客网站,学习了动态路由(Dynamic Routes)、Static Generation 相关的知识及应用,本篇文章,我们将学习如何使用服务端渲染(Server-side Rendering)、客户端渲染(Client-side Rendering)的内容,最后再和大家聊聊如何编译项目、部署站点。

一、使用服务端渲染(Server-side Rendering)

服务端渲染(SSR)发生在每次页面请求时,其相关内容逻辑比如 NodeJs 的数据请求都交由服务端处理完成后,再将内容呈现给访问的用户,因此通过此技术可以做一些复杂的业务逻辑,比如每个用户登录成功后,呈现不同的文章内容。

《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)》这篇文章里,我们使用了getStaticProps() 这个方法在项目编译时(build)处理生成 MD 动态路由相关的逻辑。如果要使用服务端渲染,我们可以使用 getServerSideProps()  函数,在页面请求时由服务端执行此函数逻辑,完成数据的渲染。

这里我们要实现一个简单的功能,在 about.js 这个页面,去请求一个笑话网站的API服务(https://official-joke-api.appspot.com/jokes/random),我们通过服务端的形式去请求数据,最后将数据处理完成后,再呈现给用户。废话不多说,我们开始动手实现吧。

1、我们现在 /pages/about.js 页面里添加  getServerSideProps() 函数,这个方法里我们使用 node-fetch 模块,获取 API 数据后,通过 props 将返回的数据通过组件属性进行传递(请看第2点的相关代码),示例代码如下:

// fetch a random joke (generated on every reqest)
export async function getServerSideProps({
  const res = await fetch('https://official-joke-api.appspot.com/jokes/random');
  return {
    props: {
      dataawait res.json()
    }
  }
}

2、接下来我们来编写组件 JSX 的部分,接收 getServerSideProps()  返回的数据,示例代码如下

export default function About({ data }{
  return (
    <Layout hero="keyboard.jpg">
      <Head>
        <title>About us</title>
        <meta name="description" content="What we do." />
      </Head>
      <h1>About us</h1>
      <p>Some information about us.</p>
      <h2>A random { data.type } joke</h2>
      <p className="setup">{ data.setup }...</p>
      <p className="punchline">{ data.punchline }</p>
      <style jsx>{`
        .setup { font-weight: bold; }
        .punchline { font-style: italic; }
      `}</style>
    </Layout>

  );
}

你可能注意到了,上述代码使用了 styled JSX 语法添加 CSS 样式。

到这里,服务端渲染的功能就完成了,我们通过  npm run dev 重启下 next.js 服务器,在浏览器上点击 http://localhost:3000/about  预览,就会看到如下图所示的界面:


二、客户端渲染(Client-side Rendering),实现暗黑浏览模式

Next.js 会在编译的时机(build time)或页面请求时在服务端完成 React 组件的渲染逻辑,但是有些功能完全可以交给客户端端浏览器处理,也是官方说道的客户端激活 (client-side hydration 不知道怎么翻译,暂且这么叫吧,借用vue相关文档的翻译)比如我们要实现暗黑和白天模式的切换,这里我们就可以用到 React.useEffect() 这个钩子处理函数。

大家有点需要格外注意,在服务端,有个细节需要注意,在服务端没有 window 这个顶层对象,如下段代码所示,执行时将会有错误提示:

// THIS WILL FAIL!
const [href, setHref] = React.useState(window.location.href);

为了修复这个问题,我们可以将初始值赋值null。

1、首先我们新建个 components/themetoggle.js 暗黑和白天浏览模式的切换组件,这里使用 useEffect() 这个钩子函数实现其逻辑,示例代码如下:

import React from 'react';
import styles from './themetoggle.module.scss';
export default function Themetoggle({
  const
    toggleStore = 'themeToggle',
    [theme, setTheme] = React.useState(null);
  React.useEffect(() => {
    if (!theme) {
      setTheme(
        localStorage.getItem(toggleStore) ||
        (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
      );
    }
    if (theme) {
      const body = document.body;
      body.classList.remove('dark''light');
      body.classList.add(theme);
      localStorage.setItem(toggleStore, theme);
    }
  }, [theme])
  return (
    <button
      onClick={() =>
 setTheme(theme === 'dark' ? 'light' : 'dark')}
      className={ styles.themetoggle + ' ' + styles[theme] }
      title="switch theme"
    />

  );
}

由于服务端无法访问客户端模式的初始值,我们先初始化为null,然后当组件成功加载至客户端时,我们使用 useEffect()  这个钩子函数进行黑暗和白天模式的逻辑处理。你可能注意到为此组件,我单独引用了一个 CSS 文件,具体源码,你可以在文末点击阅读原文链接,在本项目的完整源码中找到对应的CSS链接。

2、最后,我们将此组件添加至 components/header.js <Header> 组件中,示例代码如下:

import Navmenu from './navmenu';
import Themetoggle from './themetoggle';
import Link from 'next/link';
export default function Header({ hero }{
  hero = '/images/' + (hero || 'orb.jpg');
  return (
    <header>
      <p className="logo">...</p>
      <Themetoggle />
      <Navmenu />
      <figure>...</figure>
    </header>

  );
}

接下来,重新运行 Next.js 服务,每个页面都添加了黑暗与白天切换的模式功能 ,效果如下 GIF 动图所示:


三、编译发布网站

到这里为止,一个完整的简单博客网站到这里就介绍完了,如果你想在生产环境部署网站的话,先停在站点  Ctrl | Cmd + C , 然后运行如下命令:

npm run build

编译完成后,你会发现项目的根目录里多了个 .next 文件夹,你可以将此文件夹所有的文件内容拷贝到 Node.js 10 以上的服务器上进行部署。

你可以在此文件夹里运行 npm run start,在测试环境下去测试生产环境的站点。

四、生成静态HTML页面

Next.js 允许你将现有的站点生成静态的 HTML 页面(除了需要服务端渲染的界面),如果你为页面定义了 getServerSideProps() 服务端渲染相关的函数,导出将会失败。

如下所示,需要按照命令的先后进行运行,将站点生成静态页面:

npx next build
npx next export

编译完成后,你将会在项目的根目录看到 out 这个文件夹,如下图所示:


五、接下来你可以动手试一试

本文给大家展示了 Next.js 基础内容,并实现了博客的基础功能,接下来你可以继续完善博客的功能,不妨亲自动手试一试为博客网站添加以下功能 :

  • 添加404页面配置
  • 实现博客文章列表页的分页功能
  • 添加文章标签功能
  • 添加 SSR 功能
  • 尝试从其他内容源获取博客文章内容(服务端API数据接口、wordpress等)

六、相关阅读

《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(上)》

《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)》

结束语

到这里,本案例就介绍完了,本案例的完整源码,你可以点击阅读原文下载本案例的完整源码。

Next.js 是一个灵活的应用程序框架,可以帮助你构建任何类型的 web 项目,对于博客网站这类需求,很容易满足实现。Next.js 这个框架已经很成熟,而且定期维护,如果你已很熟悉 React 这个前端框架,选择 Next.js 构建站点将会是一个很不错的选择。

浏览 31
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报