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

Update docs regarding SPA Template ssr.noExternal setting #8957

Merged
merged 2 commits into from Mar 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 34 additions & 7 deletions docs/future/spa-mode.md
Expand Up @@ -222,14 +222,41 @@ startTransition(() => {

- You cannot call `serverLoader`/`serverAction` from your `clientLoader`/`clientAction` methods since there is no running server -- those will throw a runtime error if called

- It's important to note that Remix SPA mode generates your `index.html` file by performing a "pre-render" of your root route on the server during the build
### Server Build
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the bottom 2 more complex bullet points to sub headings to make them linkable and facilitate a code snippet


- This means that while you're creating a SPA, you still have a "server build" and "server render" step, so you do need to be careful about using dependencies that reference client-only aspects such as `document`, `window`, `localStorage`, etc.
- Generally speaking, the way to resolve these issues is to import any browser-only libraries from `entry.client.tsx` so they don't end up in the server build
- Otherwise, you can generally solve these by using [`React.lazy`][react-lazy] or the [`<ClientOnly>`][client-only] component from `remix-utils`
It's important to note that Remix SPA mode generates your `index.html` file by performing a "pre-render" of your root route on the server during the build

- The [SPA Mode template][spa-mode-template] enables the Vite [ssr.noExternal][vite-ssr-noexternal] option by default to automatically bundle all of your dependencies during the server build to avoid most ESM/CJS issues
- This may slow down your build a bit — if so, you can try removing this option, or switching to a more targeted array containing the specific dependencies you wish to bundle
- This means that while you're creating a SPA, you still have a "server build" and "server render" step, so you do need to be careful about using dependencies that reference client-only aspects such as `document`, `window`, `localStorage`, etc.
- Generally speaking, the way to resolve these issues is to import any browser-only libraries from `entry.client.tsx` so they don't end up in the server build
- Otherwise, you can generally solve these by using [`React.lazy`][react-lazy] or the [`<ClientOnly>`][client-only] component from `remix-utils`

### CJS/ESM Dependency Issues

If you are running into ESM/CJS issues with your app dependencies you may need to play with the Vite [ssr.noExternal][vite-ssr-noexternal] option to include certain dependencies in your server bundle:

```ts filename=vite.config.ts lines=[12-15]
import { vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
plugins: [
remix({
ssr: false,
}),
tsconfigPaths(),
],
ssr: {
// Bundle `problematic-dependency` into the server build
noExternal: ["problematic-dependency"],
},
// ...
});
```

These issues are usually due to dependencies whose published code is incorrectly-configured for CJS/ESM. By including the specific dependency in `ssr.noExternal`, Vite will bundle the dependency into the server build and can help avoid runtime import issues when running your server.

If you have the opposite use-case and you specifically want to keep dependencies external to the bundle, you can use the opposite [`ssr.external`][vite-ssr-external] option.

## Migrating from React Router

Expand Down Expand Up @@ -273,5 +300,5 @@ Once you've got all your routes living in their own files, you can:
[client-only]: https://github.com/sergiodxa/remix-utils?tab=readme-ov-file#clientonly
[vite-preview]: https://vitejs.dev/guide/cli#vite-preview
[sirv-cli]: https://www.npmjs.com/package/sirv-cli
[spa-mode-template]: https://github.com/remix-run/remix/tree/main/templates/spa
[vite-ssr-noexternal]: https://vitejs.dev/config/ssr-options#ssr-noexternal
[vite-ssr-external]: https://vitejs.dev/config/ssr-options#ssr-external