kiliman / remix-flat-routes

Remix package to define routes using the flat-routes convention
MIT License
695 stars 24 forks source link

Colocation is creating routes for directories #38

Open chuckstock opened 1 year ago

chuckstock commented 1 year ago

I have nested directories in my colocated routes folders that get included in my routes, but the other files do not. My assumption is they would be excluded from the routes created by remix-flat-routes, but they seem to become routes when I run npx remix routes.

Here is a small repo for reproduction https://github.com/chuckstock/remix-flat-routes-repro.

Here is the routes created from npx remix routes:

<Routes>
  <Route file="root.tsx">
    <Route index file="routes/_app._index/index.tsx" />
    <Route path="other" file="routes/_app.other/index.tsx">
      <Route path="components" file="routes/_app.other/components/index.tsx" />
    </Route>
  </Route>

I'm new to flat-routes so I'm sorry if this is just a misunderstanding on my part. But I assumed nested directories would be treated the same as nested files and be excluded for the routes created.

sdriffill-tm commented 11 months ago

I think the readme section hybrid routes covers why you'd be seeing this behaviour for deeply nested folders.

See the epic stack for a manual solution using a custom file name convention for ignored paths
e.g. double underscore prefix __note-editor.tsx and ignoring matches in remix config.js

Have not tested but I think with the above config applied you could rename your folder to routes/_app.other/__components and its contents would be excluded from route creation.

kiliman commented 11 months ago

With v2 routing, the entire route must be a single folder name, then the contents are colocated.

app/routes-colo
├── _app._index
│   └── index.tsx
└── _app.other
    ├── components
    │   └── index.tsx
    └── index.tsx

Remix v2 routes

Remix only sees _app.other as a route. Everything else is considered colocated.

<Routes>
  <Route file="root.tsx">
    <Route index file="routes/_app._index/index.tsx" />
    <Route path="other" file="routes/_app.other/index.tsx" />
  </Route>
</Routes>

remix-flat-routes hybrid routes

hybrid routes allow / in routes. Only the last segment is checked to see if it is colocated. It sees _app.other/components as another route because components/index.tsx is the last segment and treats it as colocated since it's a folder. So currently there's no way to have folders inside your colocated route.

<Routes>
  <Route file="root.tsx">
    <Route index file="routes-colo/_app._index/index.tsx" />
    <Route path="other" file="routes-colo/_app.other/index.tsx">
      <Route path="components" file="routes-colo/_app.other/components/index.tsx" />
    </Route>
  </Route>
</Routes>

The hard part is trying to encode different requirements based on simple file paths. Perhaps a naked / inside a route is not a desired feature. We also use the + suffix on hybrid routes to create a folder for organization instead of colocation. If we state that you must use the + suffix for internal folders, then a naked / will always denote colocation so you can have a nested components folder.

kiliman commented 11 months ago

Also, if you know you'll never use components as an actual route name, then you can ignore '**/components/*' in remix.config

module.exports = {
  ignoredRouteFiles: ['**/*'],
  routes: async defineRoutes => {
    return flatRoutes('routes', defineRoutes, {
      ignoredRouteFiles: ['**/components/*'],
      enableUniqueIdCheck: false,
    })
  },
}
<Routes>
  <Route file="root.tsx">
    <Route index file="routes-colo/_app._index/index.tsx" />
    <Route path="other" file="routes-colo/_app.other/index.tsx" />
  </Route>
</Routes>