Skip to content

Commit 0b3b13a

Browse files
authored
Merge pull request #1686 from dvprrsh/master
add `with-fastify` example
2 parents f3d5266 + 4d39060 commit 0b3b13a

File tree

18 files changed

+333
-2
lines changed

18 files changed

+333
-2
lines changed

examples/with-fastify/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
logs
2+
*.log
3+
npm-debug.log*
4+
.DS_Store
5+
6+
coverage
7+
node_modules
8+
build
9+
public/static
10+
.env.local
11+
.env.development.local
12+
.env.test.local
13+
.env.production.local

examples/with-fastify/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Razzle Fastify Example
2+
3+
## How to use
4+
5+
<!-- START install generated instructions please keep comment here to allow auto update -->
6+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN yarn update-examples TO UPDATE -->Create and start the example:
7+
8+
```bash
9+
npx create-razzle-app --example with-fastify with-fastify
10+
11+
cd with-fastify
12+
yarn start
13+
```
14+
<!-- END install generated instructions please keep comment here to allow auto update -->
15+
16+
## Idea behind the example
17+
18+
This is an example of how to use Razzle with [Fastify](https://www.fastify.io/) and includes [TypeScript](https://github.com/Microsoft/TypeScript).
19+
20+
It is a very similar implementation to `with-koa` but with help from that example itself (found [here](https://github.com/jaredpalmer/razzle/blob/master/examples/with-koa/src/index.js)) and from the Fastify docs for serverless application [Serverless](https://www.fastify.io/docs/latest/Serverless/#should-you-use-fastify-in-a-serverless-platform#Vercel).
21+
22+
### TypeScript
23+
24+
Basic razzle will uses Babel to transform TypeScript to plain JavaScript ( with babel-loader ), and uses TypeScript for type-checking.
25+
26+
Razzle knows how to resolve `.ts` and `.tsx` files out of the box.

examples/with-fastify/package.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "razzle-examples-with-fastify",
3+
"version": "4.0.6",
4+
"license": "MIT",
5+
"scripts": {
6+
"start": "razzle start",
7+
"build": "razzle build",
8+
"test": "razzle test --env=jsdom",
9+
"start:prod": "NODE_ENV=production node build/server.js"
10+
},
11+
"dependencies": {
12+
"fastify": "^3.20.2",
13+
"fastify-static": "^4.2.3",
14+
"react": "^17.0.1",
15+
"react-dom": "^17.0.1",
16+
"react-router-dom": "^5.1.2"
17+
},
18+
"devDependencies": {
19+
"@testing-library/dom": "^7.29.4",
20+
"@testing-library/jest-dom": "^5.5.0",
21+
"@testing-library/react": "^10.0.3",
22+
"@testing-library/user-event": "^10.1.0",
23+
"@types/express": "^4.17.6",
24+
"@types/jest": "^25.2.1",
25+
"@types/node": "^13.13.2",
26+
"@types/react": "^16.9.34",
27+
"@types/react-dom": "^16.9.6",
28+
"@types/react-router-dom": "^5.1.4",
29+
"@types/webpack-env": "^1.15.2",
30+
"babel-preset-razzle": "4.0.6",
31+
"cross-env": "^7.0.3",
32+
"express": "^4.17.1",
33+
"html-webpack-plugin": "^4.5.2",
34+
"mini-css-extract-plugin": "^0.9.0",
35+
"razzle": "4.0.6",
36+
"razzle-dev-utils": "4.0.6",
37+
"typescript": "^4.0.3",
38+
"webpack": "^4.44.1",
39+
"webpack-dev-server": "^3.11.2"
40+
}
41+
}
32.2 KB
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
User-agent: *
2+

examples/with-fastify/src/App.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
body {
2+
margin: 0;
3+
padding: 0;
4+
font-family: sans-serif;
5+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { render } from '@testing-library/react';
2+
import React from 'react';
3+
import { MemoryRouter } from 'react-router-dom';
4+
import App from './App';
5+
6+
test('renders learn react link', () => {
7+
const { getByText } = render(
8+
<MemoryRouter>
9+
<App />
10+
</MemoryRouter>
11+
);
12+
const linkElement = getByText(/welcome to razzles/i);
13+
expect(linkElement).toBeInTheDocument();
14+
});

examples/with-fastify/src/App.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react';
2+
import { Route, Switch } from 'react-router-dom';
3+
import './App.css';
4+
import Home from './Home';
5+
6+
7+
const App = () => (
8+
<Switch>
9+
<Route exact={true} path="/" component={Home} />
10+
</Switch>
11+
);
12+
13+
export default App;

examples/with-fastify/src/Home.css

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.Home {
2+
text-align: center;
3+
}
4+
5+
.Home-logo {
6+
animation: Home-logo-spin infinite 20s linear;
7+
height: 80px;
8+
}
9+
10+
.Home-header {
11+
background-color: #222;
12+
height: 150px;
13+
padding: 20px;
14+
color: white;
15+
}
16+
17+
.Home-intro {
18+
font-size: large;
19+
}
20+
21+
.Home-resources {
22+
list-style: none;
23+
}
24+
25+
.Home-resources > li {
26+
display: inline-block;
27+
padding: 1rem;
28+
}
29+
30+
@keyframes Home-logo-spin {
31+
from {
32+
transform: rotate(0deg);
33+
}
34+
to {
35+
transform: rotate(360deg);
36+
}
37+
}

examples/with-fastify/src/Home.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react';
2+
import './Home.css';
3+
import logo from './react.svg';
4+
5+
6+
class Home extends React.Component<{}, {}> {
7+
public render() {
8+
return (
9+
<div className="Home">
10+
<div className="Home-header">
11+
<img src={logo} className="Home-logo" alt="logo" />
12+
<h2>Welcome to Razzle</h2>
13+
</div>
14+
<p className="Home-intro">
15+
To get started, edit <code>src/App.tsx</code> or{' '}
16+
<code>src/Home.tsx</code> and save to reload.
17+
</p>
18+
<ul className="Home-resources">
19+
<li>
20+
<a href="https://github.com/jaredpalmer/razzle">Docs</a>
21+
</li>
22+
<li>
23+
<a href="https://github.com/jaredpalmer/razzle/issues">Issues</a>
24+
</li>
25+
<li>
26+
<a href="https://palmer.chat">Community Slack</a>
27+
</li>
28+
</ul>
29+
</div>
30+
);
31+
}
32+
}
33+
34+
export default Home;

examples/with-fastify/src/client.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import { hydrate } from 'react-dom';
3+
import { BrowserRouter } from 'react-router-dom';
4+
import App from './App';
5+
6+
7+
hydrate(
8+
<BrowserRouter>
9+
<App />
10+
</BrowserRouter>,
11+
document.getElementById('root')
12+
);
13+
14+
if (module.hot) {
15+
module.hot.accept();
16+
}

examples/with-fastify/src/index.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import http from 'http';
2+
3+
/**
4+
* This implementation is similar to the `with-koa` example,
5+
* but Fastify does not have a `app#callback()` method.
6+
* Thus, this import implements a similar implementation.
7+
* See `./server.tsx` for more information.
8+
*/
9+
let currentHandler: http.RequestListener = require('./server').default;
10+
11+
const server = http.createServer(currentHandler);
12+
13+
const port = process.env.PORT || 3000;
14+
15+
server.listen(port, () => {
16+
console.log(`🚀 Server Started on Port ${port}`);
17+
});
18+
19+
if (module.hot) {
20+
module.hot.accept('./server', async function() {
21+
console.log('🔁 HMR Reloading `./server`...');
22+
try {
23+
const newHandler: http.RequestListener = require('./server').default;
24+
server.removeListener('request', currentHandler);
25+
server.on('request', newHandler);
26+
currentHandler = newHandler;
27+
} catch (error) {
28+
console.error('ERROR', error);
29+
}
30+
console.log('🚀 Server-side HMR Complete');
31+
});
32+
console.info('✅ Server-side HMR Enabled!');
33+
}

examples/with-fastify/src/react.svg

Lines changed: 1 addition & 0 deletions
Loading

examples/with-fastify/src/server.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import fastify from "fastify";
2+
import fastifyStatic from "fastify-static";
3+
import type { IncomingMessage, ServerResponse } from "http";
4+
import React from "react";
5+
import { renderToString } from "react-dom/server";
6+
import { StaticRouter } from "react-router-dom";
7+
import App from "./App";
8+
9+
let assetsImport: Record<string, any>;
10+
import(process.env.RAZZLE_ASSETS_MANIFEST!).then((res) => {
11+
assetsImport = res.default;
12+
});
13+
14+
const cssLinksFromAssets = (assets: Record<string, any>, entryPoint: string) =>
15+
(assets && assets[entryPoint]?.css?.map((asset: string) => `<link rel="stylesheet" href="${asset}">`).join("")) || "";
16+
17+
const jsScriptTagsFromAssets = (assets: Record<string, any>, entryPoint: string, extra = "") =>
18+
(assets && assets[entryPoint]?.js.map((asset: string) => `<script src="${asset}"${extra}></script>`).join("")) || "";
19+
20+
const app = fastify()
21+
.register(fastifyStatic, { root: process.env.RAZZLE_PUBLIC_DIR!, prefix: "/public" })
22+
.get("/*", async (req, res) => {
23+
const context: { url?: string } = {};
24+
const markup = renderToString(
25+
<StaticRouter context={context} location={req.url}>
26+
<App />
27+
</StaticRouter>,
28+
);
29+
30+
if (context.url) {
31+
return res.redirect(context.url);
32+
}
33+
res
34+
.status(200)
35+
.type("text/html")
36+
.send(
37+
`
38+
<!doctype html>
39+
<html lang="en-GB">
40+
<head>
41+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
42+
<meta charset="utf-8" />
43+
<title>Welcome to Razzle</title>
44+
<meta name="viewport" content="width=device-width, initial-scale=1">
45+
${cssLinksFromAssets(assetsImport, "client")}
46+
</head>
47+
<body>
48+
<div id="root">${markup}</div>
49+
${jsScriptTagsFromAssets(assetsImport, "client", " defer crossorigin")}
50+
</body>
51+
</html>
52+
`,
53+
);
54+
});
55+
56+
/**
57+
* This is a similar implementation to the one found in the Fastify docs,
58+
* which can be found [here]{@link https://www.fastify.io/docs/latest/Serverless/#should-you-use-fastify-in-a-serverless-platform#Vercel}.
59+
* The `app#ready()` is to indicate that all plugins have been loaded and the server is ready,
60+
* then the `app#server#emit()` method is called to handle the incoming request and Fastify handles it from there.
61+
*/
62+
export default async (req: IncomingMessage, res: ServerResponse): Promise<void> => {
63+
await app.ready();
64+
app.server.emit("request", req, res);
65+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// jest-dom adds custom jest matchers for asserting on DOM nodes.
2+
// allows you to do things like:
3+
// expect(element).toHaveTextContent(/react/i)
4+
// learn more: https://github.com/testing-library/jest-dom
5+
import '@testing-library/jest-dom/extend-expect';

examples/with-fastify/tsconfig.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"compilerOptions": {
3+
"target": "esnext",
4+
"module": "commonjs",
5+
"lib": ["dom", "dom.iterable", "esnext"],
6+
"allowJs": true,
7+
"skipLibCheck": true,
8+
"esModuleInterop": true,
9+
"allowSyntheticDefaultImports": true,
10+
"strict": false,
11+
"forceConsistentCasingInFileNames": true,
12+
"moduleResolution": "node",
13+
"resolveJsonModule": true,
14+
"isolatedModules": true,
15+
"noEmit": true,
16+
"jsx": "react",
17+
"typeRoots": ["node_modules/@types", "typings"]
18+
},
19+
"include": ["src", "typings/*"]
20+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules
2+
3+
declare module '*.svg' {
4+
const src: string;
5+
export default src;
6+
}

examples/with-koa/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
"koa-helmet": "^6.1.0",
1414
"koa-router": "^10.0.0",
1515
"koa-static": "^5.0.0",
16-
"react": "^17.0.2",
17-
"react-dom": "^17.0.2",
16+
"react": "^17.0.1",
17+
"react-dom": "^17.0.1",
1818
"react-router-dom": "^5.2.0"
1919
},
2020
"devDependencies": {

0 commit comments

Comments
 (0)