Nuxt/S3/CloudFront(OAI)でfaviconが見つからない問題をLambda@Edge(Node.js)で解決

当記事は、半年以上前に投稿されたものです。そのため、古い技術や情報をもとに書かれている可能性があります。参照する際は十分に注意していただければです。

先日、Nuxt.js / S3 / CloudFront で Jamstack なサイトを作っていると、/XXX/favicon.ico is not foundが発生。

うん?

favicon.ico はルートにしか置いてないよ… emoji-full_moon_with_face

ということで、Lambda@Edge でリクエストを操作して、/XXX/favicon.ico -> /favicon.ico にリダイレクトされるように対応しました。

コード

ちなみに、下記のコードは Classmethod さんのコチラの記事を大いに参考にしています emoji-beers

exports.lambdaHandler = async (event, context, callback) => {

  // CloudFrontのイベントからリクエストを抽出
  let request = event.Records[0].cf.request;

  const oldUri = request.uri; // リクエストから変換前のURI
  const newUri = redirectUri(oldUri); // 変換条件からURIを変更

  // リクエストに変換後のURLを注入
  request.uri = newUri;

  return callback(null, request);
};

const redirectUri = (uri) => {

  // favicon.ico はルートディレクトリにして返す
  if (uri.indexOf('favicon.ico') !== -1) {
    return '/favicon.ico';
  }

  // pathの末端が拡張子付きである場合は、そのまま返す
  if (uri.split('/').pop().search(/\./) !== -1) {
    return uri;
  }

  // 末尾に'/'がない場合は、'/index.html'を追加
  if (uri.search(/\/$/) === -1) {
    return uri + '/index.html'; // 末尾に'/'を追加
  }

  // 末尾が'/'の場合、つまり、'/xxx/' -> '/xxx/index.html' に変換
  if (uri.search(/\/$/) !== -1) {
    return uri + 'index.html'; // 末尾に'index.html'を追加
  }

  return uri;
};

favicon.ico 対応意外にも、/XXX -> /XXX/index.html など幾つか細かい対応をしています。

参考文献


Canji

クラウド周りをちょこまかしたい注意散漫人間。個人開発を楽しんでいたあの頃。