Skip to content

Commit

Permalink
Added code splitting (lazy and Suspense), server-side rendering with …
Browse files Browse the repository at this point in the history
…pipeable streams serving the non-interactive part of the code first and express added to the project to serve the stream
  • Loading branch information
rosen777 committed Jan 3, 2023
1 parent eccc4d7 commit acf8dff
Show file tree
Hide file tree
Showing 31 changed files with 8,380 additions and 82 deletions.
1,026 changes: 986 additions & 40 deletions 14-context/package-lock.json

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions 14-context/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
"version": "8.0.0",
"description": "Complete Intro to React v8 project",
"main": "index.js",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"build:client": "vite build --outDir ../dist/client",
"build:server": "vite build --outDir ../dist/server --ssr ServerApp.jsx",
"build": "npm run build:client && npm run build:server",
"preview": "vite preview",
"format": "prettier --write \"src/**/*.{js,jsx}\"",
"lint": "eslint \"src/**/*.{js,jsx}\" --quiet"
"lint": "eslint \"src/**/*.{js,jsx}\" --quiet",
"start": "node server.js"
},
"keywords": [],
"author": "Brian Holt",
Expand All @@ -26,6 +30,7 @@
},
"dependencies": {
"@tanstack/react-query": "4.10.1",
"express": "^4.18.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-router-dom": "6.4.1"
Expand Down
49 changes: 49 additions & 0 deletions 14-context/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import express from "express";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import renderApp from "./dist/server/ServerApp.js";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const PORT = process.env.PORT || 3001;

const html = fs
.readFileSync(path.resolve(__dirname, "./dist/client/index.html"))
.toString();

const parts = html.split("not rendered");

const app = express();
app.use(
"/assets",
express.static(path.resolve(__dirname, "./dist/client/assets"))
);

app.use((req, res) => {
res.write(parts[0]);

const stream = renderApp(req.url, {
onShellReady() {
// if it is crawler, do nothing here
stream.pipe(res);
},
onShellError() {
// do error handling
},
onAllReady() {
// if it is crawler,
// stream.pipe(res)

// last thing to write
res.write(parts[1]);
res.end();
},
onError(err) {
console.error(err);
},
});
});

console.log(`listening on http://localhost:${PORT}`);
app.listen(PORT);
45 changes: 28 additions & 17 deletions 14-context/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { createRoot } from "react-dom/client";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import { Routes, Route, Link } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useState } from "react";
import { useState, lazy, Suspense } from "react";
import AdoptedPetContext from "./AdoptedPetContext";
import Details from "./Details";
import SearchParams from "./SearchParams";

const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -15,27 +12,41 @@ const queryClient = new QueryClient({
},
});

const Details = lazy(() => import("./Details"));
const SearchParams = lazy(() => import("./SearchParams"));

const App = () => {
const adoptedPet = useState(null);
return (
<div>
<BrowserRouter>
<AdoptedPetContext.Provider value={adoptedPet}>
<QueryClientProvider client={queryClient}>
<header>
<Link to="/">Adopt Me!</Link>
<div
className="m-1 p-0"
style={{
background: "url(https://pets-images.dev-apis.com/pets/wallpaperA.jpg)",
}}
>
<AdoptedPetContext.Provider value={adoptedPet}>
<QueryClientProvider client={queryClient}>
<Suspense
fallback={
<div className="loading-pane">
<h2 className="loader">🌀</h2>
</div>
}
>
<header className="mb-10 w-full bg-gradient-to-b from-yellow-400 via-orange-500 to-red-500 p-7 text-center">
<Link className="text-6xl text-white hover:text-gray-200" to="/">
Adopt Me!
</Link>
</header>
<Routes>
<Route path="/details/:id" element={<Details />} />
<Route path="/" element={<SearchParams />} />
</Routes>
</QueryClientProvider>
</AdoptedPetContext.Provider>
</BrowserRouter>
</Suspense>
</QueryClientProvider>
</AdoptedPetContext.Provider>
</div>
);
};

const container = document.getElementById("root");
const root = createRoot(container);
root.render(<App />);
export default App;
10 changes: 10 additions & 0 deletions 14-context/src/ClientApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { hydrateRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";

hydrateRoot(
document.getElementById("root"),
<BrowserRouter>
<App />
</BrowserRouter>
);
5 changes: 3 additions & 2 deletions 14-context/src/Details.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useNavigate, useParams } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { useContext, useState } from "react";
import { useContext, useState, lazy } from "react";
import AdoptedPetContext from "./AdoptedPetContext";
import Modal from "./Modal";
import ErrorBoundary from "./ErrorBoundary";
import fetchPet from "./fetchPet";
import Carousel from "./Carousel";

const Modal = lazy(() => import("./Modal"));

const Details = () => {
const { id } = useParams();
const [showModal, setShowModal] = useState(false);
Expand Down
14 changes: 14 additions & 0 deletions 14-context/src/ServerApp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { renderToPipeableStream } from "react-dom/server";
import { StaticRouter } from "react-router-dom/server";
import App from "./App";

export default function render(url, opts) {
const stream = renderToPipeableStream(
<StaticRouter location={url}>
<App />
</StaticRouter>,
opts
);

return stream;
}
2 changes: 1 addition & 1 deletion 14-context/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
<body>
<div id="modal"></div>
<div id="root">not rendered</div>
<script type="module" src="./App.jsx"></script>
<script type="module" src="./ClientApp.jsx"></script>
</body>
</html>
18 changes: 1 addition & 17 deletions code-splitting/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions code-splitting/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ const SearchParams = lazy(() => import("./SearchParams"));
const App = () => {
const adoptedPet = useState(null);
return (
<div>
<div
className="m-1 p-0"
style={{
background: "url(https://pets-images.dev-apis.com/pets/wallpaperA.jpg)",
}}
>
<BrowserRouter>
<AdoptedPetContext.Provider value={adoptedPet}>
<QueryClientProvider client={queryClient}>
Expand All @@ -30,8 +35,13 @@ const App = () => {
</div>
}
>
<header>
<Link to="/">Adopt Me!</Link>
<header className="mb-10 w-full bg-gradient-to-b from-yellow-400 via-orange-500 to-red-500 p-7 text-center">
<Link
className="text-6xl text-white hover:text-gray-200"
to="/"
>
Adopt Me!
</Link>
</header>
<Routes>
<Route path="/details/:id" element={<Details />} />
Expand Down
37 changes: 37 additions & 0 deletions frontend-masters/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"extends": [
"eslint:recommended",
"plugin:import/errors",
"plugin:react/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended",
"prettier"
],
"rules": {
"react/prop-types": 0,
"react/react-in-jsx-scope": 0
},
"plugins": ["react", "import", "jsx-a11y"],
"parserOptions": {
"ecmaVersion": 2022,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"env": {
"es6": true,
"browser": true,
"node": true
},
"settings": {
"react": {
"version": "detect"
},
"import/resolver": {
"node": {
"extensions": [".js", ".jsx"]
}
}
}
}
7 changes: 7 additions & 0 deletions frontend-masters/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
.parcel-cache/
dist/
.env
.DS_Store
coverage/
.vscode/
1 change: 1 addition & 0 deletions frontend-masters/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Loading

0 comments on commit acf8dff

Please sign in to comment.