Skip to content
This repository has been archived by the owner on Oct 21, 2024. It is now read-only.

Commit

Permalink
docs: example remix streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
jayair committed Sep 19, 2024
1 parent fe6822b commit 7fa1617
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 44 deletions.
98 changes: 68 additions & 30 deletions examples/aws-remix-stream/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,80 @@
import { defer, type MetaFunction } from "@remix-run/node";
import { Await, useLoaderData } from "@remix-run/react";
import { Suspense } from "react";
import { Await, useLoaderData } from "@remix-run/react";
import { defer, LoaderFunction } from "@remix-run/node";
import styles from "~/styles/index.css?url";

export const meta: MetaFunction = () => {
return [
{ title: "New Remix App" },
{ name: "description", content: "Welcome to Remix!" },
];
};
export const links = () => [
{ rel: "stylesheet", href: styles },
];

export const loader = async () => {
const n = Date.now();
const d = new Promise<number>((res) =>
setTimeout(() => res(Date.now() - n), 2000),
);
interface Character {
name: string;
image: string;
description?: string;
}

return defer({ n: 0, d });
interface LoaderData {
spongebob: Character;
friends: Character[];
}

export const loader: LoaderFunction = async () => {
const spongebob = {
name: "SpongeBob SquarePants",
description: "SpongeBob SquarePants is the main character of the popular animated TV series. He's a cheerful sea sponge who lives in a pineapple house in the underwater city of Bikini Bottom. SpongeBob works as a fry cook at the Krusty Krab and loves jellyfishing with his best friend Patrick Star.",
image: "spongebob.png",
};
const friendsPromise = new Promise((resolve) => {
setTimeout(() => {
resolve(
[
{ name: "Patrick Star", image: "patrick.png" },
{ name: "Sandy Cheeks", image: "sandy.png" },
{ name: "Squidward Tentacles", image: "squidward.png" },
{ name: "Mr. Krabs", image: "mr-krabs.png" },
]
);
}, 3000);
});

return defer({
spongebob,
friends: friendsPromise,
});
};

export default function Index() {
const { n, d } = useLoaderData<typeof loader>();
const { spongebob, friends } = useLoaderData<LoaderData>();

return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
<h1>Welcome to Remix</h1>

<p>
If streaming is working properly, you should see the first line appear
alone. Shortly after the second will appear.
</p>
<p>If streaming is NOT working, both will appear at the same time.</p>

<div>rendered: {n}</div>
<Suspense>
<Await resolve={d}>
{(d) => <div>deferred: {d.toLocaleString()}</div>}
</Await>
</Suspense>
<div className="container">
<section className="bio-section">
<h1>{spongebob.name}</h1>
<div className="bio-content">
<div className="bio-text">
<p>{spongebob.description}</p>
</div>
<img src={spongebob.image} alt={spongebob.name} />
</div>
</section>

<section>
<h2>Friends from Bikini Bottom</h2>
<Suspense fallback={<div>Loading...</div>}>
<Await resolve={friends}>
{(friends) => (
<div className="character-grid">
{friends.map((friend) => (
<div key={friend.name} className="character-card">
<img src={friend.image} alt={friend.name} />
<p>{friend.name}</p>
</div>
))}
</div>
)}
</Await>
</Suspense>
</section>
</div>
);
}
41 changes: 41 additions & 0 deletions examples/aws-remix-stream/app/styles/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f0f8ff;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.bio-section {
background-color: #fff;
padding: 20px;
margin-bottom: 20px;
border-radius: 10px;
}
.bio-content {
display: flex;
align-items: center;
}
.bio-text {
flex: 1;
padding-right: 20px;
}
.character-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 20px;
}
.character-card {
background-color: #fff;
padding: 10px;
border-radius: 5px;
text-align: center;
}
img {
max-width: 100%;
height: auto;
border-radius: 5px;
}
Binary file removed examples/aws-remix-stream/bun.lockb
Binary file not shown.
10 changes: 5 additions & 5 deletions examples/aws-remix-stream/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
"typecheck": "tsc"
},
"dependencies": {
"@remix-run/node": "^2.8.1",
"@remix-run/react": "^2.8.1",
"@remix-run/serve": "^2.8.1",
"@remix-run/node": "^2.12.1",
"@remix-run/react": "^2.12.1",
"@remix-run/serve": "^2.12.1",
"isbot": "^4.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"sst": "latest"
},
"devDependencies": {
"@remix-run/dev": "^2.8.1",
"@remix-run/dev": "^2.12.1",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.7.4",
Expand All @@ -36,6 +36,6 @@
"vite-tsconfig-paths": "^4.2.1"
},
"engines": {
"node": "\u003e=18.0.0"
"node": ">=18.0.0"
}
}
Binary file added examples/aws-remix-stream/public/mr-krabs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/aws-remix-stream/public/patrick.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/aws-remix-stream/public/sandy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/aws-remix-stream/public/spongebob.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/aws-remix-stream/public/squidward.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 13 additions & 1 deletion examples/aws-remix-stream/sst-env.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
/// <reference path="./.sst/types.generated.ts" />
/* This file is auto-generated by SST. Do not edit. */
/* tslint:disable */
/* eslint-disable */
import "sst"
export {}
declare module "sst" {
export interface Resource {
"MyWeb": {
"type": "sst.aws.Remix"
"url": string
}
}
}
47 changes: 39 additions & 8 deletions examples/aws-remix-stream/sst.config.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,52 @@
/// <reference path="./.sst/platform/config.d.ts" />

