From 6fb6bac7881efc1b371df490cc12070cd2762951 Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Thu, 28 Aug 2025 16:30:29 +0900 Subject: [PATCH 1/4] fix: split vite plugins --- src/commands/start/web/index.ts | 313 +----------------- .../mendix-hotreload-react-esbuild-plugin.ts | 186 +++++++++++ .../plugins/mendix-hotreload-react-plugin.ts | 129 ++++++++ 3 files changed, 320 insertions(+), 308 deletions(-) create mode 100644 src/configurations/vite/plugins/mendix-hotreload-react-esbuild-plugin.ts create mode 100644 src/configurations/vite/plugins/mendix-hotreload-react-plugin.ts diff --git a/src/commands/start/web/index.ts b/src/commands/start/web/index.ts index 940db16..eb8752f 100644 --- a/src/commands/start/web/index.ts +++ b/src/commands/start/web/index.ts @@ -11,6 +11,8 @@ import { getViteDefaultConfig } from '../../../configurations/vite'; import getWidgetName from '../../../utils/getWidgetName'; import getViteUserConfiguration from '../../../utils/getViteUserConfiguration'; import { generateTypesFromFile } from '../../../type-generator'; +import { mendixHotreloadReactPlugin } from '../../../configurations/vite/plugins/mendix-hotreload-react-plugin'; +import { mendixHotreloadReactEsbuildPlugin } from '../../../configurations/vite/plugins/mendix-hotreload-react-esbuild-plugin'; const generateTyping = async () => { const widgetName = await getWidgetName(); @@ -71,318 +73,13 @@ const startWebCommand = async () => { optimizeDeps: { esbuildOptions: { plugins: [ - // @note When the React version of Mendix is updated, the following content must also be updated. - // @todo Depending on the React version, we need to consider whether there is a way to handle this automatically rather than manually. - { - name: 'replace-react-with-virtual', - setup(build) { - build.onResolve({ filter: /^react$/ }, (args) => { - return { - path: 'mendix:react', - namespace: 'mendix-react', - external: false - }; - }); - - build.onResolve({ filter: /^react-dom$/ }, (args) => { - return { - path: 'mendix:react-dom', - namespace: 'mendix-react-dom', - external: false - }; - }); - - build.onResolve({ filter: /^react-dom\/client$/ }, (args) => { - return { - path: 'mendix:react-dom/client', - namespace: 'mendix-react-dom-client', - external: false - }; - }); - - build.onResolve({ filter: /^react\/jsx-runtime$/ }, (args) => { - return { - path: 'mendix:react/jsx-runtime', - namespace: 'mendix-react-jsx-runtime', - external: false - }; - }); - - build.onResolve({ filter: /^react\/jsx-dev-runtime$/ }, (args) => { - return { - path: 'mendix:react/jsx-dev-runtime', - namespace: 'mendix-react-jsx-dev-runtime', - external: false - }; - }); - - build.onLoad({ filter: /.*/, namespace: 'mendix-react' }, () => { - return { - contents: ` - const React = window.React; - - export const Children = React.Children; - export const Component = React.Component; - export const Fragment = React.Fragment; - export const Profiler = React.Profiler; - export const PureComponent = React.PureComponent; - export const StrictMode = React.StrictMode; - export const Suspense = React.Suspense; - export const cloneElement = React.cloneElement; - export const createContext = React.createContext; - export const createElement = React.createElement; - export const createFactory = React.createFactory; - export const createRef = React.createRef; - export const forwardRef = React.forwardRef; - export const isValidElement = React.isValidElement; - export const lazy = React.lazy; - export const memo = React.memo; - export const startTransition = React.startTransition; - export const unstable_act = React.unstable_act; - export const useCallback = React.useCallback; - export const useContext = React.useContext; - export const useDebugValue = React.useDebugValue; - export const useDeferredValue = React.useDeferredValue; - export const useEffect = React.useEffect; - export const useId = React.useId; - export const useImperativeHandle = React.useImperativeHandle; - export const useInsertionEffect = React.useInsertionEffect; - export const useLayoutEffect = React.useLayoutEffect; - export const useMemo = React.useMemo; - export const useReducer = React.useReducer; - export const useRef = React.useRef; - export const useState = React.useState; - export const useSyncExternalStore = React.useSyncExternalStore; - export const useTransition = React.useTransition; - export const version = React.version; - - export default React; - `, - loader: 'js', - }; - }); - - build.onLoad({ filter: /.*/, namespace: 'mendix-react-dom' }, () => { - return { - contents: ` - const ReactDOM = window.ReactDOM; - - export const createPortal = ReactDOM.createPortal; - export const createRoot = ReactDOM.createRoot; - export const findDOMNode = ReactDOM.findDOMNode; - export const flushSync = ReactDOM.flushSync; - export const hydrate = ReactDOM.hydrate; - export const hydrateRoot = ReactDOM.hydrateRoot; - export const render = ReactDOM.render; - export const unmountComponentAtNode = ReactDOM.unmountComponentAtNode; - export const unstable_batchedUpdates = ReactDOM.unstable_batchedUpdates; - export const unstable_renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer; - export const version = ReactDOM.version; - - export default ReactDOM; - `, - loader: 'js', - }; - }); - - build.onLoad({ filter: /.*/, namespace: 'mendix-react-dom-client' }, () => { - return { - contents: ` - const ReactDOMClient = window.ReactDOMClient; - - export const createRoot = ReactDOMClient.createRoot; - export const hydrateRoot = ReactDOMClient.hydrateRoot; - - export default ReactDOMClient; - `, - loader: 'js', - }; - }); - - build.onLoad({ filter: /.*/, namespace: 'mendix-react-jsx-runtime' }, () => { - return { - contents: ` - const ReactJSXRuntime = window.ReactJSXRuntime; - - export const Fragment = ReactJSXRuntime.Fragment; - export const jsx = ReactJSXRuntime.jsx; - export const jsxs = ReactJSXRuntime.jsxs; - - export default ReactJSXRuntime; - `, - loader: 'js', - }; - }); - - build.onLoad({ filter: /.*/, namespace: 'mendix-react-jsx-dev-runtime' }, () => { - return { - contents: ` - const ReactJSXDevRuntime = window.ReactJSXDevRuntime; - - export const Fragment = ReactJSXDevRuntime.Fragment; - export const jsxDEV = ReactJSXDevRuntime.jsxDEV; - - export default ReactJSXDevRuntime; - `, - loader: 'js', - }; - }); - - build.onResolve({ filter: /.*node_modules[\\\/]react[\\\/]index\.js$/ }, (args) => { - return { - path: 'mendix:react', - namespace: 'mendix-react', - external: false - }; - }); - - build.onResolve({ filter: /.*node_modules[\\\/]react-dom[\\\/]index\.js$/ }, (args) => { - return { - path: 'mendix:react-dom', - namespace: 'mendix-react-dom', - external: false - }; - }); - - build.onResolve({ filter: /.*node_modules[\\\/]react-dom[\\\/]client\.js$/ }, (args) => { - return { - path: 'mendix:react-dom/client', - namespace: 'mendix-react-dom-client', - external: false - }; - }); - } - } + mendixHotreloadReactEsbuildPlugin(), ], } }, plugins: [ ...resultViteConfig.plugins as PluginOption[], - // @note When the React version of Mendix is updated, the following content must also be updated. - // @todo Depending on the React version, we need to consider whether there is a way to handle this automatically rather than manually. - { - name: 'mendix-hotreload-react-18.2.0', - enforce: 'pre', - resolveId(id) { - if (id === 'react') { - return { id: 'mendix:react', external: true }; - } - - if (id === 'react-dom') { - return { id: 'mendix:react-dom', external: true }; - } - - if (id === 'react-dom/client') { - return { id: 'mendix:react-dom/client', external: true }; - } - - if (id === 'react/jsx-runtime') { - return { id: 'mendix:react/jsx-runtime', external: true }; - } - - if (id === 'react/jsx-dev-runtime') { - return { id: 'mendix:react/jsx-dev-runtime', external: true }; - } - }, - load(id) { - if (id === 'mendix:react') { - return ` - const React = window.React; - - export const Children = React.Children; - export const Component = React.Component; - export const Fragment = React.Fragment; - export const Profiler = React.Profiler; - export const PureComponent = React.PureComponent; - export const StrictMode = React.StrictMode; - export const Suspense = React.Suspense; - export const cloneElement = React.cloneElement; - export const createContext = React.createContext; - export const createElement = React.createElement; - export const createFactory = React.createFactory; - export const createRef = React.createRef; - export const forwardRef = React.forwardRef; - export const isValidElement = React.isValidElement; - export const lazy = React.lazy; - export const memo = React.memo; - export const startTransition = React.startTransition; - export const unstable_act = React.unstable_act; - export const useCallback = React.useCallback; - export const useContext = React.useContext; - export const useDebugValue = React.useDebugValue; - export const useDeferredValue = React.useDeferredValue; - export const useEffect = React.useEffect; - export const useId = React.useId; - export const useImperativeHandle = React.useImperativeHandle; - export const useInsertionEffect = React.useInsertionEffect; - export const useLayoutEffect = React.useLayoutEffect; - export const useMemo = React.useMemo; - export const useReducer = React.useReducer; - export const useRef = React.useRef; - export const useState = React.useState; - export const useSyncExternalStore = React.useSyncExternalStore; - export const useTransition = React.useTransition; - export const version = React.version; - - export default React; - `; - } - - if (id === 'mendix:react-dom') { - return ` - const ReactDOM = window.ReactDOM; - - export const createPortal = ReactDOM.createPortal; - export const createRoot = ReactDOM.createRoot; - export const findDOMNode = ReactDOM.findDOMNode; - export const flushSync = ReactDOM.flushSync; - export const hydrate = ReactDOM.hydrate; - export const hydrateRoot = ReactDOM.hydrateRoot; - export const render = ReactDOM.render; - export const unmountComponentAtNode = ReactDOM.unmountComponentAtNode; - export const unstable_batchedUpdates = ReactDOM.unstable_batchedUpdates; - export const unstable_renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer; - export const version = ReactDOM.version; - - export default ReactDOM; - `; - } - - if (id === 'mendix:react-dom/client') { - return ` - const ReactDOMClient = window.ReactDOMClient; - - export const createRoot = ReactDOMClient.createRoot; - export const hydrateRoot = ReactDOMClient.hydrateRoot; - - export default ReactDOMClient; - `; - } - - if (id === 'mendix:react/jsx-runtime') { - return ` - const ReactJSXRuntime = window.ReactJSXRuntime; - - export const Fragment = ReactJSXRuntime.Fragment; - export const jsx = ReactJSXRuntime.jsx; - export const jsxs = ReactJSXRuntime.jsxs; - - export default ReactJSXRuntime; - `; - } - - if (id === 'mendix:react/jsx-dev-runtime') { - return ` - const ReactJSXDevRuntime = window.ReactJSXDevRuntime; - - export const Fragment = ReactJSXDevRuntime.Fragment; - export const jsxDEV = ReactJSXDevRuntime.jsxDEV; - - export default ReactJSXDevRuntime; - `; - } - } - }, + mendixHotreloadReactPlugin(), { name: 'mendix-xml-watch-plugin', configureServer(server) { @@ -392,7 +89,7 @@ const startWebCommand = async () => { } }); } - } + }, ] }); diff --git a/src/configurations/vite/plugins/mendix-hotreload-react-esbuild-plugin.ts b/src/configurations/vite/plugins/mendix-hotreload-react-esbuild-plugin.ts new file mode 100644 index 0000000..3096244 --- /dev/null +++ b/src/configurations/vite/plugins/mendix-hotreload-react-esbuild-plugin.ts @@ -0,0 +1,186 @@ +import { Plugin } from "esbuild"; + +// @note When the React version of Mendix is updated, the following content must also be updated. +// @todo Depending on the React version, we need to consider whether there is a way to handle this automatically rather than manually. +export function mendixHotreloadReactEsbuildPlugin(): Plugin { + return { + name: 'mendix-hotreload-react-esbuild', + setup(build) { + build.onResolve({ filter: /^react$/ }, (args) => { + return { + path: 'mendix:react', + namespace: 'mendix-react', + external: false + }; + }); + + build.onResolve({ filter: /^react-dom$/ }, (args) => { + return { + path: 'mendix:react-dom', + namespace: 'mendix-react-dom', + external: false + }; + }); + + build.onResolve({ filter: /^react-dom\/client$/ }, (args) => { + return { + path: 'mendix:react-dom/client', + namespace: 'mendix-react-dom-client', + external: false + }; + }); + + build.onResolve({ filter: /^react\/jsx-runtime$/ }, (args) => { + return { + path: 'mendix:react/jsx-runtime', + namespace: 'mendix-react-jsx-runtime', + external: false + }; + }); + + build.onResolve({ filter: /^react\/jsx-dev-runtime$/ }, (args) => { + return { + path: 'mendix:react/jsx-dev-runtime', + namespace: 'mendix-react-jsx-dev-runtime', + external: false + }; + }); + + build.onLoad({ filter: /.*/, namespace: 'mendix-react' }, () => { + return { + contents: ` + const React = window.React; + + export const Children = React.Children; + export const Component = React.Component; + export const Fragment = React.Fragment; + export const Profiler = React.Profiler; + export const PureComponent = React.PureComponent; + export const StrictMode = React.StrictMode; + export const Suspense = React.Suspense; + export const cloneElement = React.cloneElement; + export const createContext = React.createContext; + export const createElement = React.createElement; + export const createFactory = React.createFactory; + export const createRef = React.createRef; + export const forwardRef = React.forwardRef; + export const isValidElement = React.isValidElement; + export const lazy = React.lazy; + export const memo = React.memo; + export const startTransition = React.startTransition; + export const unstable_act = React.unstable_act; + export const useCallback = React.useCallback; + export const useContext = React.useContext; + export const useDebugValue = React.useDebugValue; + export const useDeferredValue = React.useDeferredValue; + export const useEffect = React.useEffect; + export const useId = React.useId; + export const useImperativeHandle = React.useImperativeHandle; + export const useInsertionEffect = React.useInsertionEffect; + export const useLayoutEffect = React.useLayoutEffect; + export const useMemo = React.useMemo; + export const useReducer = React.useReducer; + export const useRef = React.useRef; + export const useState = React.useState; + export const useSyncExternalStore = React.useSyncExternalStore; + export const useTransition = React.useTransition; + export const version = React.version; + + export default React; + `, + loader: 'js', + }; + }); + + build.onLoad({ filter: /.*/, namespace: 'mendix-react-dom' }, () => { + return { + contents: ` + const ReactDOM = window.ReactDOM; + + export const createPortal = ReactDOM.createPortal; + export const createRoot = ReactDOM.createRoot; + export const findDOMNode = ReactDOM.findDOMNode; + export const flushSync = ReactDOM.flushSync; + export const hydrate = ReactDOM.hydrate; + export const hydrateRoot = ReactDOM.hydrateRoot; + export const render = ReactDOM.render; + export const unmountComponentAtNode = ReactDOM.unmountComponentAtNode; + export const unstable_batchedUpdates = ReactDOM.unstable_batchedUpdates; + export const unstable_renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer; + export const version = ReactDOM.version; + + export default ReactDOM; + `, + loader: 'js', + }; + }); + + build.onLoad({ filter: /.*/, namespace: 'mendix-react-dom-client' }, () => { + return { + contents: ` + const ReactDOMClient = window.ReactDOMClient; + + export const createRoot = ReactDOMClient.createRoot; + export const hydrateRoot = ReactDOMClient.hydrateRoot; + + export default ReactDOMClient; + `, + loader: 'js', + }; + }); + + build.onLoad({ filter: /.*/, namespace: 'mendix-react-jsx-runtime' }, () => { + return { + contents: ` + const ReactJSXRuntime = window.ReactJSXRuntime; + + export const Fragment = ReactJSXRuntime.Fragment; + export const jsx = ReactJSXRuntime.jsx; + export const jsxs = ReactJSXRuntime.jsxs; + + export default ReactJSXRuntime; + `, + loader: 'js', + }; + }); + + build.onLoad({ filter: /.*/, namespace: 'mendix-react-jsx-dev-runtime' }, () => { + return { + contents: ` + const ReactJSXDevRuntime = window.ReactJSXDevRuntime; + + export const Fragment = ReactJSXDevRuntime.Fragment; + export const jsxDEV = ReactJSXDevRuntime.jsxDEV; + + export default ReactJSXDevRuntime; + `, + loader: 'js', + }; + }); + + build.onResolve({ filter: /.*node_modules[\\\/]react[\\\/]index\.js$/ }, (args) => { + return { + path: 'mendix:react', + namespace: 'mendix-react', + external: false + }; + }); + + build.onResolve({ filter: /.*node_modules[\\\/]react-dom[\\\/]index\.js$/ }, (args) => { + return { + path: 'mendix:react-dom', + namespace: 'mendix-react-dom', + external: false + }; + }); + + build.onResolve({ filter: /.*node_modules[\\\/]react-dom[\\\/]client\.js$/ }, (args) => { + return { + path: 'mendix:react-dom/client', + namespace: 'mendix-react-dom-client', + external: false + }; + }); + } + }; +} \ No newline at end of file diff --git a/src/configurations/vite/plugins/mendix-hotreload-react-plugin.ts b/src/configurations/vite/plugins/mendix-hotreload-react-plugin.ts new file mode 100644 index 0000000..91e6880 --- /dev/null +++ b/src/configurations/vite/plugins/mendix-hotreload-react-plugin.ts @@ -0,0 +1,129 @@ +import { Plugin } from "vite"; + +// @note When the React version of Mendix is updated, the following content must also be updated. +// @todo Depending on the React version, we need to consider whether there is a way to handle this automatically rather than manually. +export function mendixHotreloadReactPlugin(): Plugin { + return { + name: 'mendix-hotreload-react-18.2.0', + enforce: 'pre', + resolveId(id) { + if (id === 'react') { + return { id: 'mendix:react', external: true }; + } + + if (id === 'react-dom') { + return { id: 'mendix:react-dom', external: true }; + } + + if (id === 'react-dom/client') { + return { id: 'mendix:react-dom/client', external: true }; + } + + if (id === 'react/jsx-runtime') { + return { id: 'mendix:react/jsx-runtime', external: true }; + } + + if (id === 'react/jsx-dev-runtime') { + return { id: 'mendix:react/jsx-dev-runtime', external: true }; + } + }, + load(id) { + if (id === 'mendix:react') { + return ` + const React = window.React; + + export const Children = React.Children; + export const Component = React.Component; + export const Fragment = React.Fragment; + export const Profiler = React.Profiler; + export const PureComponent = React.PureComponent; + export const StrictMode = React.StrictMode; + export const Suspense = React.Suspense; + export const cloneElement = React.cloneElement; + export const createContext = React.createContext; + export const createElement = React.createElement; + export const createFactory = React.createFactory; + export const createRef = React.createRef; + export const forwardRef = React.forwardRef; + export const isValidElement = React.isValidElement; + export const lazy = React.lazy; + export const memo = React.memo; + export const startTransition = React.startTransition; + export const unstable_act = React.unstable_act; + export const useCallback = React.useCallback; + export const useContext = React.useContext; + export const useDebugValue = React.useDebugValue; + export const useDeferredValue = React.useDeferredValue; + export const useEffect = React.useEffect; + export const useId = React.useId; + export const useImperativeHandle = React.useImperativeHandle; + export const useInsertionEffect = React.useInsertionEffect; + export const useLayoutEffect = React.useLayoutEffect; + export const useMemo = React.useMemo; + export const useReducer = React.useReducer; + export const useRef = React.useRef; + export const useState = React.useState; + export const useSyncExternalStore = React.useSyncExternalStore; + export const useTransition = React.useTransition; + export const version = React.version; + + export default React; + `; + } + + if (id === 'mendix:react-dom') { + return ` + const ReactDOM = window.ReactDOM; + + export const createPortal = ReactDOM.createPortal; + export const createRoot = ReactDOM.createRoot; + export const findDOMNode = ReactDOM.findDOMNode; + export const flushSync = ReactDOM.flushSync; + export const hydrate = ReactDOM.hydrate; + export const hydrateRoot = ReactDOM.hydrateRoot; + export const render = ReactDOM.render; + export const unmountComponentAtNode = ReactDOM.unmountComponentAtNode; + export const unstable_batchedUpdates = ReactDOM.unstable_batchedUpdates; + export const unstable_renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer; + export const version = ReactDOM.version; + + export default ReactDOM; + `; + } + + if (id === 'mendix:react-dom/client') { + return ` + const ReactDOMClient = window.ReactDOMClient; + + export const createRoot = ReactDOMClient.createRoot; + export const hydrateRoot = ReactDOMClient.hydrateRoot; + + export default ReactDOMClient; + `; + } + + if (id === 'mendix:react/jsx-runtime') { + return ` + const ReactJSXRuntime = window.ReactJSXRuntime; + + export const Fragment = ReactJSXRuntime.Fragment; + export const jsx = ReactJSXRuntime.jsx; + export const jsxs = ReactJSXRuntime.jsxs; + + export default ReactJSXRuntime; + `; + } + + if (id === 'mendix:react/jsx-dev-runtime') { + return ` + const ReactJSXDevRuntime = window.ReactJSXDevRuntime; + + export const Fragment = ReactJSXDevRuntime.Fragment; + export const jsxDEV = ReactJSXDevRuntime.jsxDEV; + + export default ReactJSXDevRuntime; + `; + } + } + }; +} \ No newline at end of file From de1242426fd74ae7c03cb0321b7692f16f1bdf1c Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Thu, 28 Aug 2025 16:45:19 +0900 Subject: [PATCH 2/4] feat: add esbuild on dev dependency --- package.json | 1 + pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/package.json b/package.json index 0e180be..610b1c6 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "devDependencies": { "@rslib/core": "0.12.2", "@types/node": "22.17.2", + "esbuild": "0.25.9", "type-fest": "4.41.0", "typescript": "5.9.2" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19278cd..bf4b390 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,6 +36,9 @@ importers: '@types/node': specifier: 22.17.2 version: 22.17.2 + esbuild: + specifier: 0.25.9 + version: 0.25.9 type-fest: specifier: 4.41.0 version: 4.41.0 From e3bcb5dd885960fb7515c753cd68f5809f70f07d Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Thu, 28 Aug 2025 17:39:16 +0900 Subject: [PATCH 3/4] feat: add mendix patch vite client plugin --- src/commands/start/web/index.ts | 2 + .../mendix-patch-vite-client-plugin.ts | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/configurations/vite/plugins/mendix-patch-vite-client-plugin.ts diff --git a/src/commands/start/web/index.ts b/src/commands/start/web/index.ts index eb8752f..54b6fa4 100644 --- a/src/commands/start/web/index.ts +++ b/src/commands/start/web/index.ts @@ -13,6 +13,7 @@ import getViteUserConfiguration from '../../../utils/getViteUserConfiguration'; import { generateTypesFromFile } from '../../../type-generator'; import { mendixHotreloadReactPlugin } from '../../../configurations/vite/plugins/mendix-hotreload-react-plugin'; import { mendixHotreloadReactEsbuildPlugin } from '../../../configurations/vite/plugins/mendix-hotreload-react-esbuild-plugin'; +import { mendixPatchViteClientPlugin } from '../../../configurations/vite/plugins/mendix-patch-vite-client-plugin'; const generateTyping = async () => { const widgetName = await getWidgetName(); @@ -80,6 +81,7 @@ const startWebCommand = async () => { plugins: [ ...resultViteConfig.plugins as PluginOption[], mendixHotreloadReactPlugin(), + mendixPatchViteClientPlugin(), { name: 'mendix-xml-watch-plugin', configureServer(server) { diff --git a/src/configurations/vite/plugins/mendix-patch-vite-client-plugin.ts b/src/configurations/vite/plugins/mendix-patch-vite-client-plugin.ts new file mode 100644 index 0000000..5513bb2 --- /dev/null +++ b/src/configurations/vite/plugins/mendix-patch-vite-client-plugin.ts @@ -0,0 +1,56 @@ +import { Plugin } from "vite"; + +export function mendixPatchViteClientPlugin(): Plugin { + return { + name: 'mendix-patch-vite-client', + enforce: 'pre', + apply: 'serve', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + const url = req.url || ''; + + if (url.includes('@vite/client.mjs')) { + const transformed = await server.transformRequest('/@vite/client.mjs'); + let code = transformed?.code || ''; + const rePageReload = /const\s+pageReload\s*=\s*debounceReload\(\s*(\d+)\s*\)/; + const m = code.match(rePageReload); + + if (m) { + const delay = m[1]; + const injectScript = ` +const __mx_debounceReload = (time) => { + let timer; + return () => { + if (timer) { clearTimeout(timer); timer = null; } + + timer = setTimeout(() => { + try { + const mx = (typeof window !== 'undefined') ? window.mx : undefined; + + if (mx) { + mx.reloadWithState(); + return; + } + } catch (e) { + console.warn('[patch-vite-client-debounce] mx.reloadWithState failed:', e); + } + + location.reload(); + }, time); + }; +}; + `; + + code = code.replace(rePageReload, `${injectScript}\nconst pageReload = __mx_debounceReload(${delay})`); + } + + res.setHeader('Content-Type', 'application/javascript; charset=utf-8'); + res.end(code); + return; + } + + next(); + }); + } + }; +} \ No newline at end of file From c43ba98f9c708e79c6209f30139aca80ab4bbf8a Mon Sep 17 00:00:00 2001 From: Chan Kang Date: Thu, 28 Aug 2025 17:39:44 +0900 Subject: [PATCH 4/4] feat: bump version to 0.1.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 610b1c6..212c6b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@repixelcorp/hyper-pwt", - "version": "0.1.5", + "version": "0.1.6", "description": "A faster, more modern, superior alternative for Mendix PWT.", "repository": { "type": "git",