diff --git a/packages/server-dev/next.config.js b/packages/server-dev/next.config.js index 9387fd6b6..1af269221 100644 --- a/packages/server-dev/next.config.js +++ b/packages/server-dev/next.config.js @@ -7,7 +7,7 @@ module.exports = withLess({ modifyVars: appConfig.style.lessVariables, }, }, - reactStrictMode: true, + // reactStrictMode: true, webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback = { diff --git a/packages/server-dev/src/components/Page.js b/packages/server-dev/src/components/Page.js index 760d83328..394dda492 100644 --- a/packages/server-dev/src/components/Page.js +++ b/packages/server-dev/src/components/Page.js @@ -21,6 +21,7 @@ import { useRouter } from 'next/router'; import Context from './Context.js'; import Head from './Head.js'; import Block from './block/Block.js'; +import Reload from './Reload.js'; import PageConfig from './PageConfig.js'; import setupLink from '../utils/setupLink.js'; @@ -37,32 +38,34 @@ const Page = ({ lowdefy }) => { if (!lowdefy._internal.query.pageId) return ; return ( - - {(pageConfig) => { - return ( - - {(context, loading) => { - if (loading) { - return ; - } - return ( - <> - - - - ); - }} - - ); - }} - + + + {(pageConfig) => { + return ( + + {(context, loading) => { + if (loading) { + return ; + } + return ( + <> + + + + ); + }} + + ); + }} + + ); }; diff --git a/packages/server-dev/src/components/Reload.js b/packages/server-dev/src/components/Reload.js new file mode 100644 index 000000000..2d8f510ed --- /dev/null +++ b/packages/server-dev/src/components/Reload.js @@ -0,0 +1,57 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import React, { useEffect } from 'react'; +import { useSWRConfig } from 'swr'; + +function useMutateCache() { + const { cache, mutate } = useSWRConfig(); + return () => { + const keys = ['/api/root']; + + for (const key of cache.keys()) { + if (key.startsWith('/api/page')) { + keys.push(key); + } + } + console.log('mutate', keys); + const mutations = keys.map((key) => mutate(key)); + return Promise.all(mutations); + }; +} + +const Reload = ({ children }) => { + const mutateCache = useMutateCache(); + useEffect(() => { + const sse = new EventSource('/api/reload'); + + sse.onmessage = (event) => { + console.log(event); + mutateCache(); + }; + sse.onerror = (error) => { + console.log('ERROR'); + console.error(error); + sse.close(); + }; + return () => { + sse.close(); + }; + }, []); + return <>{children}; +}; + +export default Reload; diff --git a/packages/server-dev/src/pages/api/reload.js b/packages/server-dev/src/pages/api/reload.js new file mode 100644 index 000000000..9653ca1f6 --- /dev/null +++ b/packages/server-dev/src/pages/api/reload.js @@ -0,0 +1,34 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +const handler = async (req, res) => { + console.log('Update'); + res.setHeader('Content-Type', 'text/event-stream;charset=utf-8'); + res.setHeader('Cache-Control', 'no-cache, no-transform'); + res.setHeader('X-Accel-Buffering', 'no'); + res.setHeader('Connection', 'keep-alive'); + + for (let i = 0; i < 10; i++) { + console.log('Sending event', i); + res.write(`data: Hello seq ${i}\n\n`); + await sleep(1500); + } + res.end('done\n'); +}; + +export default handler; diff --git a/packages/server-dev/src/utils/usePageConfig.js b/packages/server-dev/src/utils/usePageConfig.js index d71ed50ba..6ef61d816 100644 --- a/packages/server-dev/src/utils/usePageConfig.js +++ b/packages/server-dev/src/utils/usePageConfig.js @@ -17,15 +17,15 @@ import request from './request.js'; // TODO: Handle TokenExpiredError -function fetchPageConfig(pageId) { - return request({ url: `/api/page/${pageId}` }); +function fetchPageConfig(url) { + return request({ url }); } function usePageConfig(pageId) { if (!pageId) { pageId = 'NULL'; } - const { data } = useSWR(pageId, fetchPageConfig, { suspense: true }); + const { data } = useSWR(`/api/page/${pageId}`, fetchPageConfig, { suspense: true }); return { data }; }