Introducing Edgio Applications v7Find out what's new.
Edgio
Edgio

Remix

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:

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 basics
3 A pre-configured stack ready for production
4...
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 Server
7❯ Express Server
8 Architect
9 Fly.io
10 Netlify
11 Vercel
12 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 Edgio
  • routes.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");
3
4 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");
16
17installGlobals();
18
19const 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);
25
26const app = express();
27
28app.use(compression());
29
30// http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header
31app.disable("x-powered-by");
32
33// Remix fingerprints its assets so we can cache forever.
34app.use(
35 "/build",
36 express.static("public/build", { immutable: true, maxAge: "1y" })
37);
38
39// Everything else (like favicon.ico) is cached for an hour. You may want to be
40// more aggressive with this caching.
41app.use(express.static("public", { maxAge: "1h" }));
42
43app.use(morgan("tiny"));
44
45app.all(
46 "*",
47 process.env.NODE_ENV === "development"
48 ? createDevRequestHandler()
49 : createRequestHandler({
50 build,
51 mode: process.env.NODE_ENV,
52 })
53);
54
55const port = process.env.PORT || 3000;
56app.listen(port, async () => {
57 console.log(`Express server listening on port ${port}`);
58
59 if (process.env.NODE_ENV === "development") {
60 broadcastDevReady(build);
61 }
62});
63
64function createDevRequestHandler() {
65 const watcher = chokidar.watch(BUILD_PATH, { ignoreInitial: true });
66
67 watcher.on("all", async () => {
68 // 1. purge require cache && load updated server build
69 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 ready
72 broadcastDevReady(await build);
73 });
74
75 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_config
4module.exports = {
5 connector: '@edgio/express',
6
7 /* ... */
8
9 // Options for hosting Cloud Functions on Edgio
10 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 that
13 // is uploaded during deployment
14 // includeNodeModules: false,
15
16 // Include additional paths that are dynamically loaded by your app at runtime here when building the serverless bundle.
17 include: ['public/**/*', 'build/**/*'],
18 },
19
20 /* ... */
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'
4
5export default new Router()
6 .match('/:path*', {
7 caching: {
8 max_age: '1d',
9 stale_while_revalidate: '1d',
10 service_worker_max_age: '1h',
11 },
12
13 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 server
2edgio 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 production
2npm 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 bundle
2edgio 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.