generated from react-component/footer
-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 0.0.0-alpha.5 * refactor: use StyleProvider instead of StyleContext * docs: Create 2 ssr demo * docs: prepare default cssinjs * chore: rename api * feat: tricky ssr * test: tricky ssr
- Loading branch information
Showing
13 changed files
with
347 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## SSR Advanced | ||
|
||
进阶 SSR 可以将样式抽离至外部的 style 标签下: | ||
|
||
<code src="../examples/ssr-advanced.tsx"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## SSR Tricky | ||
|
||
我们强烈推荐使用 SSR Advanced 示例使用服务端渲染,如果渲染侧无法控制也可以通过降级方式自动处理: | ||
|
||
<code src="../examples/ssr-tricky.tsx"> |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import React from 'react'; | ||
import { hydrate } from 'react-dom'; | ||
import { renderToString } from 'react-dom/server'; | ||
import { StyleProvider, Cache, extractStyle } from '../../src'; | ||
import Button from './components/Button'; | ||
import Spin from './components/Spin'; | ||
import { DesignTokenContext } from './components/theme'; | ||
|
||
const Demo = () => { | ||
const sharedProps: React.HTMLAttributes<HTMLButtonElement> = { | ||
onClick: ({ target }) => { | ||
console.log('Click:', target); | ||
}, | ||
}; | ||
|
||
return ( | ||
<div style={{ display: 'flex', columnGap: 8 }}> | ||
<Button {...sharedProps} type="ghost"> | ||
Button | ||
</Button> | ||
<Spin /> | ||
|
||
<DesignTokenContext.Provider | ||
value={{ token: { primaryColor: 'red' }, hashed: true }} | ||
> | ||
<Button {...sharedProps} type="ghost"> | ||
Button | ||
</Button> | ||
<Spin /> | ||
</DesignTokenContext.Provider> | ||
<DesignTokenContext.Provider | ||
value={{ token: { primaryColor: 'green' }, hashed: 'v5' }} | ||
> | ||
<Button {...sharedProps} type="ghost"> | ||
Button | ||
</Button> | ||
<Spin /> | ||
</DesignTokenContext.Provider> | ||
</div> | ||
); | ||
}; | ||
|
||
const Pre: React.FC = ({ children }) => ( | ||
<pre | ||
style={{ | ||
background: '#FFF', | ||
padding: 8, | ||
whiteSpace: 'pre-wrap', | ||
wordBreak: 'break-word', | ||
}} | ||
> | ||
{children} | ||
</pre> | ||
); | ||
|
||
export default function App() { | ||
const cacheRef = React.useRef(new Cache()); | ||
|
||
const [ssrHTML, ssrStyle] = React.useMemo(() => { | ||
const html = renderToString( | ||
<StyleProvider | ||
// Tell cssinjs not insert dom style. No need in real world | ||
mock="server" | ||
cache={cacheRef.current} | ||
> | ||
<Demo /> | ||
</StyleProvider>, | ||
); | ||
|
||
const style = extractStyle(cacheRef.current); | ||
|
||
return [html, style]; | ||
}, []); | ||
|
||
// 模拟一个空白文档,并且注水 | ||
React.useEffect(() => { | ||
console.log('Delay to hydrate...'); | ||
setTimeout(() => { | ||
const styles = document.createElement('div'); | ||
styles.innerHTML = ssrStyle; | ||
|
||
Array.from(styles.childNodes).forEach((style) => { | ||
document.head.appendChild(style); | ||
}); | ||
|
||
const container = document.getElementById('ssr'); | ||
hydrate(<Demo />, container); | ||
}, 500); | ||
}, []); | ||
|
||
return ( | ||
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 16 }}> | ||
<h3>服务端渲染提前获取所有样式</h3> | ||
|
||
<Pre>{ssrStyle}</Pre> | ||
<Pre>{ssrHTML}</Pre> | ||
|
||
<div id="ssr" dangerouslySetInnerHTML={{ __html: ssrHTML }} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import React from 'react'; | ||
import { hydrate } from 'react-dom'; | ||
import { renderToString } from 'react-dom/server'; | ||
import { StyleProvider } from '../../src'; | ||
import Button from './components/Button'; | ||
import Spin from './components/Spin'; | ||
import { DesignTokenContext } from './components/theme'; | ||
|
||
const Demo = () => { | ||
const sharedProps: React.HTMLAttributes<HTMLButtonElement> = { | ||
onClick: ({ target }) => { | ||
console.log('Click:', target); | ||
}, | ||
}; | ||
|
||
return ( | ||
<div style={{ display: 'flex', columnGap: 8 }}> | ||
<Button {...sharedProps} type="ghost"> | ||
Button | ||
</Button> | ||
<Spin /> | ||
|
||
<DesignTokenContext.Provider | ||
value={{ token: { primaryColor: 'red' }, hashed: true }} | ||
> | ||
<Button {...sharedProps} type="ghost"> | ||
Button | ||
</Button> | ||
<Spin /> | ||
</DesignTokenContext.Provider> | ||
<DesignTokenContext.Provider | ||
value={{ token: { primaryColor: 'green' }, hashed: 'v5' }} | ||
> | ||
<Button {...sharedProps} type="ghost"> | ||
Button | ||
</Button> | ||
<Spin /> | ||
</DesignTokenContext.Provider> | ||
</div> | ||
); | ||
}; | ||
|
||
const Pre: React.FC = ({ children }) => ( | ||
<pre | ||
style={{ | ||
background: '#FFF', | ||
padding: 8, | ||
whiteSpace: 'pre-wrap', | ||
wordBreak: 'break-word', | ||
}} | ||
> | ||
{children} | ||
</pre> | ||
); | ||
|
||
export default function App() { | ||
const ssrHTML = React.useMemo( | ||
() => | ||
renderToString( | ||
<StyleProvider mock="server"> | ||
<Demo /> | ||
</StyleProvider>, | ||
), | ||
[], | ||
); | ||
|
||
// 模拟一个空白文档,并且注水 | ||
React.useEffect(() => { | ||
console.log('Delay to hydrate...'); | ||
setTimeout(() => { | ||
const container = document.getElementById('ssr'); | ||
hydrate(<Demo />, container); | ||
}, 500); | ||
}, []); | ||
|
||
return ( | ||
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 16 }}> | ||
<h3>服务端渲染提前获取所有样式</h3> | ||
|
||
<Pre>{ssrHTML}</Pre> | ||
|
||
<div id="ssr" dangerouslySetInnerHTML={{ __html: ssrHTML }} /> | ||
</div> | ||
); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,66 @@ | ||
import * as React from 'react'; | ||
import canUseDom from 'rc-util/lib/Dom/canUseDom'; | ||
import CacheEntity from './Cache'; | ||
import { getTokenStyles } from './useStyleRegister'; | ||
|
||
const StyleContext = React.createContext<{ | ||
export interface StyleContextProps { | ||
autoClear?: boolean; | ||
/** @private Test only. Not work in production. */ | ||
insertStyle?: boolean; | ||
mock?: 'server' | 'client'; | ||
/** | ||
* Only set when you need ssr to extract style on you own. | ||
* If not provided, it will auto create <style /> on the end of Provider in server side. | ||
*/ | ||
cache: CacheEntity; | ||
}>({ | ||
} | ||
|
||
const StyleContext = React.createContext<StyleContextProps>({ | ||
cache: new CacheEntity(), | ||
}); | ||
|
||
export type StyleProviderProps = Partial<StyleContextProps>; | ||
|
||
const InlineStyle = ({ cache }: { cache: CacheEntity }) => { | ||
const styles = getTokenStyles(cache); | ||
return ( | ||
<> | ||
{styles.map(({ token, style }, index) => ( | ||
<style | ||
data-token-key={token} | ||
key={index} | ||
dangerouslySetInnerHTML={{ __html: style }} | ||
/> | ||
))} | ||
</> | ||
); | ||
}; | ||
|
||
export const StyleProvider: React.FC<StyleProviderProps> = ({ | ||
autoClear, | ||
mock, | ||
cache, | ||
children, | ||
}) => { | ||
const context = React.useMemo<StyleContextProps>( | ||
() => ({ | ||
autoClear, | ||
mock, | ||
cache: cache || new CacheEntity(), | ||
}), | ||
[autoClear, mock, cache], | ||
); | ||
|
||
const shouldInsertSSRStyle = React.useMemo(() => { | ||
const isServerSide = mock !== undefined ? mock === 'server' : !canUseDom(); | ||
return isServerSide && !cache; | ||
}, [mock, cache]); | ||
|
||
return ( | ||
<StyleContext.Provider value={context}> | ||
{children} | ||
{shouldInsertSSRStyle && <InlineStyle cache={context.cache} />} | ||
</StyleContext.Provider> | ||
); | ||
}; | ||
|
||
export default StyleContext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.