---
# System prepended metadata

title: 建立 Amplify Next 專案 + Gen2 新增資料庫
tags: [Amplify, Next]

---

# 建立 Amplify Next 專案 + 設定 Gen2 Backend 功能

###### 參考資料：
* https://docs.amplify.aws/nextjs/start/quickstart/nextjs-app-router-client-components/
* https://docs.amplify.aws/react/build-a-backend/data/set-up-data/
* https://docs.amplify.aws/react/build-a-backend/auth/use-existing-cognito-resources/

---

AWS 提供的 Amplify 有資料庫功能結合前端框架，很適合個人網站或客製化的中小型網站使用，實現全端架構的網站！

---

### 建立專案
###### Note：建立新的 Amplify App 需要 AWS管理員 開放 [IAM 角色權限](https://docs.aws.amazon.com/zh_tw/amplify/latest/userguide/security-iam-awsmanpol.html)
1. 先[從模板建立專案](https://github.com/new?template_name=amplify-next-template&template_owner=aws-samples&name=amplify-next-template&description=My%20Amplify%20Gen%202%20starter%20application)後，在 [Amplify控制台](https://console.aws.amazon.com/amplify/create/repo-branch) 建立應用
    （這裡使用 Amplify 提供的 [Next.js template](https://github.com/aws-samples/amplify-next-template) ，內含 Amplify CI/CD 流程)
![](https://i.imgur.com/XmYwclW.png)

2. 連結 Github 帳號與分支
![](https://i.imgur.com/5Kg8FGP.png)

3. 基本設定
![](https://i.imgur.com/Qo5Yeqa.png)

4. Review 確認後 deploy 就建立好專案了
![](https://i.imgur.com/mAKT7yM.png)

---

### Data 設定
1. 在本地打開專案中的 **amplify/data/resource.ts**
    更改資料結構
![](https://i.imgur.com/0b3ipMg.png)

```javascript
  Settings: a  // Settings 是資料庫名
    .model({
      key: a.string(), // 欄位 1
      value: a.string(), // 欄位 2
    })
    .authorization((allow) => [allow.publicApiKey()]),
```

2. commit 這筆修改，push 後 Amplify 就會自動開始部署
    等部署完就可在 [AWS 管理後台](https://console.aws.amazon.com/amplify/apps) > 專案名 > 點進分支 > 資料 > 資料管理員
    看到剛剛新增的資料表 settings
    可以直接在這新增資料：
    ![](https://i.imgur.com/F3XPzf4.png)

3. 在本地讀取剛剛push完產生的設定檔：
    [AWS 管理後台](https://console.aws.amazon.com/amplify/apps) > 專案名 > 點進分支 > 點進最新的部署 > Deployed backend resources > 下載 amplify_outputs.json 檔
    存在本地專案根目錄，即可在本地讀取該分支的資料表 
    (如果一直下載 amplify_outputs.json 沒更新，請用無痕模式下載)
    
    *或用指令部署到沙盒就可在本地操作沙盒資料表
    `npx ampx sandbox`

4. 其他資料表操控與呼叫方法可參考 [Amplify Docs Gen2 - Data](https://docs.amplify.aws/nextjs/build-a-backend/data/)
---

### Authentication 設定
這個可以用來跟AWS的 Cognito 溝通，來製作登入註冊的功能

1. 原本模板的設定:
可自定義登入註冊需要的功能，然後 push 到遠端後 Amplify 會自動產生 Cognito 的 User Pool 和 Identity Pool
```typescript
// amplify/auth/resource.ts
import { defineAuth } from "@aws-amplify/backend";

export const auth = defineAuth({
  loginWith: {
    email: true,
  },
});
```
2. 改成連結現有 Cognito (with backend)
需在[Cognito](https://ap-northeast-1.console.aws.amazon.com/cognito/)先建好 User Pool 和 Identity pool
因原本已有 User Pool，這邊只說明建立 App client 與 Identity pool流程：

- App client : Cognito > User pools > App clients > Create app client
要使用SPA方式的，然後 Create
![Create app client](https://hackmd.io/_uploads/HJtNZi2Jex.png)
###### App client > Login pages > Edit > Allowed callback URLs, Allowed sign-out URLs 要填寫, 否則 amplify CLI跑不出 amplify_outputs.json

- Identity pool : Cognito > Identity pools > Create identity pool
Step 1 : 勾選Authenticated access, Guest access, Amazon Cognito user pool
![Step 1](https://hackmd.io/_uploads/BJ8Nfi21gx.png)
Step 2 : 兩種都創新的 IAM role, 名稱結尾分別可用 authauthenticate 與 authauthenticatedU (這邊需要有AWS創立IAM的權限才能成功創建)
![Step 2](https://hackmd.io/_uploads/HyrRfi31xe.png)
Step 3 : 連結到你的User pool跟App client （有下拉選單直接選擇）
![Step 3](https://hackmd.io/_uploads/rkx5Qi2yle.png)
Step 4 : 命名 Identity pool
![Step 4](https://hackmd.io/_uploads/ryY5Ejnyxe.png)
Step 5 : 確認資訊然後就創建完成了

###### * Gen2 文件上有 without backend 的方式，但因已有用 backend 的方式連結 Data 了(如果用without會跟amplify_outputs.json打架)，所以一樣用 with backend的方式連結現有 Cognito
3. 在各個 pool 中找到對應的資訊，把amplify/auth/resource.ts 改成以下：
- userPoolClientId 在 User pools > 你的 pool > App clients
- authRoleArn(Authenticated access) 和 unauthRoleArn(Guest access) 在 Identity pools > User access
```typescript
import { referenceAuth } from "@aws-amplify/backend";
import * as dotenv from "dotenv";

/*
在本地 npx ampx sandbox 時，
這裡會讀不到環境變數，要用 dotenv，
然後可在 amplify 後台設環境變數 env=amplify
*/
if (process.env.ENV !== "amplify") {
  dotenv.config();
}

export const auth = referenceAuth({
  userPoolId: process.env.COGNITO_USER_POOL_ID!,
  userPoolClientId: process.env.COGNITO_USER_POOL_CLIENT_ID!,
  identityPoolId: process.env.COGNITO_IDENTITY_POOL_ID!,
  authRoleArn: process.env.COGNITO_AUTH_ROLE_ARN!,
  unauthRoleArn: process.env.COGNITO_UNAUTH_ROLE_ARN!,
});
```
###### * env 變數資訊存在 AWS Amplify > 專案名 > Hosting: Environment variables, 在本地 npx ampx sandbox時讀不到 .env.local的變數

4. 然後跟 Data 設定一樣去 Amplify 控制台取得 amplify_outputs.json 設定檔，或部署到沙盒就可在本地操作沙盒資料
    `npx ampx sandbox`

5. 登入註冊相關 API使用方式可參考 [Amplify Docs Gen2 - Authentication](https://docs.amplify.aws/gen2/build-a-backend/auth)

----

### 登入註冊API注意事項

- 建立 User pool 時就要選擇使用哪種方式為帳號識別(email,phone,username)，如果要修改就要重建 User pool，例如已經選擇為 email 的話，使用註冊 API 時，email 就會是必填選項
- 註冊時的驗證方式選擇在 Cognito > Sign-up > Attribute verification and user account confirmation 設定
- resendSignUpCode, resetPassword, sendUserAttributeVerificationCode 在短時間內最多只能打 5 次
- Passkey 要對到所使用的 domain 才起作用
User pools > auth.ohread.com > Authentication methods > Passkey > Domain for relying party ID
- 有設定 MFA 的話，Passkey 登入會失敗，兩者不能同時存在

----

### Amplify build output 限制 220MB

要注意的是，Amplify 的 build output 不能超過 220 MB。

#### [檢查 amplify 部署 build ouput 大小：](https://docs.aws.amazon.com/amplify/latest/userguide/troubleshooting-SSR.html#build-output-too-large)

可於 terminal 執行檢查 build output 結構（job-id 為第幾個 Deploy，例如 Deploy20 的 job-id 為 20）
```
aws amplify get-job --app-id abcd1234 --branch-name main --job-id 2
```
執行後找到 `stepName: "BUILD"` 區塊中的 artifactUrl 輸入瀏覽器下載 build output 資料夾


- [Amplify 部署規範](https://docs.aws.amazon.com/zh_cn/amplify/latest/userguide/ssr-deployment-specification.html)
- [Github issue](https://github.com/aws-amplify/amplify-hosting/issues/3647)
- [Github issue](https://github.com/aws-amplify/amplify-hosting/issues/3863)
- [Github issue](https://github.com/alexnguyennz/astro-aws-amplify/issues/23)

----

### 使用 Amplify Auth 遇到的狀況

1. referenceAuth 不支援 Custom Domain
    [相關討論](https://github.com/aws-amplify/amplify-backend/issues/2350)
    referenceAuth 轉出的 `amplify_outputs.json` (auth.oauth.domain 裡只讀得到 cognito domain )讀不到 Custom Domain，所以要自己設定在 config 裡
    ```typescript
    const outputs = JSON.parse(JSON.stringify(originalOutputs));
    outputs.auth.oauth.domain = process.env.NEXT_PUBLIC_AUTH_DOMAIN;
    
    Amplify.configure(outputs);
    ```
    
2. Passkey 、MFA不能同時存在
    [官方說不會改這功能](https://repost.aws/questions/QU-DKBR1VdQQuRn-WZRFCMzg/cognito-passkey-login-without-email-username-and-with-mfa-enabled)
    
3. cognito設定 > App client > Login pages > Allowed callback URLs 一定要設兩個：localhost跟線上的callback網址，否則會出現redirect錯誤 (好像只有在使用Hosted UI的時候才會，用Managed login可以)

4. 遇到`User needs to set a password to
sign in`可能的解法：
    * 匯入 user CVS 檔時 mfa_enabled 設定要留空
    * 在 User Pool 按 Action>Reset password,讓使用者到登入頁走 signIn API 的 RESET_PASSWORD 流程
    * 在 AWS CLI 重設 User 密碼
        ```js
        aws cognito-idp admin-set-user-password \
      --user-pool-id YOUR_USER_POOL_ID \
      --username yourmail@gmail.com \
      --password NEW_PASSWORD \
      --permanent
        ```
5. 只有 Managed login 能有 HttpOnly Cookie
    [相關連結](https://docs.amplify.aws/nextjs/build-a-backend/server-side-rendering/#authentication-with-nextjs-server-side-runtime)
    自己做 layout+Amplify API 不能