
はじめに
こんにちは、@きょーです!普段はデリッシュキッチン開発部のバックエンド中心で業務をしています。
AWS の CloudFront は CDN としての基本的な機能があるだけでなく「エッジで処理を実行できる」機能もあることをご存知でしょうか?
CloudFront には主に 2 つのエッジ実行機能があります。
- CloudFront Functions - 軽量・高速な処理用
- Lambda@Edge - 複雑な処理用
この記事では、CloudFront Functions を初めて使った際に遭遇した「JavaScript の制約」について、実体験を基に詳しく解説します。特に const や exports が使えないという、JavaScript 開発者が陥りがちな罠と、その解決策をお伝えします。
CloudFront Functions とは何か?
CloudFront Functions は、CloudFront に組み込まれた軽量・高速なエッジ実行機能です。
公式ドキュメントによると、以下の特徴を持ちます。
大規模でレイテンシーの影響を受けやすい CDN カスタマイズのための軽量な関数を JavaScript で記述できます。CloudFront Functions の runtime 環境は、起動時間が 1 ミリ秒未満、毎秒数百万のリクエストを処理するようにすぐにスケールでき、高い安全性を誇ります。
出典: AWS CloudFront Developer Guide - CloudFront Functions と Lambda@Edge の違い
CloudFront Functions が最適な用途
AWS が推奨する主な用途
キャッシュキー正規化
- HTTP リクエスト属性(ヘッダー、クエリ文字列、Cookie、URL パス)を変換
- 最適なキャッシュキーを作成してキャッシュヒット率を向上
ヘッダー操作
- リクエストやレスポンスで HTTP ヘッダーの挿入、変更、削除
- 例:
True-Client-IPヘッダーの追加
URL リダイレクト・リライト
- リクエスト情報に基づくビューアーの他ページへのリダイレクト
- 特定パスから別パスへのリクエストリライト
リクエスト認証
- ハッシュ化された認証トークン(JWT 等)の検証
- 認証ヘッダーや他のリクエストメタデータの検証
CloudFront Functions で詰まったポイント
自分は上記の用途でも触れられている URL のリダイレクト・リライトする時の処理を書こうとした際に詰まりました。
最初に書いたコード(動かない)
CloudFront Functions(JavaScript ランタイム 1.0)に以下のようなコードを書きました。
// ❌ これは動かない const handler = (event) => { const request = event.request; const uri = request.uri; // URL書き換えの処理 return request; }; exports.handler = handler;
遭遇したエラー
このコードを CloudFront Functions にデプロイして実際にアクセスしようとすると、以下のような 503 エラーが発生しました。

503 ERROR The request could not be satisfied. The CloudFront function associated with the CloudFront distribution is invalid or could not run. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner. If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
デプロイ自体は成功しているのに実際にアクセスすると 503 エラーになっていました。構文的にも問題ないと思っていたので最初は「?」で頭がいっぱいでした。
トラブルシューティング
この問題の解決には、クラスメソッドさんの記事が非常に参考になりました。
上記の記事でも紹介されていますが、CloudFront のコンソールから Functions のテスト機能を使って調べてみると、以下のような具体的なエラーメッセージが確認できました。

