-
-
Notifications
You must be signed in to change notification settings - Fork 19
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
feat: new extension vike-react-styled-jsx
#158
Changes from 15 commits
5dd4832
6f2a2d8
b4deda1
841e6cb
caa08d1
d5390de
008773b
2041820
c2ff3a4
c06d341
77aa376
57b06b5
146f90c
becd4f0
e619490
a3bab0c
a3cde20
d6e15b5
65e9166
788aa43
6809734
239b596
1ffa1e0
279ede8
4c4760e
5ec476d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/node_modules/ | ||
/dist/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# `vike-react-styled-jsx` | ||
|
||
[Installation](#installation) | ||
[Settings](#settings) | ||
[Version history](https://github.com/vikejs/vike-react/blob/main/packages/vike-react-styled-jsx/CHANGELOG.md) | ||
[What it does](#what-it-does) | ||
[See also](#see-also) | ||
|
||
<br/> | ||
|
||
Integrates [styled-jsx](https://github.com/vercel/styled-jsx) to your [`vike-react`](https://vike.dev/vike-react) app. | ||
|
||
## Installation | ||
|
||
1. `npm install vike-react-styled-jsx styled-jsx` | ||
2. Extend `+config.js`: | ||
```js | ||
// pages/+config.js | ||
|
||
import vikeReact from "vike-react/config" | ||
import vikeReactStyledJsx from "vike-react-styled-jsx/config" | ||
|
||
export default { | ||
// ... | ||
extends: [vikeReact, vikeReactStyledJsx] | ||
} | ||
``` | ||
|
||
3. Add `styled-jsx`'s Babel plugin: | ||
```js | ||
// vite.config.js | ||
import react from "@vitejs/plugin-react" | ||
import vike from "vike/plugin" | ||
|
||
export default { | ||
plugins: [ | ||
vike(), | ||
react({ | ||
babel: { | ||
plugins: [["styled-jsx/babel"]] | ||
} | ||
}) | ||
] | ||
} | ||
``` | ||
|
||
4. You can now use styled-jsx at any of your components. | ||
brillout marked this conversation as resolved.
Show resolved
Hide resolved
|
||
```jsx | ||
function SomeComponent() { | ||
return ( | ||
<div> | ||
<p>Only this paragraph will get the style.</p> | ||
|
||
<style jsx>{` | ||
p { | ||
color: red; | ||
} | ||
`}</style> | ||
</div> | ||
) | ||
} | ||
``` | ||
|
||
> [!NOTE] | ||
> The `vike-react-styled-jsx` extension requires [`vike-react`](https://vike.dev/vike-react). | ||
|
||
<br/> | ||
|
||
## Settings | ||
|
||
`vike-react-styled-jsx` provides a configuration `+styledJsx` to set the [CSP nonce for `styled-jsx`](https://github.com/vercel/styled-jsx#content-security-policy). | ||
|
||
> [!NOTE] | ||
> You also need to set a `<meta property="csp-nonce" content={nonce} />` tag with the same nonce. | ||
> See [Vike Docs > head-tags](https://vike.dev/head-tags). | ||
|
||
```ts | ||
// pages/+styledJsx.js | ||
export { styledJsx } | ||
|
||
import nanoid from 'nanoid' | ||
|
||
const styledJsx = { | ||
nonce: Buffer.from(nanoid()).toString('base64') //ex: N2M0MDhkN2EtMmRkYi00MTExLWFhM2YtNDhkNTc4NGJhMjA3 | ||
} | ||
``` | ||
|
||
You can remove the `vike-react-styled-jsx` integration from [some of your pages](https://vike.dev/config#inheritance): | ||
|
||
```js | ||
// pages/about/+styledJsx.js | ||
|
||
export const styledJsx = null | ||
``` | ||
|
||
brillout marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<br/> | ||
brillout marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
For full customization consider [ejecting](https://vike.dev/eject). | ||
phonzammi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
> [!NOTE] | ||
> Consider making a [Pull Request before ejecting](https://vike.dev/eject#when-to-eject). | ||
|
||
brillout marked this conversation as resolved.
Show resolved
Hide resolved
|
||
## What it does | ||
|
||
The `vike-react-styled-jsx` extension automatically integrates `styled-jsx`'s SSR features under the hood to avoid FOUC. It does this by collecting the page's styles during SSR and injecting them earlier, ensuring that the styles are applied before hydration begins. Learn more in the [styled-jsx README > Server Side Rendering](https://github.com/vercel/styled-jsx#server-side-rendering). | ||
phonzammi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
To learn more about how the integration works, have a look at the source code which is small. For full control [consider ejecting](https://vike.dev/eject). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's avoid the "learn more" repetition. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For more details...
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay d6e15b5 |
||
|
||
<br/> | ||
|
||
## See also | ||
|
||
- [Vike Docs > styled-jsx](https://vike.dev/styled-jsx) | ||
- [Vike Docs > CSS-in-JS](https://vike.dev/css-in-js) | ||
- [styled-jsx README](https://github.com/vercel/styled-jsx#readme) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export { Wrapper } | ||
|
||
import React, { type ReactNode } from 'react' | ||
import { StyleRegistry } from 'styled-jsx' | ||
import { usePageContext } from 'vike-react/usePageContext' | ||
|
||
function Wrapper({ children }: { children: ReactNode }) { | ||
const pageContext = usePageContext() | ||
|
||
if (pageContext.config.styledJsx === null) return <>{children}</> | ||
|
||
if ('styledJsx' in pageContext) { | ||
return <StyleRegistry registry={pageContext.styledJsx!.registry}>{children}</StyleRegistry> | ||
} | ||
return <>{children}</> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
export { config as default } | ||
|
||
import type { Config } from 'vike/types' | ||
import type { StyledJsxStyleRegistry } from 'styled-jsx' | ||
|
||
const config = { | ||
name: 'vike-react-styled-jsx', | ||
require: { | ||
vike: '>=0.4.203', | ||
'vike-react': '>=0.4.13', | ||
}, | ||
onBeforeRenderHtml: 'import:vike-react-styled-jsx/__internal/onBeforeRenderHtml:onBeforeRenderHtml', | ||
onAfterRenderHtml: 'import:vike-react-styled-jsx/__internal/onAfterRenderHtml:onAfterRenderHtml', | ||
Wrapper: 'import:vike-react-styled-jsx/__internal/Wrapper:Wrapper', | ||
meta: { | ||
styledJsx: { | ||
env: { server: true }, | ||
}, | ||
Wrapper: { | ||
env: { server: true }, | ||
}, | ||
}, | ||
} satisfies Config | ||
|
||
declare global { | ||
namespace Vike { | ||
interface PageContext { | ||
styledJsx?: { | ||
registry?: StyledJsxStyleRegistry | ||
} | ||
} | ||
interface Config { | ||
styledJsx?: null | { | ||
nonce?: string | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export { onAfterRenderHtml } | ||
phonzammi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import { useConfig } from 'vike-react/useConfig' | ||
import type { PageContext } from 'vike/types' | ||
|
||
function onAfterRenderHtml(pageContext: PageContext) { | ||
const config = useConfig() | ||
const registry = pageContext.styledJsx?.registry | ||
|
||
if (registry) { | ||
const nonce = pageContext.config.styledJsx?.nonce | ||
const styles = registry.styles({ nonce }) | ||
|
||
config({ | ||
Head: styles, | ||
}) | ||
|
||
registry.flush() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export { onBeforeRenderHtml } | ||
|
||
import { createStyleRegistry } from 'styled-jsx' | ||
import type { PageContext } from 'vike/types' | ||
|
||
function onBeforeRenderHtml(pageContext: PageContext) { | ||
if (pageContext.config.styledJsx !== null) { | ||
pageContext.styledJsx ??= {} | ||
pageContext.styledJsx.registry = createStyleRegistry() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
{ | ||
"name": "vike-react-styled-jsx", | ||
"version": "0.0.0", | ||
"type": "module", | ||
"exports": { | ||
"./config": "./dist/config.js", | ||
"./__internal/onAfterRenderHtml": "./dist/onAfterRenderHtml.js", | ||
"./__internal/onBeforeRenderHtml": "./dist/onBeforeRenderHtml.js", | ||
"./__internal/Wrapper": "./dist/Wrapper.js" | ||
}, | ||
"scripts": { | ||
"dev": "tsc --watch", | ||
"build": "rimraf dist/ && tsc", | ||
"release": "release-me patch", | ||
"release:minor": "release-me minor", | ||
"release:major": "release-me major", | ||
"release:commit": "release-me commit" | ||
}, | ||
"peerDependencies": { | ||
"styled-jsx": ">=5", | ||
"react": ">=18", | ||
"vike-react": ">=0.4.13" | ||
}, | ||
"devDependencies": { | ||
"@brillout/release-me": "^0.4.2", | ||
"@types/react": "^18.2.55", | ||
"react": "^18.3.1", | ||
"rimraf": "^5.0.5", | ||
"styled-jsx": "^5.1.6", | ||
"typescript": "^5.5.3", | ||
"vike": "^0.4.203", | ||
"vike-react": "^0.5.10", | ||
"vite": "^5.4.0" | ||
}, | ||
"typesVersions": { | ||
"*": { | ||
"config": [ | ||
"dist/config.d.ts" | ||
], | ||
"__internal/onAfterRenderHtml": [ | ||
"dist/onAfterRenderHtml.d.ts" | ||
], | ||
"__internal/onBeforeRenderHtml": [ | ||
"dist/onBeforeRenderHtml.d.ts" | ||
], | ||
"__internal/Wrapper": [ | ||
"dist/Wrapper.d.ts" | ||
] | ||
} | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"repository": "https://github.com/vikejs/vike-react/tree/main/packages/vike-react-styled-jsx", | ||
"license": "MIT" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"compilerOptions": { | ||
"declaration": true, | ||
"target": "ESNext", | ||
"module": "ESNext", | ||
"moduleResolution": "Bundler", | ||
"jsx": "react", | ||
"outDir": "./dist/", | ||
"skipLibCheck": true, | ||
"types": ["vike-react"], | ||
// Strictness | ||
"strict": true, | ||
"noUncheckedIndexedAccess": true, | ||
"noImplicitAny": true | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be before the TOC. Intervention++