-
Notifications
You must be signed in to change notification settings - Fork 42
File system routes #96
Changes from 5 commits
6eb544f
15e3388
572a77b
27f2f1f
b08c623
164f271
eda1862
bd4ee22
5688c70
b6e518c
f60440e
a83e367
222315d
92a3227
ca88c69
0d46331
11737bc
56b846a
7c81524
2e3357d
3911d61
94943b8
2b354a0
bab626b
18ba879
74ef009
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,14 @@ const pathToId = file => { | |
} | ||
|
||
module.exports = api => { | ||
let entryExists = false | ||
if (api.options.entry) { | ||
try { | ||
require.resolve(api.resolveBaseDir(api.options.entry)) | ||
entryExists = true | ||
} catch (err) {} | ||
} | ||
|
||
const enhanceAppFiles = [...api.enhanceAppFiles].map((filepath, index) => ({ | ||
id: `${pathToId(filepath)}_${index}`, | ||
filepath: slash(filepath) | ||
|
@@ -25,8 +33,6 @@ module.exports = api => { | |
import Vue from 'vue' | ||
import Meta from 'vue-meta' | ||
import Router from 'vue-router' | ||
// eslint-disable-next-line import/no-unresolved | ||
import _entry from '#app-entry' | ||
import { getRequireDefault } from '#app/utils' | ||
|
||
Vue.config.productionTip = false | ||
|
@@ -40,6 +46,10 @@ module.exports = api => { | |
tagIDKeyName: 'rhid' | ||
}) | ||
|
||
const _entry = ${ | ||
entryExists ? `getRequireDefault(require('#app-entry'))` : `{}` | ||
} | ||
|
||
const enhanceApp = getRequireDefault(require('#app/enhance-app')) | ||
|
||
${[...enhanceAppFiles] | ||
|
@@ -52,19 +62,13 @@ module.exports = api => { | |
|
||
export default context => { | ||
const entry = typeof _entry === 'function' ? _entry() : _entry | ||
let { router, extendRootOptions } = entry | ||
if (context) { | ||
context.entry = entry | ||
} | ||
|
||
if (__DEV__) { | ||
if (!router) { | ||
throw new Error('You must export "router" in entry file!') | ||
} | ||
} | ||
|
||
const rootOptions = { | ||
_isReamRoot: true | ||
_isReamRoot: true, | ||
router: entry.router | ||
} | ||
const getInitialDataContextFns = [ | ||
entry.getInitialDataContext | ||
|
@@ -75,7 +79,6 @@ module.exports = api => { | |
|
||
const event = new Vue() | ||
const enhanceContext = { | ||
router, | ||
rootOptions, | ||
entry, | ||
ssrContext: context, | ||
|
@@ -90,10 +93,6 @@ module.exports = api => { | |
|
||
enhanceApp(enhanceContext, context) | ||
|
||
if (extendRootOptions) { | ||
extendRootOptions(rootOptions) | ||
} | ||
|
||
${[...enhanceAppFiles] | ||
.map(file => | ||
` | ||
|
@@ -104,6 +103,24 @@ module.exports = api => { | |
) | ||
.join('\n')} | ||
|
||
if (entry.extendRootOptions) { | ||
entry.extendRootOptions(rootOptions) | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why after There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
const { router } = rootOptions | ||
|
||
if (__DEV__) { | ||
if (!router) { | ||
throw new Error(${JSON.stringify( | ||
`You must ${ | ||
api.options.fsRoutes | ||
? `create ${api.options.fsRoutes.path}/*.vue or ` | ||
: `` | ||
}export "router" in ${api.options.entry || `entry file`}!` | ||
)}) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm thinking about creating a default There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Thoughts? |
||
|
||
const app = new Vue(rootOptions) | ||
|
||
return { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Auto generates routes | ||
|
||
## How to use | ||
|
||
```bash | ||
git clone https://github.com/ream/ream.git | ||
``` | ||
|
||
Install dependencies: | ||
|
||
```bash | ||
cd examples/fs-routes | ||
yarn | ||
``` | ||
|
||
Run it: | ||
|
||
```bash | ||
# Start development server | ||
yarn dev | ||
|
||
# Start production server | ||
yarn build && yarn start | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"private": true, | ||
"name": "fs-routes", | ||
"scripts": { | ||
"dev": "ream dev", | ||
"start": "ream start", | ||
"build": "ream build" | ||
}, | ||
"dependencies": { | ||
"ream": "latest" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<template> | ||
<div>fs-routes example app.</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<template> | ||
<div> | ||
<h1>Item: {{ $route.params.item_id }}</h1> | ||
<router-view /> | ||
</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<template> | ||
<div>Images</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<template> | ||
<div>Info</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<template> | ||
<ul> | ||
<li><router-link to="/catalog/specials">Specials</router-link></li> | ||
<li v-for="item in items" :key="item"> | ||
Item: {{ item }} | ||
<router-link :to="`/catalog/${item}`">Info</router-link> | ||
<router-link :to="`/catalog/${item}/images`">Images</router-link> | ||
</li> | ||
</ul> | ||
</template> | ||
|
||
<script> | ||
export default { | ||
data () { | ||
return { | ||
items: [10, 20, 30] | ||
} | ||
} | ||
} | ||
</script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<template> | ||
<div>Special offers!</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<template> | ||
<ul> | ||
<li><router-link to="/about">About</router-link></li> | ||
<li><router-link to="/catalog">Catalog</router-link></li> | ||
<li><router-link to="/user">User</router-link></li> | ||
</ul> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<template> | ||
<div> | ||
<h1>User</h1> | ||
<router-link to="/user">Profile</router-link> | ||
<router-link to="/user/friends">Friends</router-link> | ||
<hr> | ||
<router-view /> | ||
</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<template> | ||
<div>Friends</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<template> | ||
<div>Profile</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const path = require('path') | ||
const fs = require('fs-extra') | ||
|
||
module.exports = { | ||
name: 'builtin:fs-routes', | ||
apply(api) { | ||
if ( | ||
api.options.fsRoutes && | ||
fs.existsSync(api.resolveBaseDir(api.options.fsRoutes.path)) | ||
) { | ||
api.enhanceAppFiles.add(path.join(__dirname, 'inject.js')) | ||
|
||
api.hooks.add('onPrepareFiles', async () => { | ||
await fs.writeFile( | ||
api.resolveOutDir('router.js'), | ||
await require('./router-template')(api, api.options.fsRoutes.path) | ||
) | ||
}) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import createRouter from '#out/router' // eslint-disable-line import/no-unresolved | ||
|
||
export default ({ rootOptions, ssrContext }) => { | ||
if (rootOptions.router) return | ||
|
||
rootOptions.router = createRouter(ssrContext) | ||
} |
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.