En el artículo anterior donde se explicaba como desplegar Gatsby usando AWS Amplify encontré que CloudFront no funcionama como se esperaba que era mostrar el sitio qlojado en el caché y cada vez que se mostraba la página las imagenes tomaban tiempo para cargar, además que cada vez que se abría en una pestaña nueva cualquier link, se redirigía a la vista inicial.
Estos problemas se debían a que Amplify esperaba que se mostrara el archivo index.html de cada ruta generada en el build, al no estar debidamente configurada no podía encontrar dicho archivo y tampoco podía encontrar ni mostrar la vista el error 404.
La solución encontrada fue la siguiente:
Configurar Gatsby
Asegurar que toda url generada por Gatsby culminara en slash ’/‘.
Para esto se debe instalar un plugin
1yarn add gatsby-plugin-canonical-urls
Luego agregar en la sección de plugins los siguiente
1{2 resolve: `gatsby-plugin-canonical-urls`,3 options: {4 siteUrl: `https://javierfonseca.me`,5 },6 },
Configurar AWS Amplify
Se debe crear una nueva instancia de Amplify
1amplify configure
Luego agregar el hosting, seleccionar S3 con CloudFront
1amplify add hosting
Este proceso de configuración crea un nuevo S3 Buckect y lo relaciona con una nueva distribución de CloudFront.
Para hacer la publicación a AWS se debe usar el siguiente comando
1amplify publish
Configurar Route 53
En caso que el dominio esté registrado en AWS, se debe actualizar el DNS a la nueva distribución de CloudFront para que los cambios se puedan visualizar.
Configurar CloudFront
Asegurar que todo error en url mostrara error 404
En la distribución creada de CloudFront, seleccionar la pestaña Error pages
, modificar 404 en Response Page Path
por `/404/“
Lambda Edge
Edge es un nuevo servicio de AWS para CloudFront que según como se describe sirve para mejorar el performance y reducir la latencia, cualquier función puede ser usada para el antes, durante y después de que CloudFront reciba un request. Para la solución se usará para el evento antes de procesar el request.
Crear función Lambda
Para preprocesar el request recibido por CloudFront la función debe ser creada usando la versión de NodeJS 10.16.3 y el cuerpo de la función debe ser la siguiente
1'use strict';2var path = require('path');3exports.handler = (event, context, callback) => {45 function is_numeric(str){6 return /^\d+$/.test(str);7 }89 // Extrae el request de CloudFront que va a ser enviado a Lambda@Edge10 var request = event.Records[0].cf.request;1112 // Extrae la URI del request13 var olduri = request.uri;1415 // Extrae la extensión de la URI16 var extension = path.extname(olduri);1718 // Extrae el último caracter de la URI19 var last_character = olduri.slice(-1);2021 // Valida si el última caracter es un número, esto sirve para evitar redirección al navegar en el paginador.22 if (is_numeric(last_character) === true) {23 return callback(null, request);24 }25 else {26 // Asigna /index.html para que CloudFront pueda encontrar la ubicación de la URL27 var newuri = `${olduri}/`;28 newuri = olduri.replace(olduri.slice(-1), '\/index.html');29 request.uri = newuri;30 return callback(null, request);31 }32};
Este código reconstruye la url para que CloudFront reconozca la ubicación del archivo html, en el browser no se verá cambio alguno porque no hace la reescritura como lo haría un servidor Apache o NGINX.
La validación de la estensión y último caracter es para poder mostrar los demas archivos como los assets y js, en este caso lambda no hace ningun cambio y devuelve la urice tal como se solicitó.
Modificación del rol creado por Lambda para reconocer CloudFront
Cuando se creó Lambda si se seleccionó “crear nuevo rol” o “usar rol existente” se debe agregar un Trust Relationship
de edgelambda para que se pueda generar la réplica de CloudFront
Al hacer click en Edit trust relationship
el json debe quedar de la siguiente forma
1{2 "Version": "2012-10-17",3 "Statement": [4 {5 "Effect": "Allow",6 "Principal": {7 "Service": [8 "edgelambda.amazonaws.com",9 "lambda.amazonaws.com"10 ]11 },12 "Action": "sts:AssumeRole"13 }14 ]15}
Invalidar caché de CloudFront
En caso que se haya ingresado a cualquier url del sitio y se necesite ver los cambios generados, se debe limpiar el caché de CloudFront porque por default el caché dura 24 horas, para crear la invalidación se debe modificar directamente en la distribución usando /*
Agregar réplica de CloudFront a Lambda
En la consola de Lambda se debe hacer lo siguiente
Seleccionar Deploy to Lambda@Edge
Crear réplica
Seleccionar Add Trigger
y luego CloudFront
Como paso final, queda esperar a que se progague en todo Cloudfront para poder acceder al sitio, de lo contrario se verá Access denied
al llamar a la url.
Una vez finalizada la propagación las imagenes se cargarán más rápido y todos los links estarán funcionales
Share