创建具有身份验证、数据和存储的全栈 Next.js 应用程序

2025-05-24

创建具有身份验证、数据和存储的全栈 Next.js 应用程序

2024 年 6 月 27 日:这篇博文使用 Amplify Gen 1,如果您要启动新的 Amplify 应用程序,我建议您尝试Gen 2

Next.js 是我最喜欢的 Web 开发工具之一,但它是一个前端框架。如何使用它构建一个全栈应用程序?在本教程中,我们将构建一个服务器端渲染的 Next.js 应用,该应用具有数据库支持的后端、静态图像存储和身份验证功能。它将以国家公园为主题——登录用户可以创建新的公园,并且每个人都可以查看所有已添加的公园。

如果您是 Next.js 新手,我写了一篇关于如何开始使用它的教程。如果您是 AWS Amplify 新手,这里也有一个关于它的教程

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

创建您的应用后端

首先,创建一个新的 Next 应用:

npx create-next-app national-parks
Enter fullscreen mode Exit fullscreen mode

确保您已安装 Amplify CLI,如果没有,请按照这些说明操作!

然后,为您的项目初始化 Amplify。您应该能够接受它为您生成的配置,然后选择您的 AWS 配置文件或输入您的访问密钥。

amplify init
Enter fullscreen mode Exit fullscreen mode

然后我们将配置所需的服务。首先,我们将添加身份验证。

amplify add auth
Enter fullscreen mode Exit fullscreen mode

像这样回答接下来的问题:

Do you want to use the default authentication and security configuration? Default configuration
How do you want users to be able to sign in? Username
Do you want to configure advanced settings? No, I am done.
Enter fullscreen mode Exit fullscreen mode

现在,我们将为应用添加存储空间。除了“谁应该拥有访问权限”之外,所有问题都选择默认配置选项。在此,授权经过身份验证的用户访问所有操作,而未经身份验证的用户则只能读取数据。

amplify add storage

? Please select from one of the below mentioned services: Content (Images, audio, video, etc.)
? Please provide a friendly name for your resource that will be used to label this category in the project: s37cd140d1
? Please provide bucket name: nationalparkbrowser248f6fd94d4f46f99a951df475e8
? Who should have access: Auth and guest users
? What kind of access do you want for Authenticated users? create/update, read, delete
? What kind of access do you want for Guest users? read
? Do you want to add a Lambda Trigger for your S3 Bucket? No
Enter fullscreen mode Exit fullscreen mode

最后,我们将创建一个 API。我们将选择 GraphQL 并使用 API 密钥进行授权。在文本编辑器中打开 GraphQL 架构。

amplify add api

? Please select from one of the below mentioned services: GraphQL
? Provide API name: nationalparks
? Choose the default authorization type for the API API key
? Enter a description for the API key:
? After how many days from now the API key should expire (1-365): 7
? Do you want to configure advanced settings for the GraphQL API No, I am done.
? Do you have an annotated GraphQL schema? No
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)
Enter fullscreen mode Exit fullscreen mode

如果您的 schema.graphql 文件未在文本编辑器中打开,请将其打开。它位于 下amplify/backend/api/nationalparks。其中已经有一个示例 GraphQL 模式,但我们将对其进行编辑,使其具有所需的数据格式。

我们将创建两个模型:S3Object 和 Park。这两个模型Park用于存储公园信息——每个公园都有一个 ID、一个名称和一个图片。该图片将引用存储在 Amazon S3 中的图片(我们在运行 时创建了一个存储桶amplify add storage)。它们S3Object将包含存储在 S3 上的图片的相关信息——存储桶、区域和密钥。我们将使用密钥在应用中访问图片。

type S3Object {
  bucket: String!
  region: String!
  key: String!
}

type Park @model {
  id: ID!
  name: String!
  image: S3Object
}
Enter fullscreen mode Exit fullscreen mode

现在运行amplify push,将您的资源部署到云端!您现在拥有一个完全部署的后端。

安装 Amplify 库。这将允许我们使用 JavaScript 辅助代码和 React 组件来加快前端开发速度。

npm i aws-amplify @aws-amplify/ui-react
Enter fullscreen mode Exit fullscreen mode

后端部署完成后,我们需要使用 将前端链接到后端Amplify.configure()。我们将使用src/aws-exports.jsAmplify 自动生成的文件中的配置信息,并确保将ssr标志设置为,true以便我们可以从服务器上的 API 中提取数据。

将其添加到您的顶部pages/_app.js

import Amplify from 'aws-amplify'
import config from '../src/aws-exports'

Amplify.configure({ ...config, ssr: true })
Enter fullscreen mode Exit fullscreen mode

前端逻辑

呼!配置代码写完了,现在我们可以编写前端 React 逻辑了。首先,我们创建一个表单来创建一个新的公园。创建一个文件pages/create-park.js,其中包含一个渲染表单的页面。然后在该文件中创建一个 React 组件。

// create-park.js
function CreatePark () {
  return <h1>Create Park</h1>
}

export default CreatePark
Enter fullscreen mode Exit fullscreen mode

然后,我们将使用withAuthenticator高阶组件在进入/create-park页面之前要求登录。它还将启用注册并要求帐户确认。

// create-park.js
import { withAuthenticator } from '@aws-amplify/ui-react'

function CreatePark () {
  return <h1>Create Park</h1>
}

export default withAuthenticator(CreatePark)
Enter fullscreen mode Exit fullscreen mode

现在我们将创建一个 React 表单,用户可以在其中输入公园的名称和图像。

