iTranslated by AI
Running Remix3 with Vite and HMR Support
Previous Article
This Repository
Using Remix3 from Vite
In the previous article, we built with rolldown and executed by calling scripts from an HTML file. This time, we will try running it from Vite with HMR support.
Vite Configuration
vite.config.ts
We will create a plugin that reloads the top-level script file when a file change is detected. Also, just like last time, we will set up aliases for JSX.
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
{
name: "reload",
handleHotUpdate({ server }) {
server.moduleGraph.getModuleByUrl("/src/main.tsx").then((mod) => {
if (mod) server.reloadModule(mod);
});
},
},
],
base: "./",
resolve: {
alias: {
"react/jsx-runtime": "@remix-run/dom/jsx-runtime",
"react/jsx-dev-runtime": "@remix-run/dom/jsx-dev-runtime",
},
},
});
Sample Program
main.tsx
This is the entry point file. We include a workaround to prevent a full reload during updates.
import { App } from "./App";
import { createRoot } from "@remix-run/dom";
createRoot(document.getElementById("root")!).render(<App />);
if (import.meta.hot) {
import.meta.hot.accept(() => {});
}
App.tsx
This is the count button component used in the previous article.
import { type Remix } from "@remix-run/dom";
import { dom } from "@remix-run/events";
import { Test } from "./Test";
export function App(this: Remix.Handle) {
let count = 0;
return () => (
<>
<button
on={[
dom.click(() => {
count++;
this.render();
}),
]}
>
Count: {count}
</button>
<Test value="test" />
</>
);
}
Test.tsx
This is for verifying mouseover events.
import { type Remix } from "@remix-run/dom";
import { dom } from "@remix-run/events";
export function Test(this: Remix.Handle) {
let mouseState = "mouseOut";
return ({ value }: { value: string }) => (
<div
on={[
dom.mouseover(() => {
mouseState = "mouseOver";
this.render();
}),
dom.mouseout(() => {
mouseState = "mouseOut";
this.render();
}),
]}
>
{value}:{mouseState}
</div>
);
}
HMR and States That Are Not Preserved
I succeeded in preventing a full reload during HMR, keeping the HTML file as is while making only the script files targets for reloading. However, there is a fundamental problem.
The data area corresponding to React's state in each component is a variable within the function. However, if the JSX structure is modified, it's necessary to return the new content as a return value, which requires re-executing the function. When this happens, the contents of the variables are naturally initialized. In other words, there is no way to maintain state during HMR like React does.
As for where React stores its state, it places them in a specific order within external variables managed by React. Remix3, which does not have such a structure, is currently unable to implement functionality to maintain state.
Conclusion
Remix3 is still under development, so there is a high possibility that the specifications will be significantly modified in the future. Since there are many issues to be resolved, I have a feeling that it will take quite a while before it is officially released.
Discussion