[Amplify]项目aws-amplfiy服务旧版本升级v6经验分享

前些天公司发下来给一个项目的aws-amplify服务升级到v6的任务,以下是我的升级经历和总结,希望对你有所帮助。

1. 关于打包 (Webpack4) + Babel 转译的问题

如果你的项目使用 Webpack4 打包,而在代码中直接导入 Amplify v6(或者间接导入带有新语法的模块),因为webpack4不能直接识别一些很新的js语法,而且babel默认不会转译node_modules下的依赖包的文件,导致webpack打包不了,在npm run dev时报错:

复制代码
 error  in ./node_modules/@aws-amplify/core/node_modules/uuid/dist/esm-browser/v4.js

Module parse failed: Unexpected token (9:33)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|     }
|     options = options || {};
>     const rnds = options.random ?? options.rng?.() ?? rng();
|     if (rnds.length < 16) {
|         throw new Error('Random bytes length must be >= 16');
............

如果出现了这种错误,那么你需要使用到babel等工具来进行转译。

我是vue2项目,可以在vue.config.js中给transpileDependencies项进行配置:

TypeScript 复制代码
// 详情可见https://cli.vuejs.org/zh/config/#transpiledependencies 
module.exports = {
    transpileDependencies: [
        /aws-amplify/
    ],
    .......
}

2. Amplify 配置按照官方文档配置后,启动仍报not configured错误

在我的升级过程中,出现了一个比较诡异的问题 ------ 即使按照官方文档已经配置好了**Amplify.configure(...),** 项目启动后仍报「没有配置」 (not configured)的错误**。**

最终解决方案是:

1、在项目根目录下的 amplify/backend/ 中补充配置文件。由 Amplify CLI 生成,具体内容视项目而定。如果你没有公司在Amplify上的账号,这一步操作通知相关负责人去完成。

2、在前端代码中,使用如下方式初始化 Amplify:

(1)把初始化的代码写到一个单独的 JS (或 TS) 文件里,然后在你的入口文件最顶部导入它:

aws-amplify-init.js:

TypeScript 复制代码
import { Amplify } from 'aws-amplify';
import amplifyconfig from './amplifyconfiguration.json';

Amplify.configure(amplifyconfig);

入口文件.js:

TypeScript 复制代码
import './amplify-init'  // ← 必须放最前面,确保在任何组件/模块之前执行

(2)若你在项目代码中导入 Auth, API, Storage等 Amplify 模块,使用 @aws-amplify/xxx 的路径形式,而不是 aws-amplify/xxxaws-amplify

TypeScript 复制代码
import { signOut, signIn, fetchAuthSession } from '@aws-amplify/auth';

我这里在使用'aws-amplify/xxx'引入时,也会报没有配置(像什么userPool not configured)的问题

TypeScript 复制代码
import { signOut, signIn, fetchAuthSession } from 'aws-amplify/auth';

这个问题目前也不清楚具体原因,可能是由于aws-amplify双包机制(aws-amplify和@aws-amplify) + webpack按package.json解析依赖path导致的。总之不太会是aws-amplify本身的问题。

3. Storage.put → uploadData 的迁移,以及路径差异的问题

在 v6 中,Storage (S3 上传/下载等) 的 API 做了重构。根据官方迁移指南:旧版本使用的是:

TypeScript 复制代码
import { Storage } from 'aws-amplify';

await Storage.put('test.txt', blob);

而在 v6 中,推荐使用新的模块化导入 + 功能 API:

TypeScript 复制代码
import { uploadData, getUrl } from 'aws-amplify/storage';

await uploadData({
  key: 'test.txt',
  data: blob,
});

但是新版本中使用uploadData之后,发现实际请求中,文件上传的路径不知道为何实际传输的文件的路径不一样:

原本: xxxxx/public/fileName

新版本v6使用uploadData: xxxxx/fileName

最后是在传输文件这里对比,补上了缺失的目录后,传输文件的地址才变得正确。 个人猜测可能升级后uploadData的验证和put不一样了,或者和公司在Amplify上的设置有关系还是怎么。但是本人在本次升级中只拿到了前端项目的代码,这些更细节的东西后续就交给公司的测试兄弟和项目经理们去解决了。(o.0)

4. GraphQL / API 的迁移:client 的生成 + subscribe / websocket / header 的改动

v6 对 API / GraphQL 部分也做了重构/优化:模块化导入 + 新的客户端 SDK + 更灵活的授权方式 (authMode) + 更好的 tree-shaking/bundle size 优化

参考链接:
Amplify クライアントを使用したクライアントアプリケーションの構築 - AWS AppSync GraphQL

在graphql()里,订阅实时事件的请求类型使用的是websocket。

在旧版本aws-amplify中,graphql的验证消息会直接补充到url的参数中:

graphql?header=xxxx&payload=e30=

如果你想在v6中也在url上包含这些信息,那么你需要在创建client时添加上header参数:

const client = generateClient({ headers: {......}, })

比如我的项目旧版本中具备两个参数:header、payload

那么我的代码就是:

const client = generateClient({ headers: { header: 'xxxxxx', payload: 'e30=' }, })

补充一点:旧版本的url中存放的是base64转码后的对象 Buffer.from(JSON.stringify(header)).toString('base64')

并且需要补充验证消息。v6创建client时,还要写认证模式 如果你的authMode是'apiKey',那你需要提供apiKey; 如果是'userPool',那你需要提供authToken。并且这个authToken,需要传入的是本次登录的验证消息里面idToken(不用base64转码)

5、signIn()升级和fetchAuthSession()

登录之后(signIn),本次登录的验证内容不再包含在signIn的返回内容中,你需要调用fetchAuthSession来获取本次登录的相关验证信息:

旧版本:

TypeScript 复制代码
await Auth.signIn(userName, passWord).then(res => { 
    console.log('login成功,响应体内容:', res) 
}) 

setJwtToken(res.signInUserSession.accessToken.jwtToken)

新版本:

TypeScript 复制代码
await signIn({ 
    username, password 
}) 

const tokenData = (await fetchAuthSession()).tokens 

if (tokenData) { 
    setJwtToken(tokenData.accessToken.toString()) 
} else { 
    console.error('fetchAuthSession error: User not signed in') 
}

创建client使用到的authToken就是base64转码后的idToken。

idToken的获取:

TypeScript 复制代码
const idToken = (await fetchAuthSession()).tokens.idToken.toString()

创建client:

TypeScript 复制代码
generateClient({ authMode: 'userPool', authToken: idToken })

希望对你有所帮助。

相关推荐
卖芒果的潇洒农民18 小时前
20260201 AWS VPC相关概念
云计算·aws
Genie cloud1 天前
1Panel SSL证书申请完整教程
服务器·网络协议·云计算·ssl
JiL 奥2 天前
Ubuntu系统安装AWS SAM
云计算·aws
liyuanchao_blog2 天前
linuxptp适配记录
linux·云计算
YongCheng_Liang2 天前
从零开始学虚拟化:性能优化全指南(资源分配 + 存储网络 + 监控)
运维·云计算
YongCheng_Liang2 天前
从零开始学虚拟化:高可用与灾备技术全解析(集群 + 备份 + 异地灾备)
运维·云计算
珠海西格2 天前
“主动预防” vs “事后补救”:分布式光伏防逆流技术的代际革命,西格电力给出标准答案
大数据·运维·服务器·分布式·云计算·能源
xianyinsuifeng3 天前
RAG + Code Analysis 的标准路线
数据仓库·自动化·云计算·原型模式·aws
Genie cloud3 天前
在 Mac 上使用 Docker 安装宝塔并部署 LNMP 环境
macos·docker·容器·云计算
php_kevlin3 天前
阿里云AI接口接口
阿里云·云计算