Filesystem Routers & Indexes
Loading tweet…
Soon, Next.js will support FS-based routes, like
Sapper,
Nuxt.js,
and my own polydev
and mdx-site
.
But, there’s one design decision I’ve made that differs from the rest:
all routes are index
-based.
A lot of engineers work from the bottom up.
”I’ll connect to the DB, query for the data I need, expose it as an API, then wire it up to the HTML.”
But, I’ve found it more intuitive to work from the user down. (Because, ultimately, the implementation details don’t matter).
”I’ll create
/some/url
, hit an API, then return a query from the DB”.
Maybe we can call this approach 404
-driven-development.
Since Cool URIs don’t change, designing URL structure is good design.
The File system Looks Like a URL
Even when I git clone
a project, I have a habit of making the file system look like a URL.
For example, my ~/Projects
directory looks like my GitHub repos:
$ tree -L2
.
├── ericclemmons
│ ├── mdx-site
│ ├── medium-to-markdown
│ ├── node-recorder
│ ├── polydev
│ └── ...
├── webpack-contrib
│ └── npm-install-webpack-plugin
└── zeit
└── next.js
So it makes sense that projects like UmiJS
would find a way to map /users/:id
to the file system:
+ pages/
+ $post/
- index.js
- comments.js
+ users/
$id.js
- index.js
In my projects, however, I whitelist index.*
files for route creation.
Why Indexes Matter
For a small project, this seems fine:
pages/
index.js
about.js
contact-us.js
But, as complexity grows, you’ll find yourself with an underscore smell:
pages/
_app.js
_document.js
_layout.js
_fetchFromDB.js
...
index.js
about.js
contact-us.js
Because every file under pages/
automatically becomes a page,
we have to find ways to get these files blacklisted.
When designing URL structure upfront, a whitelist allows our app to grow without side effects.
For comparison, my suggested structure is:
pages/
index.js
about/
index.js
contact-us/
index.js
Benefits to Index-based Routes
-
Statically compiling
about/index.js
toabout/index.html
is well-supported by many static servers at the URL/about
. -
Dependencies of
index.js
can be called whatever you’d like, without accidentally generating new pages for each file. -
Customizing the extension allows for more functionality in the future:
-
post/:id/index.GET.js
could return/post/123
. -
post/:id/index.POST.js
could handle updating/post/123
’s content. -
post/:id/index.*.js
could be a fallback for/post/123/*
& show a custom404
page.
-
Of course, what people choose for denoting parameters (e.g. :
, []
, $
)
has to be a valid filename,
but the most important goal is to provide a quick, intuitive path from the URL in the browser to the file serving it.