

# 使用 .zip 文件归档部署在 Lambda 中转换的 TypeScript 代码
<a name="typescript-package"></a>

在可以将 TypeScript 代码部署到 AWS Lambda 之前，您需要将其转换为 JavaScript。本页介绍了使用 .zip 文件存档构建 TypeScript 代码并将其部署到 Lambda 的三种方法：
+ [使用 AWS Serverless Application Model（AWS SAM）](#aws-sam-ts)
+ [使用 AWS Cloud Development Kit (AWS CDK)](#aws-cdk-ts)
+ [使用 AWS Command Line Interface (AWS CLI) 和 esbuild](#aws-cli-ts)

AWS SAM 和 AWS CDK 可以简化 TypeScript 函数的构建和部署。[AWS SAM 模板规范](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification.html)提供了一种简单而干净的语法，用于描述构成无服务器应用程序的 Lambda 函数、API、权限、配置和事件。[AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html) 使您能够借助编程语言的强大表达能力，在云中构建可靠、可扩展且成本高效的应用程序。AWS CDK 适合中度到高度经验的 AWS 用户。AWS CDK 和 AWS SAM 两者均使用 esbuild 将 TypeScript 代码转换为 JavaScript。

## 使用 AWS SAM 将 TypeScript 代码部署到 Lambda
<a name="aws-sam-ts"></a>

请按照以下步骤使用 AWS SAM 来下载、构建和部署示例 Hello World TypeScript 应用程序。此应用程序实现了基本的 API 后端。它由 Amazon API Gateway 端点和 Lambda 函数组成。在向 API Gateway 端点发送 GET 请求时，会调用 Lambda 函数。该函数将返回一条 `hello world` 消息。

**注意**  
AWS SAM 使用 esbuild 从 TypeScript 代码创建 Node.js Lambda 函数。esbuild 支持目前处于公开预览状态。在公开预览期间，esbuild 支持可能会发生向后不兼容的变更。

**先决条件**

要完成本节中的步骤，您必须满足以下条件：
+ [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS SAM CLI 版本 1.75 或更高版本](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
+ Node.js

**部署示例 AWS SAM 应用程序**

1. 使用 Hello World TypeScript 模板初始化该应用程序。

   ```
   sam init --app-template hello-world-typescript --name sam-app --package-type Zip --runtime nodejs24.x
   ```

1. （可选）该示例应用程序包括常用工具的配置，例如用于代码检查的 [esLlint](https://eslint.org/) 和用于单元测试的 [Jest](https://jestjs.io/)。要运行检查和测试命令，请执行以下操作：

   ```
   cd sam-app/hello-world
   npm install
   npm run lint
   npm run test
   ```

1. 构建应用程序。

   ```
   cd sam-app
   sam build
   ```

1. 部署应用程序。

   ```
   sam deploy --guided
   ```

1. 按照屏幕上的提示操作。要接受交互式体验中提供的原定设置选项，请通过 `Enter` 进行响应。

1. 输出将显示 REST API 的端点。在浏览器中打开该端点，以测试函数。您应该会看到以下响应：

   ```
   {"message":"hello world"}
   ```

1. 这是一个可以通过互联网访问的公有 API 端点。我们建议您在测试后删除该端点。

   ```
   sam delete
   ```

## 使用 AWS CDK 将 TypeScript 代码部署到 Lambda
<a name="aws-cdk-ts"></a>

请按照以下步骤使用 AWS CDK 来构建和部署示例 TypeScript 应用程序。此应用程序实现了基本的 API 后端。它由 API Gateway 端点和 Lambda 函数组成。在向 API Gateway 端点发送 GET 请求时，会调用 Lambda 函数。该函数将返回一条 `hello world` 消息。

**先决条件**

要完成本节中的步骤，您必须满足以下条件：
+ [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS CDK 版本 2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites)
+ Node.js
+ [Docker](https://www.docker.com/get-started/) 或 [esbuild](https://esbuild.github.io/)

**部署示例 AWS CDK 应用程序**

1. 为您的新应用程序创建一个项目目录。

   ```
   mkdir hello-world
   cd hello-world
   ```

1. 初始化该应用程序。

   ```
   cdk init app --language typescript
   ```

1. 添加 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 软件包作为开发依赖项。此程序包包含 Lambda 的类型定义。

   ```
   npm install -D @types/aws-lambda
   ```

1. 打开 **lib** 目录。您应该会看到一个名为 **hello-world-stack.ts** 的文件。在此目录中创建两个新文件：**hello-world.function.ts** 和 **hello-world.ts**。

1. 打开 **hello-world.function.ts**，然后将以下代码添加到该文件。这是适用于 Lambda 函数的代码。
**注意**  
`import` 语句从 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 中导入类型定义。它不导入 `aws-lambda` NPM 程序包，这是一个无关的第三方工具。有关更多信息，请参阅 DefinitelyTyped GitHub 存储库中的 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)。

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
       console.log(`Event: ${JSON.stringify(event, null, 2)}`);
       console.log(`Context: ${JSON.stringify(context, null, 2)}`);
       return {
           statusCode: 200,
           body: JSON.stringify({
               message: 'hello world',
           }),
       };
   };
   ```

1. 打开 **hello-world.ts**，然后将以下代码添加到该文件。其中包含 [NodejsFunction 构造](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html)（它将创建 Lambda 函数）和 [LambdaRestApi 构造](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.LambdaRestApi.html)（它将创建 REST API）。

   ```
   import { Construct } from 'constructs';
   import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
   import { LambdaRestApi } from 'aws-cdk-lib/aws-apigateway';
     
   export class HelloWorld extends Construct {
     constructor(scope: Construct, id: string) {
       super(scope, id);
       const helloFunction = new NodejsFunction(this, 'function');
       new LambdaRestApi(this, 'apigw', {
         handler: helloFunction,
       });
     }
   }
   ```

   `NodejsFunction` 构造默认假设以下内容：
   + 您的函数处理程序称为 `handler`。
   + 包含函数代码的 .ts 文件 (**hello-world.function.ts**) 与包含构造的 .ts 文件 (**hello-world.ts**) 位于相同的目录中。该构造使用构造的 ID（“hello-world”）和 Lambda 处理程序文件的名称（“function”）来查找函数代码。例如，如果您的函数代码位于名为 **hello-world.my-function.ts** 的文件中，则 **hello-world.ts** 文件必须按如下所示引用该函数代码：

     ```
     const helloFunction = new NodejsFunction(this, 'my-function');
     ```

   您可以更改此行为并配置其他 esbuild 参数。有关更多信息，请参阅 AWS CDK API 参考中的[配置 esbuild](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html#configuring-esbuild)。

1. 打开 **hello-world-stack.ts**。这是定义您的 [AWS CDK 堆栈](https://docs.aws.amazon.com/cdk/v2/guide/stacks.html)的代码。使用以下代码替换该代码：

   ```
   import { Stack, StackProps } from 'aws-cdk-lib';
   import { Construct } from 'constructs';
   import { HelloWorld } from './hello-world';
     
   export class HelloWorldStack extends Stack {
     constructor(scope: Construct, id: string, props?: StackProps) {
       super(scope, id, props);
       new HelloWorld(this, 'hello-world');
     }
   }
   ```

1. 从包含您的 `cdk.json` 文件的 `hello-world` 目录中，部署您的应用程序。

   ```
   cdk deploy
   ```

1. AWS CDK 使用 esbuild 构建和打包 Lambda 函数，然后将该函数部署到 Lambda 运行时。输出将显示 REST API 的端点。在浏览器中打开该端点，以测试函数。您应该会看到以下响应：

   ```
   {"message":"hello world"}
   ```

   这是一个可以通过互联网访问的公有 API 端点。我们建议您在测试后删除该端点。

## 使用 AWS CLI 和 esbuild 将 TypeScript 代码部署到 Lambda
<a name="aws-cli-ts"></a>

以下示例演示如何使用 esbuild 和 AWS CLI 转换 TypeScript 代码并将其部署到 Lambda。esbuild 将生成一个包含所有依赖项的 JavaScript 文件。这是您需要添加到 .zip 归档中的唯一文件。

**先决条件**

要完成本节中的步骤，您必须满足以下条件：
+ [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ Node.js
+ Lambda 函数的[执行角色](lambda-intro-execution-role.md)
+ 对于 Windows 用户来说，这是一款压缩文件实用程序，例如 [7zip](https://www.7-zip.org/download.html)。

**部署示例函数**

1. 在本地计算机上，为新函数创建项目目录。

1. 使用 npm 或您选择的软件包管理器创建一个新的 Node.js 项目。

   ```
   npm init
   ```

1. 添加 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 和 [esbuild](https://esbuild.github.io/) 软件包作为开发依赖项。`@types/aws-lambda` 程序包包含 Lambda 的类型定义。

   ```
   npm install -D @types/aws-lambda esbuild
   ```

1. 创建名为 **index.ts** 的新文件。将以下代码添加到该新文件中。这是适用于 Lambda 函数的代码。该函数将返回一条 `hello world` 消息。该函数不会创建任何 API Gateway 资源。
**注意**  
`import` 语句从 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 中导入类型定义。它不导入 `aws-lambda` NPM 程序包，这是一个无关的第三方工具。有关更多信息，请参阅 DefinitelyTyped GitHub 存储库中的 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)。

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
     console.log(`Event: ${JSON.stringify(event, null, 2)}`);
     console.log(`Context: ${JSON.stringify(context, null, 2)}`);
     return {
         statusCode: 200,
         body: JSON.stringify({
             message: 'hello world',
         }),
      };
   };
   ```

1. 将构建脚本添加到 **package.json** 文件。这会将 esbuild 配置为自动创建 .zip 部署软件包。有关更多信息，请参阅 esbuild 文档中的[构建脚本](https://esbuild.github.io/getting-started/#build-scripts)。

------
#### [ Linux and MacOS ]

   ```
   "scripts": {
     "prebuild": "rm -rf dist",
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js",
     "postbuild": "cd dist && zip -r index.zip index.js*"
   },
   ```

------
#### [ Windows ]

   在此示例中，`"postbuild"` 命令使用 [7zip](https://www.7-zip.org/download.html) 实用程序创建您的 .zip 文件。使用您自己首选的 Windows zip 实用程序并根据需要修改该命令。

   ```
   "scripts": {
     "prebuild": "del /q dist",
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js",
     "postbuild": "cd dist && 7z a -tzip index.zip index.js*"
   },
   ```

------

1. 构建软件包。

   ```
   npm run build
   ```

1. 使用该 .zip 部署软件包创建 Lambda 函数。将突出显示的文本替换为您的[执行角色](lambda-intro-execution-role.md)的 Amazon 资源名称（ARN）。

   ```
   aws lambda create-function --function-name hello-world --runtime "nodejs24.x" --role arn:aws:iam::123456789012:role/lambda-ex --zip-file "fileb://dist/index.zip" --handler index.handler
   ```

1. [运行测试事件](testing-functions.md)，以确认该函数会返回以下响应。如果您想使用 API Gateway 调用此函数，请[创建和配置 REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html)。

   ```
   {
     "statusCode": 200,
     "body": "{\"message\":\"hello world\"}"
   }
   ```