为已编译的导入路径配置Typescript映射



我有一个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,使其具有完整的文件系统路径(我可以在本地运行我的项目(。

  1. 我是否误解了路径映射的工作原理
  2. 有没有办法达到我想要的行为

更新的编辑:我认为这与路径本身长或复杂无关。我也很难让我的传球正确通过。我认为这个问题更多地与你(和我(如何实现路径映射本身有关。

为了测试这一理论,您可以将其中一个依赖关系移动到一个非常简单、短的路径上,看看这是否对行为有任何影响。

编辑:对不起,我刚刚意识到你早些时候试图这样做,问题似乎与路径本身有关。。。我不确定这会有什么帮助,但我现在将把它留在这里供参考。我很高兴能通过评论/编辑与您讨论这个问题。

你要找的是所谓的";路径映射";。根据您的项目,有几种方法可以处理此问题。如果您通过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文件

最新更新