# Survey Content Preview ## Why do we need content preview? - To reduce clinet anxiety. - To show page style change in time. ![截圖 2024-11-06 中午12.37.45](https://hackmd.io/_uploads/Bk_sz_O-kx.png) ## Methods ### 1. Copy page style and implement content preview directly in content editor ```jsx export default function ContentEditor () { const [color, setColor] = useState('#FFFFFF') return ( <div> <ContentForm color={color} setColor={setColor} /> {/* Clone styles from content page */} <ContentPreview color={color} /> </div> ) } ``` - Pros: - Brute, Easy, and Effective. - Different frontend frameworks among content page and content editor are acceptable. - Cons: - Copy / paste. - Hard to maintenance in the future. - Preview and page are not in the same repo. - Need to handle viewport issue. - Use Case: - Pages with simple style and simple bussiness logic. ### 2. Use iframe in content editor to connect with content page and set style of it through message api ```jsx const contentPreviewUrl = 'https://content/preview' export default function ContentEditor () { const ref = useRef(null) // Use this additional boolean flag to prevent iframe sending message to iframe before it's ready. const [isIframeLoaded, setIsIframeLoaded] = useState(false) const [color, setColor] = useState('#FFFFFF') useEffect(() => { if (ref.current && isIframeLoaded) { ref.current?.contentWindow?.postMessage({ key: 'backgroundColor', value: color }, contentPreviewUrl) } }, [isIframeLoaded, ref]) return ( <div> <ContentForm color={color} /> <iframe ref={ref} src={contentPreviewUrl} lazy onLoad={() => setIsIframeLoaded(true)} /> </div> ) } ``` ```vue <template> <div> <button type="button" style={{ backgroundColor }} /> </div> </template> <script lang="js" setup> const backgroundColor = ref('') const handleMessage = () => { // Should verify e.origin to trust only OAPlus origin by phase if (e.origin !== 'http://{safety-parent-origin-here}') { return } switch (e.data.key) { // You can use cloneDeepRight if event data is nested, // so you don't need to handle multiple key action here. case 'backgroundColor': this.backgroundColor = e.data.value break default: console.log('mismatched key!') } } window.addEventListener('message', handleMessage) onUnmounted(() => { window.removeEventListener('message', handleMessage) }) </script> ``` - Pros: - Different frontend frameworks among content page and content editor are acceptable. - Reusable components. - Preview and page are in the same repo. - Cons: - Take time to refactor pure components. - No need to handle viewport issue. - Use Case: - Content page and content editor are based on different frontend framwork. - Pages with complicated style, special bussiness logic, and lacks of UI freedom. ### 3. Extract component library and apply with both content page and content editor ```jsx import { Button } from '@xxx/ui-library' export default function ContentEditable () { const [color, setColor] = useState('#FFFFFF') return ( <div> <ContentForm color={color} setColor={setColor} /> <div> {/* Compose content preview with ui library */} <Button type="button" color={color} /> </div> </div> ) } ``` ```jsx import { Button } from '@xxx/ui-library' export default function ContentPage () { const color = '#FFFFFF' const handleButtonClick = () => { console.log('Do some bussiness logic') } return ( <div> <Button type="button" color={color} onClick={handleButtonClick} /> </div> ) } ``` - Pros: - Reusable components. - Cons: - Same frontend framework among repos are required (or web components). - Take time to extract components or make repo using the same frontend framework. - Preview and page are not in the same repo. - Need to handle viewport issue. - Case: - Content page and content editor are based on same frontend framwork. - Pages with complicated style, special bussiness logic, and lacks of UI freedom. ## Conclusion My team uses method 2 (iframe) because our monorepo project is based on different frontend framework and it spends least time to implement. But we should handle CSP (Content Security Policy) additionally to prevent other website to use the preview page.