The CloudFront function associated with the CloudFront distribution is invalid or could not run. SyntaxError: Token "const" not supported in this version in 2
つまり、関数自体の構文エラーが原因で CloudFront Functions が実行に失敗し、結果として 503 エラーが返されていたのです。
原因: ECMAScript 5.1 準拠という制約
調べてみると、CloudFront Functions(JavaScript ランタイム 1.0)は ECMAScript 5.1 準拠 という制約がありました。
CloudFront Functions の JavaScript ランタイム環境は ECMAScript (ES) バージョン 5.1 に準拠しており、ES バージョン 6 ~ 9 の一部の機能をサポートしています。
出典: AWS CloudFront Developer Guide - JavaScript ランタイム 1.0 の機能
具体的な制約
❌ 使用不可機能:
const/letステートメントexports/module.exports/import/require
✅ 使用可能な ES6+ 機能:
- アロー関数
- テンプレートリテラル(複数行の文字列、式の補間)
- レストパラメータ構文
- ES6-ES9 の一部オブジェクト・配列・文字列メソッド
つまり、ES5.1 + 一部の ES6+ の機能という構成になっています。
上記の制約と自分のコードを見比べてみると以下の点で構文エラーになっていました。
constステートメント は JavaScript ランタイム 1.0 でサポートされていないexportsステートメント は JavaScript ランタイム 1.0 でサポートされていない
解決策と回避方法
解決策 1: ランタイム 1.0 対応の書き方にする
ランタイム 1.0 を使う場合は、exports と const を使わない(var を使う)ことで対応できます。
// ✅ ランタイム 1.0 で動作する function handler(event) { var request = event.request; var uri = request.uri; // URL書き換えの処理 return request; }
解決策 2: JavaScript ランタイム 2.0 を使用する
2024 年初期に登場した JavaScript ランタイム 2.0 使う場合は、exports だけを使わないようにするだけで対応できます。(最初から導入する場合は JavaScript ランタイム 2.0 を使用することをお勧めします)
// ✅ ランタイム 2.0 では動作する function handler(event) { const request = event.request; // const は使える const uri = request.uri; // URL書き換えの処理 return request; }
CloudFront Functions における JavaScript ランタイムの特徴
先ほどから話で触れているランタイムについてですが、CloudFront Functions では、JavaScript の実行環境として 2 つのランタイムが提供されています。それぞれの特徴と制約について紹介します。
JavaScript ランタイム 1.0(ECMAScript 5.1 準拠)
JavaScript ランタイム 1.0 は ECMAScript 5.1 を基盤としており、以下の機能が使用できます。
基本的な制御構文:
break、catch、continue、do-while、else、finallyfor、function、if、label、return、switchthrow、try、var、while
ES6+ の一部機能:
- アロー関数
- テンプレートリテラル(複数行の文字列、式の補間)
- レストパラメータ構文
- ES6-ES9 の一部オブジェクト・配列・文字列メソッド
使用できない機能:
const、letステートメントasync、await- モジュール関連機能(
exports、requireなど)
JavaScript ランタイム 2.0(ES6-ES12 対応)
JavaScript ランタイム 2.0 では、ランタイム 1.0 の全機能に加えて、より多くの JavaScript 機能が使用できます。
ランタイム 1.0 からの主な追加機能:
const、letによるブロックスコープ変数宣言async、awaitによる非同期処理- その他 ES6-ES12 の機能
注意点:
- モジュール機能(
exports、require、importなど)は引き続き使用不可
共通の制約事項
両ランタイム共通で、以下の機能は使用できません。
動的コード評価:
eval()、new Function()
非同期・タイマー:
setTimeout()、setInterval()
ネットワーク:
fetch()、XMLHttpRequest()
モジュール:
require()、import、exports、module.exports
システム:
process.env、ファイルシステムアクセス
大きく変わる箇所について取り上げましたが、その他詳細については以下の公式ドキュメントをご覧ください。
- AWS CloudFront Developer Guide - CloudFront Functions の JavaScript ランタイム 1.0 の機能
- AWS CloudFront Developer Guide - CloudFront Functions の JavaScript ランタイム 2.0 の機能
パフォーマンスとトレードオフ
冒頭でも触れましたが、CloudFront Functions は以下の特徴を持つように設計されています。
大規模でレイテンシーの影響を受けやすい CDN カスタマイズのための軽量な関数を JavaScript で記述できます。CloudFront Functions の runtime 環境は、起動時間が 1 ミリ秒未満、毎秒数百万のリクエストを処理するようにすぐにスケールでき、高い安全性を誇ります。
これらの極限的なパフォーマンス要件を実現するため、AWS は以下の技術的判断を行っています。
1. 軽量ランタイムの採用
- ECMAScript 5.1 を基盤とし、厳選された ES6-ES12 機能のみを追加
- エッジに載せる関数の開発体験を保ちつつ、実行環境を軽量化
2. 厳格な制限による最適化 AWS 公式ドキュメントによると、以下の機能制限を実装しています。
セキュリティ制限:
- 動的コード評価の禁止 -
eval()、Functionコンストラクタはエラー - ネットワークアクセス遮断 - XHR、HTTP(S)、ソケット通信は不可
- システムアクセス禁止 - ファイルシステム、プロセス、環境変数へのアクセス不可
パフォーマンス制限:
- タイマー機能無効化 -
setTimeout()等は不可、同期実行のみ - 時間測定制限 - 高解像度タイマー禁止、経過時間測定不可
- メモリ制御 - 最大 2MB という厳格な制約
出典: AWS CloudFront Developer Guide - 制限された機能
これらの制限により、「起動時間が 1 ミリ秒未満、毎秒数百万のリクエストを処理するようにすぐにスケールでき、高い安全性がある実行環境」が実現されています。
まとめ
- ランタイム 2.0 を選ぶ -
const、letなど 1.0 に比べ書ける構文が増える exportsは使えない - モジュール化は諦めて関数内で整理- 制約は「制限」ではなく「最適化」 - パフォーマンス重視の意図的な設計
最後に
最初は「なぜ const が使えないの?」「いつもの JavaScript が動かない」という不満から始まりましたが、調べていくうちに、これらの制約がすべてパフォーマンスを向上させるために意図的に設計されたものだということがわかりました!
今回はあまり触れませんでしたが、制約を理解することで Lambda@Edge と CloudFront Functions をどう使い分けていけば良いか理解できた気がします。これから開発していく際にも、ツールごとの特性を理解して適切に使っていきたいと思います。
この記事が、みなさんの助けになれたら幸いです!