Can I run one-time code at vite server start without a custom server? #8931
-
Is it possible to run some environment validation code as the built-in Remix server starts? I'm using the vite plugin and I'd like to avoid the maintenence burden of Related, but uses custom server: #8694 |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 10 replies
-
Although doable, it's kind of tricky due to the fact the development and production builds are different. In DEV mode, Vite is responsible for the web server. Whereas in PROD, we are using Remix App Server, and it uses the build output from Vite remix vite:build. So, to tackle Vite DEV, I created a serviceStartup plugin that will let you pass in a set of services to start. I created a folder app/startup with the startup functions. // vite.config.ts
import serviceStart from "./app/startup/service";
import anotherServiceStart from "./app/startup/another-service";
installGlobals();
export default defineConfig({
plugins: [
serviceStartup({
"my-service": serviceStart,
"another-service": anotherServiceStart,
}),
remix(),
tsconfigPaths(),
],
});
type ServicesType = Record<string, () => void>;
function serviceStartup(services: ServicesType) {
const serviceStatus = new Map<string, boolean>();
return {
name: "service-startup",
configureServer(server: { config: { appType: string; mode: string } }) {
// remix vite does two builds, so only start services for custom SSR
if (
server.config.mode === "development" &&
server.config.appType === "custom"
) {
Object.entries(services).forEach(([name, startFunction]) => {
// check if service already started
if (serviceStatus.get(name)) return;
console.log(`starting service: ${name}`);
startFunction();
console.log();
serviceStatus.set(name, true);
});
}
},
};
} // app/startup/service.ts
export default function start() {
console.log("service started!");
}
// app/startup/another-service.ts
export default function start() {
console.log("another service started!");
} This should start all the services when the Vite DEV server initializes. Now, for a PROD build, we can't update RAS, and you don't want Add this to your root route, and it will start the services on startup. // app/root.tsx
import serviceStart from "~/startup/service";
import anotherServiceStart from "~/startup/another-service";
function start() {
console.log("starting services from root");
serviceStart();
anotherServiceStart();
}
// only run this in production, since Vite handles startup in development
if (process.env.NODE_ENV === "production") {
start();
} Normally we could just add this to root and it'll work in both DEV and PROD, but Vite doesn't execute the root route until the first request. |
Beta Was this translation helpful? Give feedback.
-
A little late to the party, but what about verifying the environment variables in a separate script before starting the app? That way you avoid the issues of when verification is actually called when starting the remix server. for example in package.json:
|
Beta Was this translation helpful? Give feedback.
Ok, I figured out a solution. Install the Vite plugin
vite-env-only
by @pcattori.Update your vite.config.ts file to add the plugin.
Export your
checkEnv
functionThen in your root, import the function and wrap in
serverOnly$
callThis will call
checkEnv()
at startup for production builds, and on first route access for deve…