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

Add routes.ts support behind future flag #10107

Merged
merged 25 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a0d1526
Add support for `routes.ts`
markdalgleish Oct 14, 2024
003199f
Merge branch 'dev' into markdalgleish/routes-ts
markdalgleish Oct 14, 2024
87bf880
Clean paths for relative snapshot tests
markdalgleish Oct 14, 2024
c2bb8af
Force new page in Webkit integration tests
markdalgleish Oct 14, 2024
feb10d3
Revert
markdalgleish Oct 14, 2024
3a48dfe
Fix integration test in Webkit
markdalgleish Oct 14, 2024
c743f72
Move routes.ts API to `route-config` package
markdalgleish Oct 16, 2024
3c413ff
Add fs-routes package
markdalgleish Oct 16, 2024
7601e67
Add routes-option-adapter package
markdalgleish Oct 17, 2024
b755f79
Dedupe flat routes implementation
markdalgleish Oct 17, 2024
7b9806f
Add routes.ts docs to future flags guide
markdalgleish Oct 18, 2024
210d09e
Rename routes option adapter function
markdalgleish Oct 18, 2024
0cf86a0
Mention Vite requirement in docs
markdalgleish Oct 18, 2024
713d049
Reduce git diff
markdalgleish Oct 18, 2024
40509e0
Expand changeset, update docs
markdalgleish Oct 18, 2024
63eb78c
Fix tsconfig outdir
markdalgleish Oct 18, 2024
cf7c6d8
Remove unused minimatch dep
markdalgleish Oct 18, 2024
ec9aa74
Remove exports fields
markdalgleish Oct 18, 2024
a995410
Update docs/start/future-flags.md
markdalgleish Oct 18, 2024
143f140
Fix changeset typo
markdalgleish Oct 18, 2024
78f7634
Merge branch 'dev' into markdalgleish/routes-ts
markdalgleish Oct 18, 2024
122b7b0
Merge branch 'dev' into markdalgleish/routes-ts
markdalgleish Oct 28, 2024
72511f7
Add `v3_routeConfig` future flag
markdalgleish Oct 29, 2024
0df3455
Update package name in future flags guide
markdalgleish Oct 29, 2024
5f98394
Update changeset
markdalgleish Oct 29, 2024
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
29 changes: 29 additions & 0 deletions .changeset/popular-humans-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
"@remix-run/dev": minor
---

Add support for `routes.ts` behind `future.v3_routeConfig` flag to assist with the migration to React Router v7.

Config-based routing is the new default in React Router v7, configured via the `routes.ts` file in the app directory. Support for `routes.ts` and its related APIs in Remix are designed as a migration path to help minimize the number of changes required when moving your Remix project over to React Router v7. While some new packages have been introduced within the `@remix-run` scope, these new packages only exist to keep the code in `routes.ts` as similar as possible to the equivalent code for React Router v7.

When the `v3_routeConfig` future flag is enabled, Remix's built-in file system routing will be disabled and your project will opted into React Router v7's config-based routing.

To enable the flag, in your `vite.config.ts` file:

```ts
remix({
future: {
v3_routeConfig: true,
},
})
```

A minimal `routes.ts` file to support Remix's built-in file system routing looks like this:

```ts
// app/routes.ts
import { flatRoutes } from "@remix-run/fs-routes";
import type { RouteConfig } from "@remix-run/route-config";

export const routes: RouteConfig = flatRoutes();
```
148 changes: 148 additions & 0 deletions docs/start/future-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,153 @@ You shouldn't need to make any changes to your application code for this feature

You may find some usage for the new [`<Link discover>`][discover-prop] API if you wish to disable eager route discovery on certain links.

## v3_routeConfig

Config-based routing is the new default in React Router v7, configured via the `routes.ts` file in the app directory. Support for `routes.ts` and its related APIs in Remix are designed as a migration path to help minimize the number of changes required when moving your Remix project over to React Router v7. While some new packages have been introduced within the `@remix-run` scope, these new packages only exist to keep the code in `routes.ts` as similar as possible to the equivalent code for React Router v7.

When the `v3_routeConfig` future flag is enabled, Remix's built-in file system routing will be disabled and your project will opted into React Router v7's config-based routing. To opt back in to file system routing, this can be explicitly configured within `routes.ts` as we'll cover below.

**Update your code**

To migrate Remix's file system routing and route config to the equivalent setup in React Router v7, you can follow these steps:

👉 **Enable the Flag**

```ts filename=vite.config.ts
remix({
future: {
v3_routeConfig: true,
},
});
```

👉 **Install `@remix-run/route-config`**

This package matches the API of React Router v7's `@react-router/dev/routes`, making the React Router v7 migration as easy as possible.

```shellscript nonumber
npm install --dev @remix-run/route-config
```

This provides the core `RouteConfig` type as well as a set of helpers for configuring routes in code.

👉 **Add an `app/routes.ts` file without any configured routes**

```shellscript nonumber
touch app/routes.ts
```

```ts filename=app/routes.ts
import type { RouteConfig } from "@remix-run/route-config";

export const routes: RouteConfig = [];
```

This is a good way to check that your new `routes.ts` file is being picked up successfully. Your app should now be rendering a blank page since there aren't any routes defined yet.

👉 **Install `@remix-run/fs-routes` and use it in `routes.ts`**

```shellscript nonumber
npm install --dev @remix-run/fs-routes
```

This package matches the API of React Router v7's `@react-router/fs-routes`, making the React Router v7 migration as easy as possible.

