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

vite: Enable use of vite preview to preview built SPA sites #8624

Merged
merged 6 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading