Skip to content

Commit 41da85c

Browse files
committed
doc: add remix example
1 parent cf156ab commit 41da85c

File tree

17 files changed

+7415
-0
lines changed

17 files changed

+7415
-0
lines changed

example-remix/.eslintrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": ["@remix-run/eslint-config", "@remix-run/eslint-config/node"]
3+
}

example-remix/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
3+
/.cache
4+
/build
5+
/public/build
6+
.env

example-remix/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Welcome to Remix!
2+
3+
- [Remix Docs](https://remix.run/docs)
4+
5+
## Development
6+
7+
From your terminal:
8+
9+
```sh
10+
npm run dev
11+
```
12+
13+
This starts your app in development mode, rebuilding assets on file changes.
14+
15+
## Deployment
16+
17+
First, build your app for production:
18+
19+
```sh
20+
npm run build
21+
```
22+
23+
Then run the app in production mode:
24+
25+
```sh
26+
npm start
27+
```
28+
29+
Now you'll need to pick a host to deploy it to.
30+
31+
### DIY
32+
33+
If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34+
35+
Make sure to deploy the output of `remix build`
36+
37+
- `build/`
38+
- `public/build/`
39+
40+
### Using a Template
41+
42+
When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new project, then copy over your `app/` folder to the new project that's pre-configured for your target server.
43+
44+
```sh
45+
cd ..
46+
# create a new project, and pick a pre-configured host
47+
npx create-remix@latest
48+
cd my-new-remix-app
49+
# remove the new project's app (not the old one!)
50+
rm -rf app
51+
# copy your app over
52+
cp -R ../my-old-remix-app/app app
53+
```

example-remix/app/entry.client.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { RemixBrowser } from '@remix-run/react';
2+
import { hydrateRoot } from 'react-dom/client';
3+
4+
hydrateRoot(document, <RemixBrowser />);

example-remix/app/entry.server.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { EntryContext } from '@remix-run/node';
2+
import { RemixServer } from '@remix-run/react';
3+
import { renderToString } from 'react-dom/server';
4+
import { IconsCache, SpriteContextProvider } from 'react-lazy-svg';
5+
import { renderSpriteSheetToString } from 'react-lazy-svg/dist/ssr';
6+
import { readSvg } from './serverLoadSvg';
7+
8+
export default async function handleRequest(
9+
request: Request,
10+
responseStatusCode: number,
11+
responseHeaders: Headers,
12+
remixContext: EntryContext,
13+
) {
14+
const sessionIcons: IconsCache = new Map();
15+
16+
remixContext.appState;
17+
18+
const markup = renderToString(
19+
<SpriteContextProvider loadSVG={readSvg} knownIcons={sessionIcons}>
20+
<RemixServer context={remixContext} url={request.url} />
21+
</SpriteContextProvider>,
22+
);
23+
24+
const extendedMarkup = await renderSpriteSheetToString(markup, sessionIcons);
25+
26+
responseHeaders.set('Content-Type', 'text/html');
27+
28+
return new Response('<!DOCTYPE html>' + extendedMarkup, {
29+
status: responseStatusCode,
30+
headers: responseHeaders,
31+
});
32+
}

example-remix/app/icons/icon1.svg

Lines changed: 7 additions & 0 deletions
Loading

example-remix/app/icons/icon2.svg

Lines changed: 7 additions & 0 deletions
Loading

example-remix/app/root.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import type { MetaFunction } from '@remix-run/node';
2+
import {
3+
Links,
4+
LiveReload,
5+
Meta,
6+
Outlet,
7+
Scripts,
8+
ScrollRestoration,
9+
} from '@remix-run/react';
10+
import { initOnClient, SpriteContextProvider } from 'react-lazy-svg';
11+
12+
export const meta: MetaFunction = () => ({
13+
charset: 'utf-8',
14+
title: 'New Remix App',
15+
viewport: 'width=device-width,initial-scale=1',
16+
});
17+
18+
const isClient = typeof window !== 'undefined';
19+
20+
if (isClient) {
21+
initOnClient();
22+
}
23+
24+
const loadSVG = async (url: string) => {
25+
return await (await fetch(url)).text();
26+
};
27+
28+
export default function App() {
29+
return (
30+
<html lang="en">
31+
<head>
32+
<Meta />
33+
<Links />
34+
</head>
35+
<body>
36+
<SpriteContextProvider embeddedSSR loadSVG={loadSVG}>
37+
<Outlet />
38+
<ScrollRestoration />
39+
<Scripts />
40+
<LiveReload />
41+
</SpriteContextProvider>
42+
</body>
43+
</html>
44+
);
45+
}

example-remix/app/routes/index.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { useState } from 'react';
2+
import { Links } from '@remix-run/react';
3+
import { Icon } from 'react-lazy-svg';
4+
import icon1 from '../icons/icon1.svg';
5+
import icon2 from '../icons/icon2.svg';
6+
7+
import stylesheetUrl from '../styles.css';
8+
9+
export function links() {
10+
return [{ rel: 'stylesheet', href: stylesheetUrl }];
11+
}
12+
13+
export default function Index() {
14+
const [showInitial, setShowInitial] = useState(true);
15+
16+
return (
17+
<div className="Home">
18+
<div className="Home-header">
19+
<h1>🦥 react-lazy-svg</h1>
20+
<p>
21+
The icon is loaded on the {showInitial ? 'server' : 'client'}. Size
22+
and color is set via css.
23+
</p>
24+
{showInitial ? (
25+
<>
26+
<Icon url={icon1} className="icon"></Icon>
27+
<Icon url={icon1} className="icon red"></Icon>
28+
<Icon url={icon1} className="icon blue large"></Icon>
29+
</>
30+
) : (
31+
<>
32+
<Icon url={icon2} className="icon"></Icon>
33+
<Icon url={icon2} className="icon red"></Icon>
34+
<Icon url={icon2} className="icon blue large"></Icon>
35+
</>
36+
)}
37+
<button onClick={() => setShowInitial(!showInitial)}>
38+
toggle icon
39+
</button>
40+
</div>
41+
</div>
42+
);
43+
}

example-remix/app/serverLoadSvg.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { promisify } from 'util';
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
const svgIconFiles = new Map<string, string>();
6+
const readFile = promisify(fs.readFile);
7+
const baseUrl = '/build/_assets';
8+
9+
export const readSvg = async (url: string) => {
10+
if (svgIconFiles.has(url)) {
11+
return svgIconFiles.get(url);
12+
}
13+
14+
if (url.startsWith(baseUrl)) {
15+
const filePath = path.join(
16+
__dirname,
17+
'..',
18+
'public',
19+
'build',
20+
'_assets',
21+
url.substring(baseUrl.length),
22+
);
23+
const fileContents = await readFile(filePath, 'utf8');
24+
svgIconFiles.set(url, fileContents);
25+
return fileContents;
26+
}
27+
28+
return undefined;
29+
};

0 commit comments

Comments
 (0)