Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(remix-dev/vite): remove Vite wrapper functions #8120

Merged
merged 5 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .changeset/hungry-buckets-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
"@remix-run/dev": patch
---

Remove `unstable_createViteServer` and `unstable_loadViteServerBuild` which were only minimal wrappers around Vite's `createServer` and `ssrLoadModule` functions when using a custom server.

**This is a breaking change for projects using the unstable Vite plugin.**

Instead, we now provide `unstable_viteServerBuildModuleId` so that custom servers interact with Vite directly rather than via Remix APIs, for example:

```diff
-import {
- unstable_createViteServer,
- unstable_loadViteServerBuild,
-} from "@remix-run/dev";
+import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
```

Creating the Vite server in middleware mode:

```diff
const vite =
process.env.NODE_ENV === "production"
? undefined
- : await unstable_loadViteServerBuild();
+ : await import("vite").then(({ createServer }) =>
+ createServer({
+ server: {
+ middlewareMode: true,
+ },
+ })
+ );
```

Loading the Vite server build in the request handler:

```diff
app.all(
"*",
createRequestHandler({
build: vite
- ? () => unstable_loadViteServerBuild(vite)
+ ? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId)
: await import("./build/server/index.js"),
})
);
```
31 changes: 17 additions & 14 deletions docs/future/vite.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,29 +163,23 @@ You'll also need to update to the new build output paths, which are `build/serve

#### Migrating from a custom server

If you were using a custom server in development, you'll need to update your server code to reference the new build output paths, which are `build/server` for the server build and `build/client` for client assets.

You'll also need to edit your custom server to use Vite's `connect` middleware.
If you were using a custom server in development, you'll need to edit your custom server to use Vite's `connect` middleware.
This will delegate asset requests and initial render requests to Vite during development, letting you benefit from Vite's excellent DX even with a custom server.

Remix exposes APIs for exactly this purpose:
You'll also need to update your server code to reference the new build output paths, which are `build/server` for the server build and `build/client` for client assets.

Remix exposes the server build's module ID so that it can be loaded dynamically in your request handler during development via `vite.ssrLoadModule`.

```ts
import {
unstable_createViteServer, // provides middleware for handling asset requests
unstable_loadViteServerBuild, // handles initial render requests
} from "@remix-run/dev";
import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
```

For example, if you were using Express, here's how you could do it.

👉 **Update your `server.mjs` file**

