Next.js的三个新功能以及如何使用它们

337 阅读7分钟

AWS Amplify最近增加了对Next.js 10功能的支持,包括增量静态再生、可选的捕获所有路由和图像优化。在这篇文章中,我们将深入探讨这些功能中的每一个,如何使用它们实现一个全栈应用,以及如何将它们部署到AWS上让我们深入了解一下。

请注意,我是AWS Amplify团队的开发者倡导者,如果你有任何反馈或问题,请联系我或在我们的Discord上询问 - discord.gg/amplify!

如果你是Next.js的新手,可以先看看这个教程,让你开始学习如果你想看的话,我还写了这个关于创建全栈Next.js应用程序的教程。

设置

首先,让我们创建一个Next.js应用程序。

npx create-next-app next10-blog

现在,让我们创建我们的应用程序的后端。进入Amplify沙盒,然后 "开始"。在下一页中选择 "数据",然后从博客模式开始。

data selected with blog schema

我删除了 "Blog "模型,并将 "content "字段添加到Post模型中。

然后,你可以跳过 "在你的应用程序中进行本地测试 "页面,直接用你的AWS账户进行部署。按照指导的步骤部署你的应用程序!

一旦你的后端部署完毕,进入你的应用程序的管理界面,然后点击右上方的 "本地设置说明"。将Amplify拉动命令运行到你创建的Next应用中。同时,安装AWS Amplify库以及TypeScript--你的代码不需要TypeScript,只是为了生成DataStore模型。

amplify pull --appId your-appID --envName staging
npm install aws-amplify typescript

我还打算为我的应用程序生成一些博客文章。在Amplify管理界面上点击 "管理应用程序内容"。在 "Actions "下拉菜单中,你会看到一个 "自动生成数据 "的选项。继续并生成10个博客文章。你会看到标题和描述弹出!

现在是代码时间!打开你在几步之前生成的Next.js应用程序。打开_app.js文件,广告如下。这将使Amplify的前端库自动与你创建的后端资源相联系!我们还将启用服务器端的资源。我们还将启用服务器端的渲染。

import Amplify from 'aws-amplify'
import awsconfig from '../src/aws-exports'
Amplify.configure({ ...awsconfig, ssr: true })

现在,我们将实现index.js 路线 -- 这个主页将列出我们所有的博客文章,并将它们链接到一个显示一篇文章的二级页面。我们将为这个路由使用SSR

首先,我将从生成的src/models 目录中导入我的数据模型。我还将从Amplify导入withSSRContext 函数--这将使我们能够在服务器端运行我们的查询。

import { withSSRContext } from 'aws-amplify'
import { Post } from '../src/models'

现在,创建一个getServerSideProps函数。然后我们将允许Amplify在服务器上运行,withSSRContext ,我们也将为它提供请求信息。然后,我们将运行一个查询,以获得我们所有的博客文章!最后,我们将返回一个对象,提供我们的模型作为props!你可以手动转换为JSON,或者使用 serializeModel函数。

export async function getServerSideProps (context) {
  const SSR = withSSRContext(context.req)
  const models = await SSR.DataStore.query(Post)

  return {
    props: {
      models: JSON.parse(JSON.stringify(models))
    }
  }
}

现在,我们可以通过帖子进行映射,并在页面上呈现它们!

export default function Home ({ posts }) {
  return (
    <div>
      <Head>
        <title>Amplify + Next</title>
        <meta name='description' content='Amplify + Next!' />
      </Head>

      <main>
        {posts.map(post => (
          <div key={post.id}>
            <a href={`/post/${post.id}`}>
              <h2>{post.title}</h2>
            </a>
          </div>
        ))}
      </main>
    </div>
  )
}

ISR

现在来看看Next 10的新功能吧!首先,我们将实现ISR,即增量静态再生。通常,当你使用静态网站生成时,当你部署你的应用程序时,网站会建立一次。但在很多情况下,你希望当你的数据发生变化时,你的静态页面能够更新。ISR实现了这一点 -- 你向你的getStaticProps 提供一个重新验证的时间,然后一旦达到这个时间窗口,页面就会重新生成。从本质上讲,这些页面最初是静态生成的,在提供的再生时间之前点击该页面的初始用户会得到静态生成的网站。然后,在再生时间到达后,对该页面的下一个请求会触发该页面在后台重建 -- 触发再生的用户会得到旧版本的页面,但后续用户会得到新版本。这在电子商务场景中特别有帮助,在我们的例子中,一个博客,你不需要在每次添加新的文章时都重新部署

我们将创建一个显示一篇博客文章的页面。首先,我们将在/pages/ 目录中创建一个post/[post].js 页面组件。让我们从我们将需要的导入开始。

import { withSSRContext } from 'aws-amplify'
import { useRouter } from 'next/router'

import { Post } from '../../src/models'

现在,我们将创建一个getStaticPaths 函数,为每个帖子生成一个静态页面。我们将查询我们所有的帖子,通过它们进行映射,然后从函数中返回它们。我们还将在这里提供一个fallback: true ,这将使Next.js在遇到非生成路径时不会立即给出一个404,而是在后台尝试生成页面,然后渲染它。

export async function getStaticPaths() {
  const SSR = withSSRContext()
  const posts = await SSR.DataStore.query(Post)
  const paths = posts.map(post => ({
    params: { post: post.id }
  }))

  return {
    paths, fallback: true
  }
}

现在,我们将实现我们的getStaticProps 。这次我们将使用它的id来查询一个帖子。然后我们将在props对象中返回帖子,我们还将添加revalidate key。这将为我们的页面实现ISR!我将提供10,这将使重新验证的时间为10秒。你可以根据你的使用情况来改变这个值。

export async function getStaticProps(context) {
  const SSR = withSSRContext(context.req)
  const post = await SSR.DataStore.query(Post, context.params.post)
  return {
    props: {
      post: JSON.parse(JSON.stringify(post))
    },
    revalidate: 10
  }
}

现在,我们将在页面上渲染帖子!我将使用router.isFallback ,以便在非生成路径被击中时呈现加载指示器--我这样做只是因为我使用了fallback: true!

export default function PostPage({ post }) {
  const router = useRouter()

  if (router.isFallback) {
    return <div>Loading...</div>
  }

  return (
    <div>
      <h2>{post.title}</h2>
      <p>{post.content}</p>
    </div>
  )
}

然后,我将把我的代码推送到GitHub。然后,我将回到我的应用程序的AWS控制台页面。你应该看到backend environments 页面上有你的管理界面链接。前往frontend environments 选项卡,你就可以选择部署你的应用程序了。

按照指导性的部署步骤,你应该能够从GitHub中选择你的分支,并使用从package.json中检测到的默认构建脚本你还会看到关于部署内容的信息--在这种情况下,你会有一个Lambda@Edge函数来为你处理ISR!

可选的 "捕捉所有 "路线

我们还有两个更快捷的功能要谈,首先是可选的捕捉所有路由。这些允许你创建一个可以在它后面有任何参数的路由。我们将为一个关于页面创建一个路由。/about 应该呈现这个页面,但是/about/hi/about/ali/spittel 也应该如此。我们可以通过创建一个页面组件,然后把它放在双括号里,在它前面加上三个点来实现。

首先,为该页面创建文件。

/pages/about/[[...about.js]]

现在,我将实现这个组件。我将使用Next中的useRouter ,以获得关于路由的信息,然后我将在页面上渲染路由参数试试/about,/about/hi/about/ali/spittel ,看看这有什么变化!

import { useRouter } from 'next/router'
import React from 'react'

export default function About(props) {
  const routeData = useRouter()
  return (
    <div>
      {JSON.stringify(routeData.query)}
    </div>
  )
}

现在把你的代码推送到GitHub,Amplify会自动把你的前端与新的关于页面重新部署起来

图片组件

最后,让我们试试Next.js的Image 组件。这个组件可以自动实现图像优化,包括调整大小、优化以及在浏览器支持的情况下提供不同的图像类型,如webp。我在/public目录中添加了一张我的狗Blair的照片。

然后,我在index.js 文件中导入了Image 组件

import Image from 'next/image'

然后,我在页面上渲染了她的图片!

 <Image src='/blair.jpeg' alt='Fluffy white dog lying on a couch' height={200} width={150} />

我再次推送到GitHub,重新部署了这个网站

总结

我希望这个教程能帮助你实现Next.js的一些新功能,并将它们部署到AWS Amplify。如果你想关闭你的应用程序,你可以从你的CLI运行amplify delete ,你的代码将在本地持续存在,但它将不再被部署到云端。如果你对AWS Amplify或本教程有任何反馈,请告诉我!