/**
* ## AWS Remix Streaming
*
* Follows the [Remix Streaming](https://remix.run/docs/en/main/guides/streaming) guide to create
* an app that streams data.
*
* Uses the `defer` utility to stream data through the `loader` function.
*
* ```tsx title="app/routes/_index.tsx"
* return defer({
* spongebob,
* friends: friendsPromise,
* });
* ```
*
* Then uses the the `Suspense` and `Await` components to render the data.
*
* ```tsx title="app/routes/_index.tsx"
* <Suspense fallback={<div>Loading...</div>}>
* <Await resolve={friends}>
* { /* ... *\/ }
* </Await>
* </Suspense>
* ```
*
* You should see the _friends_ section load after a 3 second delay.
*
* :::note
* Safari handles streaming differently than other browsers.
* :::
*
* Safari uses a [different heuristic](https://bugs.webkit.org/show_bug.cgi?id=252413) to
* determine when to stream data. You need to render _enough_ initial HTML to trigger streaming.
* This is typically only a problem for demo apps.
*
* Streaming works out of the box with the `Remix` component.
*
*/
export default $config({
app(input) {
return {
name: "aws-remix-stream",
removal: input?.stage === "production" ? "retain" : "remove",
home: "aws",
providers: {
aws: {
region: "us-west-1",
},
},
};
},
async run() {
new sst.aws.Remix("MyWeb", {
buildCommand: "npm run build",
});
new sst.aws.Remix("MyWeb");
},
});
43 changes: 43 additions & 0 deletions www/src/content/docs/docs/examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,49 @@ return {
View the [full example](https://github.com/sst/ion/tree/dev/examples/aws-queue).


---
## AWS Remix Streaming

Follows the [Remix Streaming](https://remix.run/docs/en/main/guides/streaming) guide to create
an app that streams data.

Uses the `defer` utility to stream data through the `loader` function.

```tsx title="app/routes/_index.tsx"
return defer({
spongebob,
friends: friendsPromise,
});
```

Then uses the the `Suspense` and `Await` components to render the data.

```tsx title="app/routes/_index.tsx"
<Suspense fallback={<div>Loading...</div>}>
<Await resolve={friends}>
{ /* ... */ }
</Await>
</Suspense>
```

You should see the _friends_ section load after a 3 second delay.

:::note
Safari handles streaming differently than other browsers.
:::

Safari uses a [different heuristic](https://bugs.webkit.org/show_bug.cgi?id=252413) to
determine when to stream data. You need to render _enough_ initial HTML to trigger streaming.
This is typically only a problem for demo apps.

Streaming works out of the box with the `Remix` component.
```ts title="sst.config.ts"
new sst.aws.Remix("MyWeb");
```

View the [full example](https://github.com/sst/ion/tree/dev/examples/aws-remix-stream).


---
## Router and bucket

Expand Down

0 comments on commit 7fa1617

Please sign in to comment.