Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

templates(classic-compiler/cloudflare-workers): use static assets #10041

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -713,3 +713,4 @@
- zayenz
- zhe
- zwhitchcox
- zwily
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ node_modules
/build
/public/build
.env
.dev.vars
25 changes: 20 additions & 5 deletions templates/classic-remix-compiler/cloudflare-workers/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { LinksFunction } from "@remix-run/cloudflare";
import { cssBundleHref } from "@remix-run/css-bundle";
import {
Links,
LiveReload,
Expand All @@ -8,12 +6,25 @@ import {
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import type { LinksFunction } from "@remix-run/cloudflare";

import styles from "./tailwind.css";

export const links: LinksFunction = () => [
...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
{ rel: "stylesheet", href: styles },
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
{
rel: "preconnect",
href: "https://fonts.gstatic.com",
crossOrigin: "anonymous",
},
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
},
];

export default function App() {
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
Expand All @@ -23,11 +34,15 @@ export default function App() {
<Links />
</head>
<body>
<Outlet />
{children}
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}

export default function App() {
return <Outlet />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,130 @@ export const meta: MetaFunction = () => {

export default function Index() {
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
<h1>Welcome to Remix</h1>
<ul>
<li>
<a
target="_blank"
href="https://remix.run/tutorials/blog"
rel="noreferrer"
>
15m Quickstart Blog Tutorial
</a>
</li>
<li>
<a
target="_blank"
href="https://remix.run/tutorials/jokes"
rel="noreferrer"
>
Deep Dive Jokes App Tutorial
</a>
</li>
<li>
<a target="_blank" href="https://remix.run/docs" rel="noreferrer">
Remix Docs
</a>
</li>
</ul>
<div className="flex justify-center items-center h-screen">
<div className="flex flex-col gap-16 items-center">
<header className="flex flex-col gap-9 items-center">
<h1 className="text-2xl font-bold text-gray-800 leading dark:text-gray-100">
Welcome to <span className="sr-only">Remix</span>
</h1>
<div className="h-[144px] w-[434px]">
<img
src="/logo-light.png"
alt="Remix"
className="block w-full dark:hidden"
/>
<img
src="/logo-dark.png"
alt="Remix"
className="hidden w-full dark:block"
/>
</div>
</header>
<nav className="flex flex-col gap-4 justify-center items-center p-6 rounded-3xl border border-gray-200 dark:border-gray-700">
<p className="leading-6 text-gray-700 dark:text-gray-200">
What&apos;s next?
</p>
<ul>
{resources.map(({ href, text, icon }) => (
<li key={href}>
<a
className="flex gap-3 items-center self-stretch p-3 leading-normal text-blue-700 group hover:underline dark:text-blue-500"
href={href}
target="_blank"
rel="noreferrer"
>
{icon}
{text}
</a>
</li>
))}
</ul>
</nav>
</div>
</div>
);
}

const resources = [
{
href: "https://remix.run/start/quickstart",
text: "Quick Start (5 min)",
icon: (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="20"
viewBox="0 0 20 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
>
<path
d="M8.51851 12.0741L7.92592 18L15.6296 9.7037L11.4815 7.33333L12.0741 2L4.37036 10.2963L8.51851 12.0741Z"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
},
{
href: "https://remix.run/start/tutorial",
text: "Tutorial (30 min)",
icon: (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="20"
viewBox="0 0 20 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
>
<path
d="M4.561 12.749L3.15503 14.1549M3.00811 8.99944H1.01978M3.15503 3.84489L4.561 5.2508M8.3107 1.70923L8.3107 3.69749M13.4655 3.84489L12.0595 5.2508M18.1868 17.0974L16.635 18.6491C16.4636 18.8205 16.1858 18.8205 16.0144 18.6491L13.568 16.2028C13.383 16.0178 13.0784 16.0347 12.915 16.239L11.2697 18.2956C11.047 18.5739 10.6029 18.4847 10.505 18.142L7.85215 8.85711C7.75756 8.52603 8.06365 8.21994 8.39472 8.31453L17.6796 10.9673C18.0223 11.0653 18.1115 11.5094 17.8332 11.7321L15.7766 13.3773C15.5723 13.5408 15.5554 13.8454 15.7404 14.0304L18.1868 16.4767C18.3582 16.6481 18.3582 16.926 18.1868 17.0974Z"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
},
{
href: "https://remix.run/docs",
text: "Remix Docs",
icon: (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="20"
viewBox="0 0 20 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
>
<path
d="M9.99981 10.0751V9.99992M17.4688 17.4688C15.889 19.0485 11.2645 16.9853 7.13958 12.8604C3.01467 8.73546 0.951405 4.11091 2.53116 2.53116C4.11091 0.951405 8.73546 3.01467 12.8604 7.13958C16.9853 11.2645 19.0485 15.889 17.4688 17.4688ZM2.53132 17.4688C0.951566 15.8891 3.01483 11.2645 7.13974 7.13963C11.2647 3.01471 15.8892 0.951453 17.469 2.53121C19.0487 4.11096 16.9854 8.73551 12.8605 12.8604C8.73562 16.9853 4.11107 19.0486 2.53132 17.4688Z"
strokeWidth="1.5"
strokeLinecap="round"
/>
</svg>
),
},
{
href: "https://rmx.as/discord",
text: "Join Discord",
icon: (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="20"
viewBox="0 0 24 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
>
<path
d="M15.0686 1.25995L14.5477 1.17423L14.2913 1.63578C14.1754 1.84439 14.0545 2.08275 13.9422 2.31963C12.6461 2.16488 11.3406 2.16505 10.0445 2.32014C9.92822 2.08178 9.80478 1.84975 9.67412 1.62413L9.41449 1.17584L8.90333 1.25995C7.33547 1.51794 5.80717 1.99419 4.37748 2.66939L4.19 2.75793L4.07461 2.93019C1.23864 7.16437 0.46302 11.3053 0.838165 15.3924L0.868838 15.7266L1.13844 15.9264C2.81818 17.1714 4.68053 18.1233 6.68582 18.719L7.18892 18.8684L7.50166 18.4469C7.96179 17.8268 8.36504 17.1824 8.709 16.4944L8.71099 16.4904C10.8645 17.0471 13.128 17.0485 15.2821 16.4947C15.6261 17.1826 16.0293 17.8269 16.4892 18.4469L16.805 18.8725L17.3116 18.717C19.3056 18.105 21.1876 17.1751 22.8559 15.9238L23.1224 15.724L23.1528 15.3923C23.5873 10.6524 22.3579 6.53306 19.8947 2.90714L19.7759 2.73227L19.5833 2.64518C18.1437 1.99439 16.6386 1.51826 15.0686 1.25995ZM16.6074 10.7755L16.6074 10.7756C16.5934 11.6409 16.0212 12.1444 15.4783 12.1444C14.9297 12.1444 14.3493 11.6173 14.3493 10.7877C14.3493 9.94885 14.9378 9.41192 15.4783 9.41192C16.0471 9.41192 16.6209 9.93851 16.6074 10.7755ZM8.49373 12.1444C7.94513 12.1444 7.36471 11.6173 7.36471 10.7877C7.36471 9.94885 7.95323 9.41192 8.49373 9.41192C9.06038 9.41192 9.63892 9.93712 9.6417 10.7815C9.62517 11.6239 9.05462 12.1444 8.49373 12.1444Z"
strokeWidth="1.5"
/>
</svg>
),
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

html,
body {
@apply bg-white dark:bg-gray-950;

@media (prefers-color-scheme: dark) {
color-scheme: dark;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { type PlatformProxy } from "wrangler";

type GetLoadContextArgs = {
request: Request;
context: {
cloudflare: Omit<
PlatformProxy<Env, IncomingRequestCfProperties>,
"dispose" | "caches"
> & {
caches:
| PlatformProxy<Env, IncomingRequestCfProperties>["caches"]
| CacheStorage;
};
};
};

declare module "@remix-run/cloudflare" {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface AppLoadContext extends ReturnType<typeof getLoadContext> {
// This will merge the result of `getLoadContext` into the `AppLoadContext`
}
}

export function getLoadContext({ context }: GetLoadContextArgs) {
return context;
}
13 changes: 7 additions & 6 deletions templates/classic-remix-compiler/cloudflare-workers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"type": "module",
"scripts": {
"build": "remix build",
"deploy": "wrangler deploy",
"deploy": "npm run build && wrangler deploy",
"dev": "remix dev --manual -c \"npm start\"",
"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
"start": "wrangler dev ./build/index.js",
"typecheck": "tsc"
"start": "wrangler dev --no-x-dev-env ./build/index.js",
"typecheck": "tsc",
"typegen": "wrangler types"
},
"dependencies": {
"@cloudflare/kv-asset-handler": "^0.1.3",
"@remix-run/cloudflare": "*",
"@remix-run/css-bundle": "*",
"@remix-run/react": "*",
Expand All @@ -20,7 +20,7 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20230518.0",
"@cloudflare/workers-types": "^4.20240925.0",
"@remix-run/dev": "*",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
Expand All @@ -32,8 +32,9 @@
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"tailwindcss": "^3.4.4",
"typescript": "^5.1.6",
"wrangler": "^3.24.0"
"wrangler": "^3.80.0"
},
"engines": {
"node": ">=18.0.0"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export default {
server: "./server.ts",
serverConditions: ["workerd", "worker", "browser"],
serverDependenciesToBundle: [
// bundle everything except the virtual module for the static content manifest provided by wrangler
/^(?!.*\b__STATIC_CONTENT_MANIFEST\b).*$/,
// bundle everything except the external cloudflare:workers package
/^(?!.*\bcloudflare:workers\b).*$/,
],
serverMainFields: ["browser", "module", "main"],
serverMinify: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/// <reference types="@remix-run/dev" />
/// <reference types="@remix-run/cloudflare" />
/// <reference types="@cloudflare/workers-types" />

declare module "__STATIC_CONTENT_MANIFEST" {
const manifest: string;
export default manifest;
}
58 changes: 20 additions & 38 deletions templates/classic-remix-compiler/cloudflare-workers/server.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,38 @@
import { getAssetFromKV } from "@cloudflare/kv-asset-handler";
import type { AppLoadContext } from "@remix-run/cloudflare";
import { createRequestHandler, logDevReady } from "@remix-run/cloudflare";
import * as build from "@remix-run/dev/server-build";
// eslint-disable-next-line import/no-unresolved
import __STATIC_CONTENT_MANIFEST from "__STATIC_CONTENT_MANIFEST";
import { getLoadContext } from "./load-context";

const MANIFEST = JSON.parse(__STATIC_CONTENT_MANIFEST);
const handleRemixRequest = createRequestHandler(build, process.env.NODE_ENV);

if (process.env.NODE_ENV === "development") {
logDevReady(build);
}

export default {
async fetch(
request: Request,
env: {
__STATIC_CONTENT: Fetcher;
},
ctx: ExecutionContext
): Promise<Response> {
async fetch(request, env, ctx): Promise<Response> {
try {
const url = new URL(request.url);
const ttl = url.pathname.startsWith("/build/")
? 60 * 60 * 24 * 365 // 1 year
: 60 * 5; // 5 minutes
return await getAssetFromKV(
{
request,
waitUntil: ctx.waitUntil.bind(ctx),
} as FetchEvent,
{
ASSET_NAMESPACE: env.__STATIC_CONTENT,
ASSET_MANIFEST: MANIFEST,
cacheControl: {
browserTTL: ttl,
edgeTTL: ttl,
const loadContext = getLoadContext({
request,
context: {
cloudflare: {
// This object matches the return value from Wrangler's
// `getPlatformProxy` used during development via Remix's
// `cloudflareDevProxyVitePlugin`:
// https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy
cf: request.cf,
ctx: {
waitUntil: ctx.waitUntil.bind(ctx),
passThroughOnException: ctx.passThroughOnException.bind(ctx),
},
caches,
env,
},
}
);
} catch (error) {
// No-op
}

try {
const loadContext: AppLoadContext = {
env,
};
},
});
return await handleRemixRequest(request, loadContext);
} catch (error) {
console.log(error);
return new Response("An unexpected error occurred", { status: 500 });
}
},
};
} satisfies ExportedHandler<Env>;
Loading