// create-park.js
import { useState } from 'react'
import { withAuthenticator } from '@aws-amplify/ui-react'

function CreatePark () {
  const [name, setName] = useState('')
  const [image, setImage] = useState('')

  const handleSubmit = async () => {

  }

  return (
    <form onSubmit={handleSubmit}>
      <h2>Create a Park</h2>
      <label htmlFor='name'>Name</label>
      <input type='text' id='name' onChange={e => setName(e.target.value)} />
      <label htmlFor='image'>Image</label>
      <input type='file' id='image' onChange={e => setImage(e.target.files[0])} />
      <input type='submit' value='create' />
    </form>
  )
}

export default withAuthenticator(CreatePark)
Enter fullscreen mode Exit fullscreen mode

最后,我们将实现handleSubmit将用户图像上传到 S3 并使用 GraphQL API 将新创建的公园存储到数据库中的功能。我们将从aws-exports.jsAmplify 目录中导入配置信息以及 Amplify 生成的一个 GraphQL 变更src/graphql

然后,我们将使用图片Storage.put()名称作为键、图片本身作为值来上传图片。之后,我们将使用API.graphql用户输入的数据和 S3 存储桶的配置信息来运行 graphQL 变更。

// create-park.js
import { useState } from 'react'
import { API, Storage } from 'aws-amplify'
import { withAuthenticator } from '@aws-amplify/ui-react'

import { createPark } from '../src/graphql/mutations'
import config from '../src/aws-exports'

function CreatePark () {
  const [name, setName] = useState('')
  const [image, setImage] = useState('')

  const handleSubmit = async e => {
    e.preventDefault()
    // upload the image to S3
    const uploadedImage = await Storage.put(image.name, image)
    console.log(uploadedImage)
    // submit the GraphQL query 
    const newPark = await API.graphql({
      query: createPark,
      variables: {
        input: {
          name,
          image: {
            // use the image's region and bucket (from aws-exports) as well as the key from the uploaded image
            region: config.aws_user_files_s3_bucket_region,
            bucket: config.aws_user_files_s3_bucket,
            key: uploadedImage.key
          }
        }
      }
    })
    console.log(newPark)
  }

  return (
    <form onSubmit={handleSubmit}>
      <h2>Create a Park</h2>
      <label htmlFor='name'>Name</label>
      <input type='text' id='name' onChange={e => setName(e.target.value)} />
      <label htmlFor='image'>Image</label>
      <input type='file' id='image' onChange={e => setImage(e.target.files[0])} />
      <input type='submit' value='create' />
    </form>
  )
}

export default withAuthenticator(CreatePark)
Enter fullscreen mode Exit fullscreen mode

如果您愿意,可以把几行 CSS 粘贴到styles/globals.css文件中,让应用程序看起来更美观。

amplify-s3-image {
  --width: 70%;
  overflow: hidden;
  margin: 0 auto;
}

.container {
  max-width: 1000px;
  margin: 0 auto;
  padding: 0 2rem;
  text-align: center;
}

.img-square img h2 {
  margin: 0 auto;
  text-align: center;
}
Enter fullscreen mode Exit fullscreen mode

最后,我们将在索引页上列出所有公园。我们将使用listParks生成的 graphql 查询src/graphql/queries.js来获取公园,并使用AmplifyS3Image组件在页面上渲染图像。我们将在服务器端获取公园信息,以便我们的应用在添加新公园时动态更新。

import Head from 'next/head'
import { withSSRContext } from 'aws-amplify'
import { listParks } from '../src/graphql/queries'
import { AmplifyS3Image } from '@aws-amplify/ui-react'
import Link from 'next/link'

export async function getServerSideProps () {
  const SSR = withSSRContext()
  const { data } = await SSR.API.graphql({ query: listParks })
  return {
    props: {
      parks: data.listParks.items
    }
  }
}

export default function Home ({ parks }) {
  return (
    <div>
      <Head>
        <title>National Parks</title>
      </Head>
      <div className='container'>
        <h1>National Parks <Link href='/create-park'>(+)</Link></h1>
        <div className='img-grid'>
          {parks.map(park => {
            return (
              <div key={park.id} className='img-square'>
                <h2>{park.name}</h2>
                {/* use the AmplifyS3Image component to render the park's image using its S3 key */}
                <AmplifyS3Image imgKey={park.image.key} height='200px' />
              </div>
            )
          })}
        </div>
      </div>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

前端部署

现在我们的应用已经拥有完整的前端了!让我们通过 Amplify 托管服务进行部署。将您的代码推送到 GitHub 存储库,然后打开应用的Amplify 控制台。点击 ,frontend environments tab然后点击connect app按钮。选择您的存储库,使用自动生成的配置,然后save and deploy。只需几分钟,您的应用即可上线!

无需额外配置,Amplify 会自动推断您正在创建 SSR Next.js 应用,并为您的应用部署所需的托管资源。如果您感兴趣,可以查看更多信息!

清理

您可能不想保留该应用程序的部署,在这种情况下,您可以点击delete appAWS 控制台中的按钮或amplify delete从命令行运行。这将从您的 AWS 账户中取消配置后端资源!

AWS Amplify 允许您使您的 Next.js 应用程序具有数据、图像存储和身份验证的全栈功能,而无需具备丰富的云或全栈开发知识。

文章来源:https://dev.to/aws/create-a-fullstack-next-js-app-with-authentication-data-and-storage-47od
PREV
使用 Amazon S3 和 AWS Amplify 构建音乐共享应用程序
NEXT
使用 React 和 AWS 构建无服务器直播平台