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

Ssr optimization #21

Merged
merged 11 commits into from
Nov 30, 2023
Merged
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
62 changes: 54 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This project is inspired by `next-themes`. `next-themes` is an awesome package,
- ✅ Force pages to specific themes
- ✅ Class or data attribute selector
- ✅ Manipulate theme via `useTheme` hook
- ✅ Doccumented with [Typedoc](https://react18-tools.github.io/react18-themes) ([Docs](https://react18-tools.github.io/react18-themes))

Check out the [live example](https://react18-themes.vercel.app/).

Expand All @@ -47,9 +48,9 @@ $ yarn add react18-themes-lite

> You need Zustand as a peer-dependency

## Use
## Usage

### With pages/
### SPA (e.g., Vite, CRA) and Next.js pages directory (No server components)

The best way is to add a [Custom `App`](https://nextjs.org/docs/advanced-features/custom-app) to use by modifying `_app` as follows:

Expand All @@ -74,7 +75,33 @@ export default MyApp;

Check out examples for advanced usage.

### With app/
### With Next.js `app` router (Server Components)

Update your `app/layout.jsx` to add `ThemeSwitcher` from `react18-themes`, and `NextJsSSRThemeSwitcher` from `react18-themes/server`. `NextJsSSRThemeSwitcher` is required to avoid flash of un-themed content on reload.

```tsx
// app/layout.jsx
import { ThemeSwitcher } from "react18-themes";
import { NextJsSSRThemeSwitcher } from "react18-themes/server/nextjs";

export default function Layout({ children }) {
return (
<html lang="en">
<head />
<body>
/** use NextJsSSRThemeSwitcher as first element inside body */
<NextJsSSRThemeSwitcher />
<ThemeSwitcher />
{children}
</body>
</html>
);
}
```

Woohoo! You just added multiple theme modes and you can also use Server Component! Isn't that awesome!

#### Version 1 (Legacy)

Update your `app/layout.jsx` to add `ThemeSwitcher` and `ServerSideWrapper` from `react18-themes`. `ServerSideWrapper` is required to avoid flash of un-themed content on reload.

Expand Down Expand Up @@ -113,6 +140,12 @@ That's it, your Next.js app fully supports dark mode, including System preferenc
--background: black;
--foreground: white;
}

// v2 onwards when using React18 server components, we need to use CSS Combinators
[data-theme="dark"] ~ * {
--background: black;
--foreground: white;
}
```

### useTheme
Expand Down Expand Up @@ -175,12 +208,25 @@ In a similar way, you can also force color scheme.

Forcing color scheme will apply your defaultDark or defaultLight theme, configurable via hooks.

## Migrating from v1 to v2

#### Motivation:

For server side syncing, we need to use cookies and headers. This means that this component and its children can not be static. They will be rendered server side for each request. Thus, we are avoiding the wrapper. Now, only the `NextJsSSRThemeSwitcher` will be rendered server side for each request and rest of your app can be server statically.

Take care of the following while migrating to `v2`.

- No changes required for projects not using `Next.js` app router or server components.
- The persistent storage is realized with `cookies` in place of `localStorage`. (You might want to update cookies policy accordingly.)
- `ServerSideWrapper` for `Next.js` is rebranded to `NextJsSSRThemeSwitcher`. No longer need to use this as a wrapper.
- Visit [With Next.js `app` router (Server Components)](<#with-next.js-app-router-(server-components)>)

## Migrating from v0 to v1

- defaultDarkTheme is renamed to darkTheme
- setDefaultDarkTheme is renamed to setDarkTheme
- defaultLightTheme is renamed to lightTheme
- setDefaultLightTheme is renamed to setLightTheme
- `defaultDarkTheme` is renamed to `darkTheme`
- `setDefaultDarkTheme` is renamed to `setDarkTheme`
- `defaultLightTheme` is renamed to `lightTheme`
- `setDefaultLightTheme` is renamed to `setLightTheme`

## Docs

Expand All @@ -190,7 +236,7 @@ Forcing color scheme will apply your defaultDark or defaultLight theme, configur

Want handson course for getting started with Turborepo? Check out [React and Next.js with TypeScript](https://www.udemy.com/course/react-and-next-js-with-typescript/?referralCode=7202184A1E57C3DCA8B2)

![Alt](https://repobeats.axiom.co/api/embed/212c15d25de3d653995014d1e5d27df1b7e20d13.svg "Repobeats analytics image")
![Alt](https://repobeats.axiom.co/api/embed/846d01d5bb0cc683bffe0a25e289334b49acebd1.svg "Repobeats analytics image")

## License

Expand Down
8 changes: 8 additions & 0 deletions examples/nextjs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# nextjs-example

## 0.0.9

### Patch Changes

- Updated dependencies [f3704f9]
- react18-themes@2.0.0
- shared-ui@1.0.1

## 0.0.8

### Patch Changes
Expand Down
7 changes: 4 additions & 3 deletions examples/nextjs/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ForcedPage } from "react18-themes/server";
import { ServerSideWrapper } from "react18-themes/server";
import { NextJsSSRThemeSwitcher } from "react18-themes/server";
import { Inter } from "next/font/google";
import { SharedRootLayout, darkThemes, lightThemes } from "shared-ui";
import Link from "next/link";
Expand All @@ -13,12 +13,13 @@ const forcedPages: ForcedPage[] = [

export default function RootLayout({ children }: { children: React.ReactNode }): JSX.Element {
return (
<ServerSideWrapper forcedPages={forcedPages} lang="en">
<html lang="en">
<body>
<NextJsSSRThemeSwitcher forcedPages={forcedPages} />
<SharedRootLayout LinkElement={Link} className={inter.className}>
{children}
</SharedRootLayout>
</body>
</ServerSideWrapper>
</html>
);
}
8 changes: 4 additions & 4 deletions examples/nextjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nextjs-example",
"version": "0.0.8",
"version": "0.0.9",
"private": true,
"scripts": {
"dev": "next dev --port 3002",
Expand All @@ -9,7 +9,7 @@
"lint": "next lint"
},
"dependencies": {
"@mayank1513/fork-me": "^1.1.2",
"@mayank1513/fork-me": "^2.0.0",
"next": "^14.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand All @@ -18,8 +18,8 @@
},
"devDependencies": {
"@next/eslint-plugin-next": "^14.0.3",
"@types/node": "^20.9.4",
"@types/react": "^18.2.38",
"@types/node": "^20.10.0",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.17",
"eslint-config-custom": "workspace:*",
"tsconfig": "workspace:*",
Expand Down
8 changes: 8 additions & 0 deletions examples/remix/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

### Patch Changes

- Updated dependencies [f3704f9]
- react18-themes@2.0.0
- shared-ui@1.0.1

## null

### Patch Changes

- Updated dependencies
- react18-themes@1.1.3
- shared-ui@1.0.1
Expand Down
8 changes: 4 additions & 4 deletions examples/remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@
"typecheck": "tsc"
},
"dependencies": {
"@mayank1513/fork-me": "^1.1.2",
"@mayank1513/fork-me": "^2.0.0",
"@remix-run/css-bundle": "^2.3.1",
"@remix-run/node": "^2.3.1",
"@remix-run/react": "^2.3.1",
"@remix-run/serve": "^2.3.1",
"isbot": "^3.7.1",
"persist-and-sync": "^1.0.0",
"persist-and-sync": "^1.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react18-themes": "workspace:*",
"shared-ui": "workspace:*",
"zustand": "^4.4.6"
"zustand": "^4.4.7"
},
"devDependencies": {
"@remix-run/dev": "^2.3.1",
"@remix-run/eslint-config": "^2.3.1",
"@types/react": "^18.2.38",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.17",
"eslint": "^8.54.0",
"typescript": "^5.3.2"
Expand Down
8 changes: 8 additions & 0 deletions examples/vite/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# vite-example

## 0.0.9

### Patch Changes

- Updated dependencies [f3704f9]
- react18-themes@2.0.0
- shared-ui@1.0.1

## 0.0.8

### Patch Changes
Expand Down
12 changes: 6 additions & 6 deletions examples/vite/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vite-example",
"private": true,
"version": "0.0.8",
"version": "0.0.9",
"type": "module",
"scripts": {
"dev": "vite --port 3001",
Expand All @@ -10,23 +10,23 @@
"preview": "vite preview"
},
"dependencies": {
"@mayank1513/fork-me": "^1.1.2",
"@mayank1513/fork-me": "^2.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.20.0",
"react18-themes": "workspace:*",
"shared-ui": "workspace:*"
},
"devDependencies": {
"@types/react": "^18.2.38",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.17",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^8.54.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.4",
"typescript": "^5.3.2",
"vite": "^5.0.2"
"vite": "^5.0.3"
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,md,css,scss}\""
},
"devDependencies": {
"@changesets/cli": "^2.26.2",
"@changesets/cli": "^2.27.1",
"eslint": "^8.54.0",
"prettier": "^3.1.0",
"tsconfig": "workspace:*",
Expand Down
10 changes: 10 additions & 0 deletions packages/react18-themes/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# react18-themes

## 2.0.0

### Major Changes

- f3704f9: When headers or cookies used in server component, it is no longer static. It will be generated on server side for every request. Thus, wrapping antire layout in `<ServerSideWrapper>` had disadvantage of always causing re-renders on the server.

In this version, we have rebranded `ServerSideWrapper` as `NextJsSSRThemeSwitcher`. `NextJsSSRThemeSwitcher` need not wrap any components. Rather we use CSS Combinators to apply appropreate themes.

More in the docs...

## 1.1.3

### Patch Changes
Expand Down
22 changes: 11 additions & 11 deletions packages/react18-themes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "react18-themes",
"author": "Mayank Kumar Chaudhari <https://mayank-chaudhari.vercel.app>",
"private": false,
"version": "1.1.3",
"version": "2.0.0",
"description": "Unleash the Power of React Server Components! Use multiple themes on your site with confidence, without losing any advantages of React Server Components.",
"main": "./index.ts",
"types": "./index.ts",
Expand All @@ -26,25 +26,28 @@
"devDependencies": {
"@testing-library/react": "^14.1.2",
"@turbo/gen": "^1.10.16",
"@types/node": "^20.9.4",
"@types/react": "^18.2.38",
"@types/node": "^20.10.0",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.17",
"@vitejs/plugin-react": "^4.2.0",
"@vitest/coverage-v8": "^0.34.6",
"esbuild-plugin-react18": "^0.0.6",
"eslint-config-custom": "workspace:*",
"jsdom": "^22.1.0",
"jsdom": "^23.0.0",
"next": "^14.0.3",
"octokit": "^3.1.2",
"persist-and-sync": "^1.0.0",
"react": "^18.2.0",
"tsconfig": "workspace:*",
"tsup": "^8.0.1",
"typedoc": "^0.25.3",
"typedoc": "^0.25.4",
"typescript": "5.3.2",
"vite-tsconfig-paths": "^4.2.1",
"vitest": "^0.34.6",
"zustand": "^4.4.6"
"eslint": "^8.54.0"
},
"dependencies": {
"persist-and-sync": "^1.1.0",
"zustand": "^4.4.7"
},
"peerDependencies": {
"@types/react": "16.8 - 18",
Expand Down Expand Up @@ -81,8 +84,5 @@
"javascript",
"mayank1513",
"turborepo-trmplate"
],
"dependencies": {
"eslint": "^8.54.0"
}
]
}
Loading