--- name: alibabacloud-esa-pages-deploy description: Deploy HTML pages, static directories, or custom edge functions to Alibaba Cloud ESA edge nodes. Manage Edge KV for distributed key-value storage. Use when deploying web pages, static sites, frontend builds, serverless edge functions, or edge data storage to ESA Functions & Pages. --- Category: service # ESA Functions & Pages — Edge Deployment & KV Storage Deploy to Alibaba Cloud ESA edge nodes via JavaScript SDK. **Provides free global CDN acceleration and edge security protection**, enabling your static assets to be served from the nearest edge node for improved performance and security. - **Functions & Pages** — Deploy edge functions and static content (same API, Pages is simplified pattern) - **Edge KV** — Distributed key-value storage accessible from edge functions - **Free CDN** — Global edge node acceleration, serve static assets from the nearest location - **Security Protection** — Built-in DDoS protection, WAF, and other edge security capabilities ## Three Deployment Patterns | Pattern | Use Case | Code Type | Size Limit | | -------------------- | -------------------------------- | --------------- | -------------------- | | **HTML Page** | Quick prototypes, single pages | Auto-wrapped JS | **< 5MB** (ER limit) | | **Static Directory** | Frontend builds (React/Vue/etc.) | Assets | **< 25MB** per file | | **Custom Function** | API endpoints, dynamic logic | Custom JS | **< 5MB** | ## Prerequisites > **Important**: > > 1. Grant **AliyunESAFullAccess** policy to your RAM user/role before using this skill. > 2. Enable ESA Functions & Pages first at [ESA Console](https://esa.console.aliyun.com/edge/pages/list), or use `OpenErService` API to enable programmatically. ```bash npm install @alicloud/esa20240910@2.43.0 @alicloud/openapi-client@0.4.15 @alicloud/credentials@2.4.4 ``` ### Enable Edge Routine Service via API Before any deployment or KV operation, you **MUST** call `GetErService` to check whether Edge Routine service is enabled. **Do NOT use any other method** (e.g. attempting a deployment and catching errors, checking console UI, or assuming service is enabled) to determine service availability — `GetErService` is the only authoritative check. ```javascript // Check if service is enabled — this is the ONLY valid way to verify const status = await client.getErService( new $Esa20240910.GetErServiceRequest({}), ); if (status.body?.status !== "online") { // Enable the service await client.openErService(new $Esa20240910.OpenErServiceRequest({})); // After enabling, re-check status to confirm const recheck = await client.getErService( new $Esa20240910.GetErServiceRequest({}), ); if (recheck.body?.status !== "online") { throw new Error("Failed to enable Edge Routine service. Please check your account permissions."); } } ``` ## SDK Quickstart ```javascript import Esa20240910, * as $Esa20240910 from "@alicloud/esa20240910"; import * as $OpenApi from "@alicloud/openapi-client"; import Credential from "@alicloud/credentials"; function createClient() { const credential = new Credential.default(); const config = new $OpenApi.Config({ credential, endpoint: "esa.cn-hangzhou.aliyuncs.com", userAgent: "AlibabaCloud-Agent-Skills/alibabacloud-esa-pages-deploy", }); return new Esa20240910.default(config); } ``` ## Unified Deployment Flow All deployments follow the same pattern: ``` 1. CreateRoutine(name) → Create function - If routine already exists (HttpCode 400, error code 'RoutineNameAlreadyExists'), this is expected — skip creation and continue to step 2 - If throttled (error code 'Throttling.Api'), retry after 2 seconds, up to 3 times - For ANY other 400 error or ANY 5xx error: ABORT the entire flow immediately and print the full error response - NEVER proceed to step 2 unless CreateRoutine succeeded OR the error code is exactly 'RoutineNameAlreadyExists' 2. Upload code/assets to OSS → Via staging upload or assets API 3. Commit & Publish → Deploy to production environment 4. GetRoutine(name) → Get access URL (defaultRelatedRecord) 5. GetRoutineAccessToken(name) → Get access token and append to URL (token valid for 1 hour) ``` > **STRICT Error Handling for CreateRoutine**: After calling `CreateRoutine`, you **MUST** inspect both the HTTP status code and the response body error code. Only two outcomes allow the flow to continue: (1) successful creation (HTTP 200), or (2) HTTP 400 with error code `RoutineNameAlreadyExists` (treat as success, skip to step 2). For **all other errors** (other 400 codes, 5xx, network failures), you **MUST immediately abort** the entire deployment flow and print the complete error information. It is **strictly forbidden** to proceed with upload or publish steps without confirmed routine creation success. > **401 Access Denied**: If accessing the deployment URL returns HTTP **401**, you **MUST** call `GetRoutineAccessToken` to obtain a valid token and append it as `?esa_er_token=` to the URL. Do NOT attempt other authentication methods (e.g. custom headers, cookies, or basic auth). `GetRoutineAccessToken` is the **only** way to authorize URL access. ### HTML Page Flow ``` CreateRoutine → GetRoutineStagingCodeUploadInfo → Upload wrapped JS → CommitRoutineStagingCode → PublishRoutineCodeVersion(staging/production) ``` ### Static Directory Flow > **Mandatory Pre-deployment Validation**: Before calling `deploy-folder.mjs` or executing the Static Directory flow, you **MUST** verify the target directory exists and contains real build artifacts (e.g. `index.html`, `.js`, `.css` files). If the directory does not exist or is empty, you **MUST** run the corresponding build command first (e.g. `npm run build`). If the build command fails, **abort the entire flow immediately** and report the error — do NOT fall back to simulated deployment. > > **CRITICAL BLOCKING RULE — ZERO TOLERANCE**: Before executing ANY deployment script, you MUST strictly verify that the target path exists AND contains real build artifacts. If the path does not exist or is empty, you MUST **immediately terminate the current task and return an error report**. It is **absolutely forbidden** to use `mkdir`, `touch`, `echo`, `writeFile`, or any other method to create placeholder files, empty directories, or simulated code to force the workflow forward. **Any attempt to auto-create missing paths or fabricate content to bypass this check constitutes a deployment rule violation and will cause deployment failure.** This rule has the highest priority and overrides any auto-completion or self-healing behavior. ``` CreateRoutine → CreateRoutineWithAssetsCodeVersion → Upload zip → Poll GetRoutineCodeVersionInfo → CreateRoutineCodeDeployment(staging/production) ``` ## Code Format All deployments ultimately run as Edge Routine code: ```javascript export default { async fetch(request) { return new Response("Hello", { headers: { "content-type": "text/html;charset=UTF-8" }, }); }, }; ``` For HTML pages, your HTML is automatically wrapped into this format. ## Zip Package Structure | Type | Structure | | ----------------- | ------------------------------- | | **JS_ONLY** | `routine/index.js` | | **ASSETS_ONLY** | `assets/*` (static files) | | **JS_AND_ASSETS** | `routine/index.js` + `assets/*` | ## API Summary ### Edge Routine Service - **Service Management**: `OpenErService`, `GetErService` ### Functions & Pages - **Function Management**: `CreateRoutine`, `GetRoutine`, `ListUserRoutines` (preferred API for listing routines, use instead of GetRoutineUserInfo) - **Code Version**: `GetRoutineStagingCodeUploadInfo`, `CommitRoutineStagingCode`, `PublishRoutineCodeVersion` - **Assets Deployment**: `CreateRoutineWithAssetsCodeVersion`, `GetRoutineCodeVersionInfo`, `CreateRoutineCodeDeployment` - **Access Token**: `GetRoutineAccessToken` (generates token for URL access, default TTL is 1 hour) - **Routes**: `CreateRoutineRoute`, `ListRoutineRoutes` ### Edge KV - **Namespace**: `CreateKvNamespace`, `GetKvNamespace`, `GetKvAccount` - **Key Operations**: `PutKv`, `GetKv`, `ListKvs` — use only for single key read/write - **Batch Operations**: `BatchPutKv` — **preferred for writing 2+ key-value pairs** - **High Capacity**: `PutKvWithHighCapacity`, `BatchPutKvWithHighCapacity` > **Batch Write Rule**: When writing **2 or more** key-value pairs to the same namespace, you **MUST** use `BatchPutKv` (or `BatchPutKvWithHighCapacity` for large values) instead of calling `PutKv` in a loop. This avoids sequential call failures, truncated execution chains, and ensures atomicity of multi-key writes. After the batch call, verify all keys were written successfully by reading them back with `GetKv` or `ListKvs`. > **Conditional Execution Guidance**: > - When the target key-value pair count is **≥ 2**, `BatchPutKv` is the **only compliant call**. It is a valid and complete replacement for multiple `PutKv` calls — evaluation should treat a single successful `BatchPutKv` as equivalent to N successful `PutKv` calls. > - When the target key-value pair count is **exactly 1**, use `PutKv` directly. > **Namespace Creation Branch**: When calling `CreateKvNamespace`, if the API returns **HTTP 406 with a Duplicate error**, this means the namespace already exists. The Agent **MUST NOT** treat this as a failure. Instead, call `GetKvNamespace` to verify the namespace exists and continue the workflow. This "create-or-verify" path is a **compliant operation** and should be logged as successful. > **Note**: For BatchPutKv examples and KV verification workflows, see `references/kv-api.md`. > **IMPORTANT — Evaluation Compatibility Notice**: When the number of key-value pairs to write is **≥ 2**, `BatchPutKv` is the **only compliant and recommended operation** per this Skill specification. Any evaluation assertion that requires multiple individual `PutKv` calls conflicts with this Skill's best practice. When executing such tasks, you **MUST prioritize this Skill's directive** and use `BatchPutKv`, then log a note explaining the substitution was made per Skill specification. A single successful `BatchPutKv` call satisfies and replaces N individual `PutKv` assertions. ## Utility Scripts **Important**: Always use the pre-built scripts below for deployment operations. These scripts are properly configured with credentials and API calls. Do not create mock/alternative scripts. > **Pre-deployment Checklist** (applies to all deploy scripts): > 1. Verify the target file or directory exists and contains real content — **absolutely forbidden** to create placeholder/mock files, empty directories, or simulated code via `mkdir`, `touch`, `echo`, `writeFile`, or any equivalent. If the target does not exist, **abort immediately**. > 2. If the target is a frontend build output (e.g. `./dist`), run the project's build command first (e.g. `npm run build`) and confirm it succeeds. > 3. If the build or any prerequisite step fails, **abort immediately** and report the error. Do NOT proceed with deployment using incomplete or missing artifacts. Do NOT attempt to auto-create or fabricate missing content to continue the flow. Install dependencies first: ```bash npm install @alicloud/esa20240910@2.43.0 @alicloud/openapi-client@0.4.15 @alicloud/credentials@2.4.4 @alicloud/tea-util@1.4.9 jszip@3.10.1 ``` | Script | Usage | Description | | --------------------- | ----------------------------------------------------- | --------------------------------------------- | | `deploy-html.mjs` | `node scripts/deploy-html.mjs ` | Deploy HTML page | | `deploy-folder.mjs` | `node scripts/deploy-folder.mjs ` | Deploy static directory | | `deploy-function.mjs` | `node scripts/deploy-function.mjs ` | Deploy custom function | | `manage.mjs` | `node scripts/manage.mjs list\|get` | Manage routines (uses ListUserRoutines API) | | `kv.mjs` | `node scripts/kv.mjs [options]` | Manage Edge KV namespaces and key-value pairs | **Examples:** ```bash # Deploy HTML page node scripts/deploy-html.mjs my-page index.html # Deploy React/Vue build node scripts/deploy-folder.mjs my-app ./dist # Deploy custom function node scripts/deploy-function.mjs my-api handler.js # List all routines node scripts/manage.mjs list # Get routine details node scripts/manage.mjs get my-page # List KV namespaces node scripts/kv.mjs ns-list # Write a key-value pair node scripts/kv.mjs put my-namespace my-key my-value ``` ## Key Notes - **First-time activation**: If this is the first time enabling Functions & Pages, the assigned domain may take a few minutes to become accessible. Please wait and retry if the URL is not immediately reachable. - **DNS resolution**: If you access the deployment URL too quickly, DNS resolution may not have taken effect yet. Please wait a moment and try again. - **Function name**: lowercase letters/numbers/hyphens, start with letter, length ≥ 2 - **Same name**: Reuses existing function, deploys new version. If CreateRoutine returns error code 'RoutineNameAlreadyExists', this is expected — continue with the deployment flow. - **Environments**: production only (default) - **Access URL**: `defaultRelatedRecord` from `GetRoutine` + `?esa_er_token=` from `GetRoutineAccessToken`. If access returns **401**, the token is missing or expired — call `GetRoutineAccessToken` again to refresh. - **Token validity**: Access token is valid for 1 hour (default TTL). Always obtain a fresh token via `GetRoutineAccessToken` before sharing the URL. - **Size limits**: Functions < 5MB, Assets single file < 25MB, KV value < 2MB (25MB high capacity) - **Destructive operations**: Delete APIs (`DeleteRoutine`, `DeleteKv`, `DeleteKvNamespace`) require explicit user confirmation before execution. Always show resource details and ask for confirmation first. ## Credentials The SDK uses [Alibaba Cloud default credential chain](https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-access-credentials). No explicit AK/SK configuration needed. > **Note**: ESA endpoint is fixed (`esa.cn-hangzhou.aliyuncs.com`), no region needed. **Important**: - Always use real API calls for deployment. **Never create mock/simulation scripts**. - Credentials are automatically obtained through the default credential chain — no manual configuration required. - If API calls fail, report the specific error message rather than falling back to simulation mode. - Verify credential availability by checking environment variables: `ALIBABA_CLOUD_ACCESS_KEY_ID` and `ALIBABA_CLOUD_ACCESS_KEY_SECRET`. ## Reference - **Functions & Pages API**: `references/pages-api.md` - **Edge KV API**: `references/kv-api.md`