iTranslated by AI
Pitfalls of Configuring Remix on Cloudflare Workers
During this New Year's holiday, I was playing around with Remix on Cloudflare Workers.
None of these would have been issues if I had read the official documentation thoroughly, but in my case, I struggled a bit, so I'm writing this down as an article. Here are the four things I got stuck on:
- Handling environment variables on both the server and frontend sides
- Using Tailwind CSS
- Deploying using GitHub Actions
- Not being able to use certain Node.js libraries
Development Environment Setup
Setup was very easy.
The development environment for Remix on Cloudflare Workers can be easily set up with the following command:
$ npx create-remix@latest
When you run the command above, you will be asked where you want to deploy, so select Cloudflare Workers.
? Where do you want to deploy? Choose Remix if you're unsure, it's easy to change deployment targets.
Express Server
Architect (AWS Lambda)
Fly.io
Netlify
Vercel
Cloudflare Pages
❯ Cloudflare Workers
(Move up and down to reveal more choices)
Also, you need to install Wrangler separately as a tool for building functions and deploying to Cloudflare. You can install it using npm.
$ npm install -g @cloudflare/wrangler
1. Handling environment variables on the server and frontend
In local development, you can use .env files as follows.
However, instead of extracting environment variables from process.env like process.env.API_KEY, constants are defined globally as they are on the server side.
Therefore, when using TypeScript, it was necessary to define the types for the environment variables used in global.d.ts or similar.
declare const SUPABASE_ANON_KEY: string
When using environment variables on the Cloudflare Workers side, you need to define them using Wrangler.
$ wrangler secret put SUPABASE_ANON_KEY
However, since these environment variables cannot be used on the frontend side, it was necessary to pass them to the frontend using a loader as shown below. This is a bit inconvenient.
export function loader() {
return {
ENV: {
SUPABASE_URL: SUPABASE_URL,
SUPABASE_ANON_KEY: SUPABASE_ANON_KEY,
}
}
}
export function Root() {
const data = useLoaderData();
return (
<html>
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<script
dangerouslySetInnerHTML={{
__html: `window.ENV = ${JSON.stringify(
data.ENV
)}`
}}
/>
<Scripts />
</body>
</html>
);
}
By doing this, you can retrieve environment variables from the frontend side in the form of window.ENV.SUPABASE_URL.
Therefore, when using TypeScript, define the environment variable types on the window side for the frontend as well, as follows:
interface Window {
ENV: {
SUPABASE_ANON_KEY: string
}
}
2. Using Tailwind CSS
When npx create-remix@latest is executed, a package.json is automatically generated. Modify this package.json slightly so that tailwind.css is built when running npm run start, outputting the result to ./app/styles/tailwind.css.
"scripts": {
- "build": "remix build",
+ "build": "npm run build:css && npm run build:remix",
+ "build:remix": "remix build",
+ "build:css": "tailwindcss --output ./app/styles/tailwind.css --minify",
"dev": "remix watch",
"postinstall": "remix setup cloudflare-workers",
"build:worker": "esbuild --define:process.env.NODE_ENV='\"production\"' --minify --bundle --sourcemap --outdir=dist ./worker",
"dev:worker": "esbuild --define:process.env.NODE_ENV='\"development\"' --bundle --sourcemap --outdir=dist ./worker",
- "start": "miniflare --build-command \"npm run dev:worker\" --watch",
+ "start": "npm-run-all -p start:*",
+ "start:css": "tailwindcss --output ./app/styles/tailwind.css --watch",
+ "start:miniflare": "miniflare --build-command \"npm run dev:worker\" --watch",
"deploy": "npm run build && wrangler publish"
},
Import the outputted CSS in root.tsx as follows.
import tailwindStyles from "~/styles/tailwind.css";
export const links: LinksFunction = () => {
return [
{ rel: "stylesheet", href: tailwindStyles },
];
};
3. Automating deployment using GitHub Actions
Install Wrangler globally on CI as shown below, and set CF_EMAIL and CF_API_TOKEN as GitHub environment variables.
steps:
- name: checkout
uses: actions/checkout@v1
- name: setup Node
uses: actions/setup-node@v1
with:
node-version: 16.x
registry-url: 'https://registry.npmjs.org'
- name: install
run: npm ci
- name: install wrangler
run: npm i @cloudflare/wrangler -g
- name: set env
run: |
echo "CF_EMAIL=${CF_EMAIL}" >> $GITHUB_ENV
echo "CF_API_TOKEN=${CF_API_TOKEN}" >> $GITHUB_ENV
env:
CF_EMAIL: ${{secrets.CLOUDFLARE_EMAIL}}
CF_API_TOKEN: ${{secrets.WRANGLER_API_KEY}}
- name: publish
run: npm run deploy
CF_EMAIL is the email address used to log in to Cloudflare, and CF_API_TOKEN is the API token obtained from the Cloudflare dashboard.
Issuing an API Token
You can issue a token from the following page.
You can easily generate a token by selecting the "Edit Cloudflare Workers" template.
4. Some Node.js libraries cannot be used
This was entirely due to my own lack of research, but since Cloudflare Workers is different from Node, standard Node libraries such as fs and net/http cannot be used. Consequently, libraries that depend on those standard libraries also could not be used.
Many packages that require Node dependencies, such as fs or net/http, aren't supported in Workers because Workers isn't Node—it's built on V8.
Conclusion
These three things were the points I got stuck on while working with Remix. Since I'm so used to Next.js, I faced various challenges.
I'll add more to this article if I encounter any other issues with the Remix on Cloudflare Workers configuration.
Discussion