capri-js / capri

Build static sites with interactive islands
https://capri.build
MIT License
200 stars 5 forks source link

Hot Reload resulting in blank pages. #49

Closed phiberber closed 1 year ago

phiberber commented 1 year ago

One problem that I've had with Capri was the Hot Reload, seems that every Hot Reload makes Vite return the virtual/client.js file without the entry code, I can reproduce it just by running the preact example and changing the main.tsx file, here is the content Vite serves before the changes:

// http://127.0.0.1:5173/src/main.tsx
import.meta.env = {
    "BASE_URL": "/",
    "MODE": "development",
    "DEV": true,
    "PROD": false,
    "SSR": false
};
import "/node_modules/.vite/deps/preact_debug.js?v=a38e079f";
var _jsxFileName = "/Users/peixe/Projects/my-capri-site/src/main.tsx";
import {render} from "/node_modules/.vite/deps/preact.js?v=a38e079f";
import {Router} from "/node_modules/.vite/deps/wouter-preact.js?v=a38e079f";
import {App} from "/src/App.tsx";
import {PreviewBanner} from "/src/Preview.tsx";
import {jsxDEV as _jsxDEV} from "/node_modules/.vite/deps/preact_jsx-dev-runtime.js?v=a38e079f";
const base = import.meta.env.BASE_URL.slice(0, -1);
render(_jsxDEV(Router, {
    base,
    children: [_jsxDEV(PreviewBanner, {}, void 0, false, {
        fileName: _jsxFileName,
        lineNumber: 12,
        columnNumber: 5
    }, void 0), _jsxDEV(App, {}, void 0, false, {
        fileName: _jsxFileName,
        lineNumber: 13,
        columnNumber: 5
    }, void 0)]
}, void 0, true, {
    fileName: _jsxFileName,
    lineNumber: 11,
    columnNumber: 3
}, void 0), document.body);

Here is the content after the changes:

// http://127.0.0.1:5173/src/main.tsx?t=1677586235225
import "/node_modules/.vite/deps/preact_debug.js?v=a38e079f";
import "/@id/__x00__virtual:capri-hydration";

Seems that the t query parameter is added but it seems to have no effect on what Vite serves as the main.tsx file. To fix this issue I've changed the line 26 at https://github.com/capri-js/capri/blob/main/packages/capri/src/wrapper.ts from

if (isWrapperInfo(info)) {

to

if (process.env.NODE_ENV === "production" && isWrapperInfo(info)) {

Seems that this.getModuleInfo(id) returns {} when the project starts, adding the wrapper and wrapped values when hot reload is called. Seems the meta properties are only being added after the Hot Reload and I couldn't find the reason why.

I would like to know if you have any ideas on what could be happening here, if not I guess I will continue my debugging session.

fgnass commented 1 year ago

Can you maybe provide an example repository or CodeSandbox link? If I run npm run dev in the React example and modify Home.tsx hot reload works as intended. What steps are needed to reproduce the issue?

phiberber commented 1 year ago

Could you try to run the Preact example then? I can reproduce it by just installing the preact example and changing an entry file.

fgnass commented 1 year ago

Ah okay, I see. I can change any file but the entry script, i.e. changing Home.tsx (or any other component) works but changing main.tsx breaks. I hope I'll find some time to look into this tomorrow.

fgnass commented 1 year ago

Okay, I know what's going on. It all boils down to this line and me being lazy - I used the wrapper mechanism to serve the client hydration code even if the server entry is requested. The idea was to allow projects having only a server entry and no client entry file at all.