```ts filename=server.mjs lines=[1-4,11-14,18-21,29,36-38]
import {
unstable_createViteServer,
unstable_loadViteServerBuild,
} from "@remix-run/dev";
import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
import { createRequestHandler } from "@remix-run/express";
import { installGlobals } from "@remix-run/node";
import express from "express";
Expand All @@ -195,7 +189,13 @@ installGlobals();
const vite =
process.env.NODE_ENV === "production"
? undefined
: await unstable_createViteServer();
: await import("vite").then(({ createServer }) =>
createServer({
server: {
middlewareMode: true,
},
})
);

const app = express();

Expand All @@ -218,7 +218,10 @@ app.all(
"*",
createRequestHandler({
build: vite
? () => unstable_loadViteServerBuild(vite)
? () =>
vite.ssrLoadModule(
unstable_viteServerBuildModuleId
)
: await import("./build/server/index.js"),
})
);
Expand Down
21 changes: 11 additions & 10 deletions integration/helpers/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ export const basicTemplate = (args: {
});
`,
"server.mjs": js`
import {
unstable_createViteServer,
unstable_loadViteServerBuild,
} from "@remix-run/dev";
import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
import { createRequestHandler } from "@remix-run/express";
import { installGlobals } from "@remix-run/node";
import express from "express";
Expand All @@ -42,26 +39,30 @@ export const basicTemplate = (args: {
let vite =
process.env.NODE_ENV === "production"
? undefined
: await unstable_createViteServer();
: await import("vite").then(({ createServer }) =>
createServer({
server: { middlewareMode: true },
})
);

const app = express();

if (vite) {
app.use(vite.middlewares);
} else {
app.use(
"/build",
express.static("public/build", { immutable: true, maxAge: "1y" })
"/assets",
express.static("build/client/assets", { immutable: true, maxAge: "1y" })
);
}
app.use(express.static("public", { maxAge: "1h" }));
app.use(express.static("build/client", { maxAge: "1h" }));

app.all(
"*",
createRequestHandler({
build: vite
? () => unstable_loadViteServerBuild(vite)
: await import("./build/index.js"),
? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId)
: await import("./build/server/index.js"),
${args.requestHandlerArgs ?? ""}
})
);
Expand Down
27 changes: 15 additions & 12 deletions integration/vite-css-dev-express-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ test.describe("Vite CSS dev (Express server)", () => {
});
`,
"server.mjs": js`
import {
unstable_createViteServer,
unstable_loadViteServerBuild,
} from "@remix-run/dev";
import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
import { createRequestHandler } from "@remix-run/express";
import { installGlobals } from "@remix-run/node";
import express from "express";
Expand All @@ -54,26 +51,32 @@ test.describe("Vite CSS dev (Express server)", () => {
let vite =
process.env.NODE_ENV === "production"
? undefined
: await unstable_createViteServer();

const app = express();
: await import("vite").then(({ createServer }) =>
createServer({
server: {
middlewareMode: true
},
})
);

const app = express();

if (vite) {
app.use(vite.middlewares);
} else {
app.use(
"/build",
express.static("public/build", { immutable: true, maxAge: "1y" })
"/assets",
express.static("build/client/assets", { immutable: true, maxAge: "1y" })
);
}
app.use(express.static("public", { maxAge: "1h" }));
app.use(express.static("build/client", { maxAge: "1h" }));

app.all(
"*",
createRequestHandler({
build: vite
? () => unstable_loadViteServerBuild(vite)
: await import("./build/index.js"),
? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId)
: await import("./build/server/index.js"),
})
);

Expand Down
6 changes: 1 addition & 5 deletions packages/remix-dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@ export * as cli from "./cli/index";

export type { Manifest as AssetsManifest } from "./manifest";
export { getDependenciesToBundle } from "./dependencies";
export {
unstable_vitePlugin,
unstable_createViteServer,
unstable_loadViteServerBuild,
} from "./vite";
export { unstable_vitePlugin, unstable_viteServerBuildModuleId } from "./vite";
19 changes: 4 additions & 15 deletions packages/remix-dev/vite/index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
// This file allows us to dynamically require the plugin so non-Vite consumers
// don't need to have Vite installed as a peer dependency. Only types should
// be imported at the top level.
import type { ViteDevServer } from "vite";

import type { RemixVitePlugin } from "./plugin";
import { id } from "./vmod";
import { serverEntryId } from "./server-entry-id";

export const unstable_vitePlugin: RemixVitePlugin = (...args) => {
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
let { remixVitePlugin } = require("./plugin") as typeof import("./plugin");
return remixVitePlugin(...args);
};

export const unstable_createViteServer = async () => {
let vite = await import("vite");
return vite.createServer({
server: {
middlewareMode: true,
},
});
};

export const unstable_loadViteServerBuild = async (vite: ViteDevServer) => {
return vite.ssrLoadModule(id("server-entry"));
};
// We rename this export because from a consumer's perspective this is the
// "server build" since they also provide their own server entry
export const unstable_viteServerBuildModuleId = serverEntryId;
2 changes: 1 addition & 1 deletion packages/remix-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import invariant from "../invariant";
import { createRequestHandler } from "./node/adapter";
import { getStylesForUrl, isCssModulesFile } from "./styles";
import * as VirtualModule from "./vmod";
import { serverEntryId } from "./server-entry-id";
import { removeExports } from "./remove-exports";
import { replaceImportSpecifier } from "./replace-import-specifier";

Expand Down Expand Up @@ -88,7 +89,6 @@ type ResolvedRemixVitePluginConfig = Pick<
| "serverModuleFormat"
>;

let serverEntryId = VirtualModule.id("server-entry");
let serverManifestId = VirtualModule.id("server-manifest");
let browserManifestId = VirtualModule.id("browser-manifest");
let remixReactProxyId = VirtualModule.id("remix-react-proxy");
Expand Down
5 changes: 5 additions & 0 deletions packages/remix-dev/vite/server-entry-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This file allows us to export the module ID without forcing non-Vite
// consumers to inadvertently import the Vite plugin and all of its dependencies
import * as VirtualModule from "./vmod";

export const serverEntryId = VirtualModule.id("server-entry");
9 changes: 0 additions & 9 deletions templates/unstable-vite-express/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,6 @@ npm run start

## Customize

Remix exposes APIs for integrating Vite with a custom server:

```ts
import {
unstable_createViteServer,
unstable_loadViteServerBuild,
} from "@remix-run/dev";
```

In this template, we'll use Express but remember that these APIs can be used with _any_ Node-compatible server setup that supports standard middleware.

[remix-vite-docs]: https://remix.run/docs/en/main/future/vite
15 changes: 9 additions & 6 deletions templates/unstable-vite-express/server.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
unstable_createViteServer,
unstable_loadViteServerBuild,
} from "@remix-run/dev";
import { unstable_viteServerBuildModuleId } from "@remix-run/dev";
import { createRequestHandler } from "@remix-run/express";
import { installGlobals } from "@remix-run/node";
import express from "express";
Expand All @@ -11,7 +8,13 @@ installGlobals();
const vite =
process.env.NODE_ENV === "production"
? undefined
: await unstable_createViteServer();
: await import("vite").then(({ createServer }) =>
createServer({
server: {
middlewareMode: true,
},
})
);

const app = express();

Expand All @@ -31,7 +34,7 @@ app.all(
"*",
createRequestHandler({
build: vite
? () => unstable_loadViteServerBuild(vite)
? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId)
: await import("./build/server/index.js"),
})
);
Expand Down