Skip to content

Commit

Permalink
vite: Enable use of vite preview to preview built SPA sites (#8624)
Browse files Browse the repository at this point in the history
  • Loading branch information
ngbrown authored Feb 8, 2024
1 parent 07a73a2 commit fff83ad
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 48 deletions.
8 changes: 8 additions & 0 deletions .changeset/tender-pens-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@remix-run/dev": patch
---

vite: Enable use of `vite preview` to preview built SPA sites

In the SPA template, `start` script (`npm run start`) has been renamed to `preview` (`npm run preview`).
In the SPA template, `npm run preview` uses `vite preview` for serving built SPA sites.
101 changes: 58 additions & 43 deletions packages/remix-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,12 @@ export const remixVitePlugin: RemixVitePlugin = (remixUserConfig = {}) => {

return {
__remixPluginContext: ctx,
appType: "custom",
appType:
viteCommand === "serve" &&
viteConfigEnv.mode === "production" &&
ctx.remixConfig.unstable_ssr === false
? "spa"
: "custom",
optimizeDeps: {
include: [
// Pre-bundle React dependencies to avoid React duplicates,
Expand Down Expand Up @@ -938,48 +943,58 @@ export const remixVitePlugin: RemixVitePlugin = (remixUserConfig = {}) => {
],
},
base: viteUserConfig.base,
...(viteCommand === "build" && {
build: {
cssMinify: viteUserConfig.build?.cssMinify ?? true,
...(!viteConfigEnv.isSsrBuild
? {
manifest: true,
outDir: getClientBuildDirectory(ctx.remixConfig),
rollupOptions: {
preserveEntrySignatures: "exports-only",
input: [
ctx.entryClientFilePath,
...Object.values(ctx.remixConfig.routes).map(
(route) =>
`${path.resolve(
ctx.remixConfig.appDirectory,
route.file
)}${CLIENT_ROUTE_QUERY_STRING}`
),
],
},
}
: {
// We move SSR-only assets to client assets. Note that the
// SSR build can also emit code-split JS files (e.g. by
// dynamic import) under the same assets directory
// regardless of "ssrEmitAssets" option, so we also need to
// keep these JS files have to be kept as-is.
ssrEmitAssets: true,
copyPublicDir: false, // Assets in the public directory are only used by the client
manifest: true, // We need the manifest to detect SSR-only assets
outDir: getServerBuildDirectory(ctx),
rollupOptions: {
preserveEntrySignatures: "exports-only",
input: serverBuildId,
output: {
entryFileNames: ctx.remixConfig.serverBuildFile,
format: ctx.remixConfig.serverModuleFormat,
},
},
}),
},
}),
...(viteCommand === "build"
? {
build: {
cssMinify: viteUserConfig.build?.cssMinify ?? true,
...(!viteConfigEnv.isSsrBuild
? {
manifest: true,
outDir: getClientBuildDirectory(ctx.remixConfig),
rollupOptions: {
preserveEntrySignatures: "exports-only",
input: [
ctx.entryClientFilePath,
...Object.values(ctx.remixConfig.routes).map(
(route) =>
`${path.resolve(
ctx.remixConfig.appDirectory,
route.file
)}${CLIENT_ROUTE_QUERY_STRING}`
),
],
},
}
: {
// We move SSR-only assets to client assets. Note that the
// SSR build can also emit code-split JS files (e.g. by
// dynamic import) under the same assets directory
// regardless of "ssrEmitAssets" option, so we also need to
// keep these JS files have to be kept as-is.
ssrEmitAssets: true,
copyPublicDir: false, // Assets in the public directory are only used by the client
manifest: true, // We need the manifest to detect SSR-only assets
outDir: getServerBuildDirectory(ctx),
rollupOptions: {
preserveEntrySignatures: "exports-only",
input: serverBuildId,
output: {
entryFileNames: ctx.remixConfig.serverBuildFile,
format: ctx.remixConfig.serverModuleFormat,
},
},
}),
},
}
: viteCommand === "serve" && ctx.remixConfig.unstable_ssr === false
? {
base: ctx.remixConfig.publicPath,
build: {
manifest: true,
outDir: getClientBuildDirectory(ctx.remixConfig),
},
}
: undefined),
};
},
async configResolved(resolvedViteConfig) {
Expand Down
14 changes: 11 additions & 3 deletions templates/spa/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,24 @@ npm run dev

## Production

When you are ready yo build a production version of your app, `npm run build` will generate your assets and an `index.html` for the SPA.
When you are ready to build a production version of your app, `npm run build` will generate your assets and an `index.html` for the SPA.

```shellscript
npm run build
```

You can serve this from any server of your choosing, for a simple example, you could use [http-server](https://www.npmjs.com/package/http-server):
Preview build locally with [vite preview](https://vitejs.dev/guide/cli#vite-preview) to serve all routes via the single `index.html` file. Do not use this as a production server as it's not designed for it:

```shellscript
npx http-server build/client/
npm run preview
```

You can serve this from any server of your choosing. The server should be configured to serve multiple paths from a single root `/index.html` file (commonly called "SPA fallback"). Other steps may be required if the host doesn't directly support this functionality.

For a simple example, you could use [sirv-cli](https://www.npmjs.com/package/sirv-cli):

```shellscript
npx sirv-cli build/client/ --single --ignores "^/assets/"
```

[remix-vite-docs]: https://remix.run/docs/en/main/future/vite
3 changes: 1 addition & 2 deletions templates/spa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
"build": "remix vite:build",
"dev": "remix vite:dev",
"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
"start": "http-server build/client/",
"preview": "vite preview",
"typecheck": "tsc"
},
"dependencies": {
"@remix-run/node": "*",
"@remix-run/react": "*",
"http-server": "^14.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down

0 comments on commit fff83ad

Please sign in to comment.