> If you've configured `ignoredRouteFiles` to `["**/*"]`, you should skip this step since you're already opting out of Remix's file system routing.

```ts filename=app/routes.ts
import { flatRoutes } from "@remix-run/fs-routes";
import type { RouteConfig } from "@remix-run/route-config";

export const routes: RouteConfig = flatRoutes();
```

👉 **If you used the `routes` config option, add `@remix-run/routes-option-adapter` and use it in `routes.ts`**

Remix provides a mechanism for defining routes in code and plugging in alternative file system routing conventions, available via the `routes` option on the Vite plugin.

To make migration easier, an adapter package is available that converts Remix's `routes` option into React Router's `RouteConfig` array.

To get started, first install the adapter:

```shellscript nonumber
npm install --dev @remix-run/routes-option-adapter
```

This package matches the API of React Router v7's `@react-router/remix-routes-option-adapter`, making the React Router v7 migration as easy as possible.

Then, update your `routes.ts` file to use the adapter, passing the value of your `routes` option to the `remixRoutesOptionAdapter` function which will return an array of configured routes.

For example, if you were using the `routes` option to use an alternative file system routing implementation like [remix-flat-routes]:

```ts filename=app/routes.ts
import { type RouteConfig } from "@remix-run/route-config";
import { remixRoutesOptionAdapter } from "@remix-run/routes-option-adapter";
import { flatRoutes } from "remix-flat-routes";

export const routes: RouteConfig = remixRoutesOptionAdapter(
(defineRoutes) => flatRoutes("routes", defineRoutes)
);
```

Or, if you were using the `routes` option to define config-based routes:

```ts filename=app/routes.ts
import { flatRoutes } from "@remix-run/fs-routes";
import { type RouteConfig } from "@remix-run/route-config";
import { remixRoutesOptionAdapter } from "@remix-run/routes-option-adapter";

export const routes: RouteConfig = remixRoutesOptionAdapter(
(defineRoutes) => {
return defineRoutes((route) => {
route("/", "home/route.tsx", { index: true });
route("about", "about/route.tsx");
route("", "concerts/layout.tsx", () => {
route("trending", "concerts/trending.tsx");
route(":city", "concerts/city.tsx");
});
});
}
);
```

If you're defining config-based routes in this way, you might want to consider migrating to the new route config API since it's more streamlined while still being very similar to the old API. For example, the routes above would look like this:

```ts
import {
type RouteConfig,
route,
layout,
index,
} from "@remix-run/route-config";

export const routes: RouteConfig = [
index("home/route.tsx"),
route("about", "about/route.tsx"),
layout("concerts/layout.tsx", [
route("trending", "concerts/trending.tsx"),
route(":city", "concerts/city.tsx"),
]),
];
```

Note that if you need to mix and match different route config approaches, they can be merged together into a single array of routes. The `RouteConfig` type ensures that everything is still valid.

```ts
import { flatRoutes } from "@remix-run/fs-routes";
import type { RouteConfig } from "@remix-run/route-config";
import { route } from "@remix-run/route-config";
import { remixRoutesOptionAdapter } from "@remix-run/routes-option-adapter";

export const routes: RouteConfig = [
...(await flatRoutes({ rootDirectory: "fs-routes" })),

...(await remixRoutesOptionAdapter(/* ... */)),

route("/hello", "routes/hello.tsx"),
];
```

## unstable_optimizeDeps

Opt into automatic [dependency optimization][dependency-optimization] during development. This flag will remain in an "unstable" state until React Router v7 so you do not need to adopt this in your Remix v2 app prior to upgrading to React Router v7.
Expand All @@ -495,4 +642,5 @@ Opt into automatic [dependency optimization][dependency-optimization] during dev
[vite-url-imports]: https://vitejs.dev/guide/assets.html#explicit-url-imports
[mdx]: https://mdxjs.com
[mdx-rollup-plugin]: https://mdxjs.com/packages/rollup
[remix-flat-routes]: https://github.com/kiliman/remix-flat-routes
[dependency-optimization]: ../guides/dependency-optimization
3 changes: 3 additions & 0 deletions integration/helpers/node-template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
},
"devDependencies": {
"@remix-run/dev": "workspace:*",
"@remix-run/fs-routes": "workspace:*",
"@remix-run/route-config": "workspace:*",
"@remix-run/routes-option-adapter": "workspace:*",
"@vanilla-extract/css": "^1.10.0",
"@vanilla-extract/vite-plugin": "^3.9.2",
"@types/react": "^18.2.20",
Expand Down
1 change: 1 addition & 0 deletions integration/helpers/vite-template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"devDependencies": {
"@remix-run/dev": "workspace:*",
"@remix-run/eslint-config": "workspace:*",
"@remix-run/route-config": "workspace:*",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"eslint": "^8.38.0",
Expand Down
10 changes: 8 additions & 2 deletions integration/helpers/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,19 @@ export const viteConfig = {
`;
return text;
},
basic: async (args: { port: number; fsAllow?: string[] }) => {
basic: async (args: {
port: number;
fsAllow?: string[];
routeConfig?: boolean;
}) => {
return dedent`
import { vitePlugin as remix } from "@remix-run/dev";

export default {
${await viteConfig.server(args)}
plugins: [remix()]
plugins: [remix(${
args.routeConfig ? "{ future: { v3_routeConfig: true } }" : ""
})]
}
`;
},
Expand Down
Loading