This guide shows you how to deploy a Remix application to Edgio.
Edgio only supports Remix 1.x. Remix 2.x is unsupported due to Node.js requirements and its usage will generate runtime errors.
Example
Prerequisites
Setup requires:
- An Edgio account. Sign up for free.
- An Edgio property. Learn how to create a property.
- Node.js. View supported versions and installation steps.
- Edgio CLI.
Install the Edgio CLI
If you have not already done so, install the Edgio CLI.
Bash
1npm i -g @edgio/cli@latest
Create a New Remix App
If you don’t already have a Remix app, create one by running the following:
Bash
1npx create-remix@latest
To ensure your Remix app works with Edgio, make the following selections when prompted:
plaintext
1? What type of app do you want to create? (Use arrow keys)2❯ Just the basics3 A pre-configured stack ready for production4...5? Where do you want to deploy? Choose Remix App Server if you're unsure; it's easy to change deployment targets.6 Remix App Server7❯ Express Server8 Architect9 Fly.io10 Netlify11 Vercel12 Cloudflare Pages
You can verify your app works by running it locally with:
Bash
1npm run dev
Configuring Your Remix App for Edgio
Update the type Property in package.json
In most cases, a Remix app will have
"type": "module"
in the package.json
file. This property should be removed as Edgio does not support it at this time.JavaScriptpackage.json
1{2 "name": "remix-app",3 "version": "0.0.0",4 "description": "A Remix app",5 "main": "index.js",6 "type": "module",7 "scripts": {8 "dev": "remix dev",9 "build": "remix build",10 "start": "remix run"11 },12 ...13}
Initialize Your Project
In the root directory of your project run
edgio init
:Bash
1edgio init --edgioVersion latest --connector @edgio/express
This will automatically update your
package.json
and add all of the required Edgio dependencies and files to your project. These include:- The
@edgio/core
package - Allows you to declare routes and deploy your application on Edgio - The
@edgio/prefetch
package - Allows you to configure a service worker to prefetch and cache pages to improve browsing speed - The
@edgio/express
package - Allows you to run your application using the configured Express server edgio.config.js
- A configuration file for Edgioroutes.js
- A default routes file that sends all requests to Remix.
Modify Remix’s Server Configuration
Edgio requires a few changes to your configuration to correctly bundle your app.
Set Up the Express Server
If you created a Remix application by following the above steps, you will have already selected the Express server as your deployment target. If you are using an existing Remix application, you will need to update your
server.js
file with a compatible Express server.For either scenario, we’ve provided a sample Express server below that you can use to replace the default
server.js
file in your project.JavaScriptserver.js
1 import * as fs from "node:fs";2 const fs = require("node:fs");34 import { createRequestHandler } from "@remix-run/express";5 const { createRequestHandler } = require("@remix-run/express");6 import { broadcastDevReady, installGlobals } from "@remix-run/node";7 const { broadcastDevReady, installGlobals } = require("@remix-run/node");8 import chokidar from "chokidar";9 const chokidar = require("chokidar");10 import compression from "compression";11 const compression = require("compression");12 import express from "express";13 const express = require("express");14 import morgan from "morgan";15 const morgan = require("morgan");1617installGlobals();1819const BUILD_PATH = "./build/index.js";20/**21 * @type { import('@remix-run/node').ServerBuild | Promise<import('@remix-run/node').ServerBuild> }22 */23 let build = await import(BUILD_PATH);24 let build = require(BUILD_PATH);2526const app = express();2728app.use(compression());2930// http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header31app.disable("x-powered-by");3233// Remix fingerprints its assets so we can cache forever.34app.use(35 "/build",36 express.static("public/build", { immutable: true, maxAge: "1y" })37);3839// Everything else (like favicon.ico) is cached for an hour. You may want to be40// more aggressive with this caching.41app.use(express.static("public", { maxAge: "1h" }));4243app.use(morgan("tiny"));4445app.all(46 "*",47 process.env.NODE_ENV === "development"48 ? createDevRequestHandler()49 : createRequestHandler({50 build,51 mode: process.env.NODE_ENV,52 })53);5455const port = process.env.PORT || 3000;56app.listen(port, async () => {57 console.log(`Express server listening on port ${port}`);5859 if (process.env.NODE_ENV === "development") {60 broadcastDevReady(build);61 }62});6364function createDevRequestHandler() {65 const watcher = chokidar.watch(BUILD_PATH, { ignoreInitial: true });6667 watcher.on("all", async () => {68 // 1. purge require cache && load updated server build69 const stat = fs.statSync(BUILD_PATH);70 build = import(BUILD_PATH + "?t=" + stat.mtimeMs);71 // 2. tell dev server that this app server is now ready72 broadcastDevReady(await build);73 });7475 return async (req, res, next) => {76 try {77 //78 return createRequestHandler({79 build: await build,80 mode: "development",81 })(req, res, next);82 } catch (error) {83 next(error);84 }85 };86}
Note that the
server.js
file is using CommonJS require
instead of ES import
. This is required for Edgio to correctly bundle your app.Update the servermoduleformat Property in remix.config.js
Use the CommonJS module format by setting the
serverModuleFormat
property in the remix.config.js
file to cjs
.JavaScriptremix.config.js
1/** @type {import('@remix-run/dev').AppConfig} */2 export default {3 module.exports = {4 ignoredRouteFiles: ["**/.*"],5 // appDirectory: "app",6 // assetsBuildDirectory: "public/build",7 // serverBuildPath: "build/index.js",8 // publicPath: "/build/",9 serverModuleFormat: "esm",10 serverModuleFormat: "cjs",11 future: {12 v2_dev: true,13 v2_errorBoundary: true,14 v2_headers: true,15 v2_meta: true,16 v2_normalizeFormMethod: true,17 v2_routeConvention: true,18 },19};
With various changes made to the Remix app configuration, it’s important to ensure that the app still works as expected. Build the app locally using
npm run build
to verify there are no errors.Update Edgio Configuration File
Update
edgio.config.js
serverless
property to include the public
and build
directories:JavaScriptedgio.config.js
1// This file was automatically added by edgio init.2// You should commit this file to source control.3// Learn more about this file at https://docs.edg.io/guides/edgio_config4module.exports = {5 connector: '@edgio/express',67 /* ... */89 // Options for hosting Cloud Functions on Edgio10 serverless: {11 // Set to true to include all packages listed in the dependencies property of package.json when deploying to Edgio.12 // This option generally isn't needed as Edgio automatically includes all modules imported by your code in the bundle that13 // is uploaded during deployment14 // includeNodeModules: false,1516 // Include additional paths that are dynamically loaded by your app at runtime here when building the serverless bundle.17 include: ['public/**/*', 'build/**/*'],18 },1920 /* ... */21}
Configure the Caching Policy
Update the
routes.[js|ts]
to add a caching policy for your app’s SSR pages and static assets:JavaScriptroutes.js
1/// This file was automatically added by edgio init.2// You should commit this file to source control.3import { Router } from '@edgio/core'45export default new Router()6 .match('/:path*', {7 caching: {8 max_age: '1d',9 stale_while_revalidate: '1d',10 service_worker_max_age: '1h',11 },1213 origin: {14 set_origin: 'edgio_serverless',15 },16 })17 .static('public')
Refer to the CDN-as-code guide for the full syntax of the
routes.js
file and how to configure it for your use case.Run the Remix App Locally on Edgio
Create a development build of your app by running the following in your project’s root directory:
Bash
1# start the Edgio dev server2edgio dev
Load the site http://127.0.0.1:3000
Deploying
Create a production build of your app by running the following in your project’s root directory:
Bash
1# build your app for production2npm run build
Deploy your app to the Sites by running the following command in your project’s root directory:
Bash
1# deploy the Edgio production bundle2edgio deploy
Your initial CDN-as-code deployment will generate system-defined origin configurations along with those defined within your
edgio.config.js
. Learn more about system-defined origins.Refer to the Deployments guide for more information on the
deploy
command and its options.