In today's deep dive, I'll be unpacking my journey of deploying Remix on AWS, specifically as a Lambda function.
For the tech aficionados, dive into the code details in our web platform's repository here: https://github.com/pagemosaic/pagemosaic-web-platform
Remix Handler
Let's cut through the jargon: Remix is versatile enough to run on various JavaScript runtimes, making it a perfect candidate for AWS Lambda functions.
Here’s the catch: Remix typically nestles within an HTTP server to handle requests. This requires a specialized adapter to interface with various HTTP servers. So, in a Lambda environment (essentially a JavaScript runtime container), we leverage an HTTP server to fetch web pages as responses.
In a turn away from conventional servers like Express, I opted for Remix's native solution – the Remix App Server. However, Lambda's distinct request handling interface necessitated a custom adapter for effective Remix integration.
Remix Adapter
The Remix library does offer an AWS Lambda adapter. Yet, it's tied to a framework I sidestepped: AWS Architect, known for orchestrating Lambda microservices and S3-backed websites.
So, I extracted the crucial elements from the adapter’s code, creating a bespoke module – the web-adapter
– in my project.
Remix Web Application
What's next? Developing the web application module itself using Remix. Given my preference for Vite or Rollup for module compilation, Vite was my go-to for bundling the web application.
Here's a twist for Remix web applications: they require dual bundles. One for the client side (sans server-executable code) and another for the server side.
Thus, the build command for the web application module aligns as vite build && vite build --ssr
. Peek into the web-app
module's code in our GitHub repository.
Bundle All
Now, deploying the server-side bundle on AWS as a Lambda function means integrating it with the custom web-adapter
module.
This led to introducing Rollup with a configuration merging dependencies from both modules, resulting in a Lambda-ready JS runtime bundle.
The final build command for my web application stands as vite build && vite build --ssr && NODE_ENV='production' rollup -c rollup.config.mjs
.
But it’s not just about code. I tweaked the Remix directory structure for a streamlined deployment process – separating the server part as a Lambda function and the client part as static files in an S3 bucket.
Deployment
The next phase involved crafting CDK constructs for Lambda function creation and HTTP endpoint setup for the web application, alongside another construct for deploying the client's static files.
You can unearth these construct codes in the infra module files: web-app-api.ts
, system-bucket.ts
, system-bucket-deployment.ts
. Strategically, these are split into distinct constructs for tailored resource initialization sequences on AWS.
Entry Point
Finally, I assembled a construct for creating a CloudFront distribution with varied access points for both the web application and static resources. Find this code in enty-point.ts
in the infra
module.
That wraps up my Remix utilization saga for our web platform. Keen on taking it for a spin? The launchpad awaits in the readme of our source code repository: https://github.com/pagemosaic/pagemosaic-web-platform.
Follow Alex Pust on Twitter for updates on the Page Mosaic Web Platform development.
Top comments (0)