我有一个aws-amplify项目,它使用了yarn工作区。
我的项目有一个lambda函数和一个层。当lambda函数在aws中运行时,它需要从层导入我的库。。。
import MyLib from '/opt/nodejs/build/MyLib';
然而,当我在本地运行此函数时,我想从本地文件系统导入库
import MyLib from '/Users/sive/Documents/SWT/wake-book/amplify/backend/function/wakebookLayer/lib/nodejs/build/MyLib';
如何告诉typescript将导入从/opt/nodejs/build/MyLib
编译到本地文件系统上的位置。
我尝试在tsconfig.json 中使用路径映射
"baseUrl": ".",
"paths": {
"/opt/nodejs/build/MyLib": ["./amplify/backend/function/wakebookLayer/lib/nodejs/build/MyLib.d.ts"]
},
这阻止了vscode抱怨未知的导入,因此它被正确地"链接"了(我可以命令单击我的导入/opt/nodejs/build/MyLib
路径,然后我被带到完整的文件系统路径。(
但是编译后的js仍然使用错误的路径。
编译后的js文件看起来像这个
const MyLib_1 = __importDefault(require("/opt/nodejs/build/MyLib"));
我希望它能重新映射导入路径,并看起来像这个
const MyLib_1 = __importDefault(require("/Users/sive/Documents/SWT/wake-book/amplify/backend/function/wakebookLayer/lib/nodejs/build/MyLib"));
如果我手动编辑输出js,使其具有完整的文件系统路径(我可以在本地运行我的项目(。
- 我是否误解了路径映射的工作原理
- 有没有办法达到我想要的行为
更新的编辑:我认为这与路径本身长或复杂无关。我也很难让我的传球正确通过。我认为这个问题更多地与你(和我(如何实现路径映射本身有关。
为了测试这一理论,您可以将其中一个依赖关系移动到一个非常简单、短的路径上,看看这是否对行为有任何影响。
编辑:对不起,我刚刚意识到你早些时候试图这样做,问题似乎与路径本身有关。。。我不确定这会有什么帮助,但我现在将把它留在这里供参考。我很高兴能通过评论/编辑与您讨论这个问题。
你要找的是所谓的";路径映射";。根据您的项目,有几种方法可以处理此问题。如果您通过SAM进行部署,AWS的这篇文章描述了一种可能的解决方案:https://aws.amazon.com/blogs/compute/working-with-aws-lambda-and-lambda-layers-in-aws-sam/
其中的重要摘录如下:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: sam app
Globals:
Function:
Timeout: 3
Runtime: nodejs8.10
Resources:
TempConversionFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Events:
HelloWorld:
Type: Api
Properties:
Path: /{conversion}/{value}
Method: get
此更改删除了一些注释和输出参数将函数资源更新为TempConversionFunction。初级更改为Path:/{conversion}/{value}行。这使您能够对转换类型和值使用路径映射。
我也看到过利用tsconfig的例子,但这似乎是一个单独的解决方案。同样,这里有一个指向文档的链接:https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-映射
以及相关摘录:
有时模块不直接位于baseUrl下。对于例如模块的导入";jquery";将在运行时到";node_modules/jquery/dist/jquery.slim.min.js";。装载机使用用于在运行时将模块名称映射到文件的映射配置,请参阅RequireJs文档和SystemJS文档。
TypeScript编译器支持此类映射的声明使用tsconfig.json文件中的path属性。以下是如何为jquery指定path属性。
{
"compilerOptions": {
"baseUrl": ".", // This must be specified if "paths" is.
"paths": {
"jquery": ["node_modules/jquery/dist/jquery"] // This mapping is relative to "baseUrl"
}
}
}
如果不了解更多关于如何部署代码的信息,我不可能给出更准确的答案。但我希望这能有所帮助。
我应该注意的是,你的try/catch块确实有效,但它不会被认为是最佳实践。
这篇文章第一次得到回复已经一年半了,似乎仍然没有一个广泛宣传的解决方案。
因此,如果有人无意中发现了这一点,以下是我的想法:
我在所有lambda函数处理程序目录中都有一个JAVASCRIPT(.js,而不是.ts文件(,其唯一职责是在运行时从适当的路径(在我计算机上的"/opt/nodejs"路径或本地路径(导入层。它使用try/catch机制来实现这一点,我知道这是一种反模式,但它在这种情况下运行良好。
try{
module.exports = require("/opt/nodejs/index")
} catch {
module.exports = require("../../layer/index"); // my local path
}
然后,在我的处理程序代码中,我导入了带有以下代码片段的层:
import layer = require("../../layer"); // path to aforementioned file
该解决方案利用了一种被称为"导出=语法"的晦涩打字脚本功能
https://www.typescriptlang.org/docs/handbook/modules.html#export--和导入--需要
只有当导入切换层代码的文件是javascript(.js(文件时,它才有效。如果它是一个typescript(.ts(文件,它就不起作用。因此,您还必须使用"allowJs": true
配置tsconfig.json文件