-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: optimize live demo feature in v2.3 (#1992)
* refactor: clean up compile-time logic * feat: emit demo context in loader * refactor: clean up runtime api and slots * feat: add SourceCodeEditor slot * feat: add useLiveDemo api * refactor: rewrite live demo feature with useLiveDemo * feat: live demo support iframe mode * refactor: constants for browser runtime
- Loading branch information
1 parent
e14fa51
commit 206b04e
Showing
39 changed files
with
591 additions
and
593 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
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 |
---|---|---|
@@ -1,12 +1,31 @@ | ||
import { useDemo, useParams } from 'dumi'; | ||
import { createElement, type FC } from 'react'; | ||
import { useDemo, useLiveDemo, useParams } from 'dumi'; | ||
import { createElement, useEffect, type FC } from 'react'; | ||
import './index.less'; | ||
|
||
const DemoRenderPage: FC = () => { | ||
const { id } = useParams(); | ||
const { component } = useDemo(id!) || {}; | ||
const { node: liveDemoNode, setSources } = useLiveDemo(id!); | ||
const finalNode = liveDemoNode || (component && createElement(component)); | ||
|
||
return component && createElement(component); | ||
useEffect(() => { | ||
const handler = ( | ||
ev: MessageEvent<{ | ||
type: string; | ||
value: Parameters<typeof setSources>[0]; | ||
}>, | ||
) => { | ||
if (ev.data.type === 'dumi.liveDemo.setSources') { | ||
setSources(ev.data.value); | ||
} | ||
}; | ||
|
||
window.addEventListener('message', handler); | ||
|
||
return () => window.removeEventListener('message', handler); | ||
}, [setSources]); | ||
|
||
return finalNode; | ||
}; | ||
|
||
export default DemoRenderPage; |
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 was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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,65 @@ | ||
import { useDemo } from 'dumi'; | ||
import { | ||
createElement, | ||
useCallback, | ||
useState, | ||
type ComponentType, | ||
type ReactNode, | ||
} from 'react'; | ||
import DemoErrorBoundary from './DumiDemo/DemoErrorBoundary'; | ||
|
||
export const useLiveDemo = (id: string) => { | ||
const { context, asset } = useDemo(id)!; | ||
const [demoNode, setDemoNode] = useState<ReactNode>(); | ||
const [error, setError] = useState<Error | null>(null); | ||
const setSources = useCallback( | ||
(sources: Record<string, string>) => { | ||
const entryFileName = Object.keys(asset.dependencies).find( | ||
(k) => asset.dependencies[k].type === 'FILE', | ||
)!; | ||
const entryFileCode = sources[entryFileName]; | ||
const require = (v: string) => { | ||
if (v in context) return context[v]; | ||
throw new Error(`Cannot find module: ${v}`); | ||
}; | ||
const exports: { default?: ComponentType } = {}; | ||
const module = { exports }; | ||
|
||
// lazy load react-dom/server | ||
import('react-dom/server').then(({ renderToStaticMarkup }) => { | ||
try { | ||
// initial component with fake runtime | ||
new Function('module', 'exports', 'require', entryFileCode)( | ||
module, | ||
exports, | ||
require, | ||
); | ||
const newDemoNode = createElement( | ||
DemoErrorBoundary, | ||
null, | ||
createElement(exports.default!), | ||
); | ||
const oError = console.error; | ||
|
||
// hijack console.error to avoid useLayoutEffect error | ||
console.error = (...args) => | ||
!args[0].includes('useLayoutEffect does nothing on the server') && | ||
oError.apply(console, args); | ||
|
||
// check component is renderable, to avoid show react overlay error | ||
renderToStaticMarkup(newDemoNode); | ||
console.error = oError; | ||
|
||
// set new demo node with passing sources | ||
setDemoNode(newDemoNode); | ||
setError(null); | ||
} catch (err: any) { | ||
setError(err); | ||
} | ||
}); | ||
}, | ||
[context], | ||
); | ||
|
||
return { node: demoNode, error, setSources }; | ||
}; |
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
Oops, something went wrong.