-
Notifications
You must be signed in to change notification settings - Fork 42
Conversation
TODO: - Recursive routes - Dynamic routes - Update documentation - Make entry file optional
// Nuxt-compatible syntax: _item_id.vue | ||
// egoist suggested syntax: [item_id].vue | ||
return path.replace(/^_/, ':').replace(/\[(.*?)\]/g, ':$1') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer using [username].vue
syntax and ignoring paths starting with an underscore _
, when I was using Nuxt.js I always want to put some page-related components in pages
but don't know how to exclude them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. _*
and .*
are excluded, [username].vue
is the only supported syntax.
// catalog/index.vue -> /catalog | ||
// catalog/specials.vue -> /catalog/specials | ||
|
||
async function collectRoutes({ dir, componentPrefix, parentPath }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use fast-glob
to simplify this, and chokidar
to add watch functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with chokidar
, but I don't think fast-glob
will be simpler. The reasons being:
- non-uniform directory recursion (a directory may either generate child routes with cleared path prefix, or extend path prefix and append to the parent routes)
- per-directory sorting
app/create-app-template.js
Outdated
}export "router" in ${api.options.entry || `entry file`}!` | ||
)}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking about creating a default router
instance here if entry.router
is not provided, and use router.addRoutes
to add routes in the fs-routes
plugin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reworked it the way you described. One of the benefits it's that it's now possible to merge entry routes with fs routes (with former taking precedence).
However, it's now not possible to detect a misconfigured router in create-app-template.js
, as router doesn't expose the full set of routes (you can't rely on router.options.routes
as it only contains the initial set of routes and not the ones added by addRoutes
):
https://github.com/vuejs/vue-router/blob/4cb6699ecc4453a992429b28f32f4add3e2680b6/src/create-matcher.js#L171
Thoughts?
app/create-app-template.js
Outdated
require.resolve(api.resolveBaseDir(api.options.entry)) | ||
entryExists = true | ||
} catch (err) {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can use require.context
in the runtime code to check if there's entry file so that the app will be properly reloaded when you add an entry file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added hot reload for the entry with require.context
.
Since it requires string literals at compile time, the code is a bit verbose. I guess it could be moved into a reusable code generation function eventually (so the code becomes something like const _entry = ${importOptional(api.baseDir, api.options.entry)}
, but I'm not entirely sure where you'd like it to reside.
return `export default ${renderRoutes(routes)}` | ||
} | ||
|
||
function renderRoutes(routes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you have time, we can start adding some unit tests at lib/plugins/fs-routes/__test__/routes.test.js
using jest
, otherwise I'll do it later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@egoist I added tests.
a40e6b4
to
b6e518c
Compare
@egoist I addressed everything that you've mentioned. The only problem that I see is that we lost "You must export "router" in entry file!" message as it's not now possible to determine if router has any added routes or not. What I think is that in dev mode, for |
2865ef9
to
92a3227
Compare
Add regression test for empty pages dir.
OK so what bothers me is naming. fsRoutes: {
path: 'pages',
basePath: '/',
match: /\.(vue|js)$/i
} How can we distinguish between UPDATE: renamed as |
if (entry.extendRootOptions) { | ||
entry.extendRootOptions(rootOptions) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why after enhanceAppFiles
🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that user provided entry callback should be called last (to have chance to correct all previous plugin-imposed setup). This change is not needed for the PR. If you dislike it I can revert.
{__DEV__ && | ||
error.code === 404 && | ||
error.errorPath === '/' && ( | ||
<p>You must create pages/*.vue or export "router" in entry file!</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this message necessary? I mean it's obviously missing router
or pages
when there's 404 error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely not. Problem is, your original message from https://github.com/ream/ream/blob/a66d664477f4519b9d362893dd90c36d3184fe82/app/create-app-template.js#L62 is gone (as router is always instantiated), so I figured I would restore it somewhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also note that it's only printed for /
. In dev mode, this most probably means a misconfigured install.
@@ -49,6 +49,11 @@ class Ream extends Event { | |||
this.options = merge( | |||
{ | |||
entry: 'index.js', | |||
fsRoutes: { | |||
baseDir: 'pages', | |||
basePath: '/', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this the same thing as router.options.base
? maybe we can get it from the router
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so; router.options.base
is runtime and this basePath
is compile-time (it's imprinted in .ream/routes.js
). Unless we go with some routes post-processing in inject.js
it's not possible to achieve.
Also, I don't think it's really needed. The defaults are good for 95% use cases; for the rest additional flexibility wouldn't hurt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, from what I believe router.options.base
is automatically applied in runtime to all routes. So it's not the same thing. For example, I may set router.options.base
to /foo
and fsRoutes.baseDir
to /bar
and then pages/baz.vue
will open at /foo/bar/baz
.
It's weird that on your branch my computer runs out memory real fast.. Step to reproduce:
Errors: 2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
2018-06-14 21:24 node[4192] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21) It works fine on |
Hmmm yes I 5688c70 is the first bad commit (the |
OK, so it crashes because of this line: const context = require.context(
"/Users/semenov/work/github/patches/ream/examples/fs-routes",
false,
/^\\.\\/index\\.js$/
) Simply creating a webpack context (not even resolving it) makes it fail. Looks like it's specific to OS X, and happens when there's a lot of files in a directory. (Lots of similar reports: gruntjs/grunt-contrib-watch#75, expo/create-react-native-app#281, etc. etc.) It didn't happen to me before because I didn't use I tried upgrading everything with Unless there's some workaround, I guess the only options are either to disable the auto-discovery of the entry file, or make it required again. |
I reproduced the crash in a standalone project, with this: const context = require.context(
"/Users/semenov/work/github/patches/ream/examples/fs-routes",
false,
/^\.\/index\.js$/
)
setTimeout(() => {}, 2**30) this goes to
|
The problem only occurs when using Related webpack issue: webpack/watchpack#45 |
there's a dirty workaround: 😅 if there's an entry file, we create a file called |
I don't see how it's different from simply checking if the actual entry exists in What I'm thinking we may come up with a webpack resolver plugin which falls back unresolved |
I managed to create an Unfortunately, that does not directly solve the problem. Once it resolves to say |
@egoist I reworked entry file watching with chokidar. Do you think this is enough to merge? |
FWIW I believe we may also watch |
This PR fixes #68. It may look huge, but the most part of the PR is the new example directory and tests.
pages
, its contents will be used to construct a router. This router will be injected by a plugin into entry object._param.vue
or[param].vue
(or:param.vue
, although not on Windows).some.vue
andsome/
in the same directory. If there's onlysome/
, it also works, but adds prefixed routes to common list.pages/*.vue
(same as Nuxt). If entry is there, it is used. If there's no pages (and no router that came from entry), an exception will be thrown like it used to be (but better as it is more descriptive).pages
to something else, or change supported extensions. (I am also thinking about other options, e.g.trailingSlashes: true
, or a custom filter function.)I had to make some small changes in
create-app-template.js
to be able to allow plugins to override the router, and to make entry point optional, but most of the code went into a plugin.The default naming
pages
(notroutes
and notviews
) was chosen because I believe it reflects better what users are putting there — pages that will show on their site. (Routes are URL matching rules, and views are from MVC world where there are also controllers in front — withfsRoutes
, users don't create neither of these.)write-routes.js
is specifically made to be reusable. In my project, I need to have not one but two file system routers (for project.com and for app.project.com). It is now possible with a small ad-hoc plugin that callswrite-routes.js
twice.routes-template.js
is decoupled from Ream API for easier testing.