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

Dynamic routes do not get generated with build #160

Closed
mdaffin opened this issue Apr 19, 2018 · 14 comments
Closed

Dynamic routes do not get generated with build #160

mdaffin opened this issue Apr 19, 2018 · 14 comments
Labels
version: next Planned to do or already included in the next(1.0.0) version

Comments

@mdaffin
Copy link
Contributor

mdaffin commented Apr 19, 2018

You have access to the route via .vuepress/enhanceApp.js and can add extra routes such as:

export default ({ Vue, router, options }) => {
  router.addRoutes([
    { path: '/test', redirect: '/' }
  ])
}

or

const Test = () => import("./Test");

export default ({ Vue, options, router }) => {
  router.addRoutes([
    { path: "/test", component: Test }
  ]);
};

And they work as expected when you run it is dev mode vurepress dev site. But when building the app vurepress build site the added routes do not get generated/prerendered, resulting in a 404 when trying to load the route for the first time.

As far as I can tell there is no other way to add routes to the generated list of routes which means that routes cannot be added dynamically via the site or themes.

@ycmjason
Copy link
Contributor

ycmjason commented Apr 20, 2018

Maybe try to use the config.nav or config.sidebar? Not sure if the pre rendering respects the manual routes from vue router.

@mdaffin
Copy link
Contributor Author

mdaffin commented Apr 20, 2018

Even it that works there are pages I want to be rendered (redirect links) that I do not want to appear in the sidebar or nav menu. We need a way to add extra routes through the config and via themes for this to work fully.

@yyx990803 yyx990803 added the type: enhancement Request to enhance an existing feature label Apr 20, 2018
@stickmy
Copy link
Contributor

stickmy commented Apr 23, 2018

util.js
Here, the router option is been created by new Router(), so this router option cannot add extra routes

@mdaffin
Copy link
Contributor Author

mdaffin commented Apr 23, 2018

@Bloss utils.js or app.js? Not that it matters both of them are client-side scripts and the problem is with the server-side prerendering.

There is no problem with adding new routes in the client-side applications - they work as expected when in dev or SPA mode. The problem is when you go to build the app the server-side it does not know about the extra routes and so does not prerender the pages. This results in a 404 when you first hit them (but then work if you navigate to them once in SPA mode).

@meteorlxy
Copy link
Member

meteorlxy commented Apr 28, 2018

According to the following code, what should be rendered is determined by the siteData.pages:

vuepress/lib/build.js

Lines 63 to 67 in f0b33e1

// render pages
console.log('Rendering static HTML...')
for (const page of options.siteData.pages) {
await renderPage(page)
}

The original routes file is generated from siteData.pages, too:

vuepress/lib/prepare.js

Lines 277 to 307 in f0b33e1

async function genRoutesFile ({ siteData: { pages }, sourceDir, pageFiles }) {
function genRoute ({ path: pagePath }, index) {
const file = pageFiles[index]
const filePath = path.resolve(sourceDir, file)
let code = `
{
path: ${JSON.stringify(pagePath)},
component: Theme,
beforeEnter: (to, from, next) => {
import(${JSON.stringify(filePath)}).then(comp => {
Vue.component(${JSON.stringify(fileToComponentName(file))}, comp.default)
next()
})
}
}`
if (/\/$/.test(pagePath)) {
code += `,{
path: ${JSON.stringify(pagePath + 'index.html')},
redirect: ${JSON.stringify(pagePath)}
}`
}
return code
}
return (
`import Theme from '@theme'\n` +
`export const routes = [${pages.map(genRoute).join(',')}\n]`
)
}

Although your add routes to router, the siteData.pages won't be aware of that, and no page will be generated. That's what causes this problem.

@meteorlxy
Copy link
Member

To make things clear:

Current routes flow is -
(1) source code
(2) prepare options
(3) generate temp routes from options
(4) load temp routes in app.js
(5) load enhanceApp which may modify routes
(6) import "enhanced" app.js in webpack entries.

In dev mode, everything is from (6) and works well.

In build mode, webapck compile from (6), and then use options from (2) to determine what should be rendered.

@david-trejo-ck
Copy link

david-trejo-ck commented May 15, 2018

@meteorlxy , not sure if this is what you meant, but when I tried this in enhanceApp.js, the new "page" still 404'd.

  const p = siteData.pages.find(({path}) => path === '/guide/assets.html')
  const c = {...p}
  c.path = '/guide/assets/index.html'
  siteData.pages.push(c)
  console.log('c', c)

  let r = router.options.routes.find(({path}) => path === '/guide/assets.html')
  const rNew = {...r}
  rNew.path = '/guide/assets/index.html'
  router.options.routes.push(rNew)
  console.log(rNew)

edit: i see now, you were pointing out the reason why this didn't work, nvm!

@meteorlxy
Copy link
Member

meteorlxy commented May 15, 2018

@david-trejo-ck

  1. siteData is for "read-only" purpose in enhanceApp.js, and editing on it has no effects.
  2. use router.addRoutes(routes) to add new routes on router instance (https://router.vuejs.org/en/api/router-instance.html#methods).

It will work in dev mode. For build mode, see the PR above.

edit: yes I was pointing out the reason, but your code is not correct and won't work even in dev mode

@ulivz ulivz added plugin scope and removed type: enhancement Request to enhance an existing feature labels May 21, 2018
@ulivz ulivz added version: next Planned to do or already included in the next(1.0.0) version and removed plugin scope labels Aug 20, 2018
@gcharang
Copy link

gcharang commented Apr 3, 2019

@meteorlxy Hello! I am using the Vuepress Next version: "vuepress": "^1.0.0-alpha.46"
Is there a way to deal with redirects using enhanceApp.js now?
Thank you.

@meteorlxy
Copy link
Member

@gcharang
Try vuepress-plugin-redirect

@gcharang
Copy link

gcharang commented Apr 4, 2019

@meteorlxy
Thanks for the reply. The plugin states that it "can redirect any page to its subpages"

i.e., /start-here/introduction.html can be redirected to /start-here/feature/introduction.html by setting feature in redirector.alternative

I am looking for a more general type of redirect.
Ex: old link: /intro/introduction.html
new link: /start-here/intro.html
I wasn't able to achieve this using the plugin - "vuepress-plugin-redirect"
any advice?

@shigma
Copy link
Collaborator

shigma commented Apr 4, 2019

@meteorlxy Thanks for your introduction, but @gcharang is right. 🤣

@gcharang I have been considering about supporting "a more general type of redirect" in vuepress-plugin-redirect but have not decided how to implement it. It will be really helpful if you can create a feature request for it.

@meteorlxy
Copy link
Member

@gcharang router.addRoutes may help, and you may need to use vuepress-plugin-dehyrate to avoid potential problems in build mode.

@gcharang
Copy link

gcharang commented Apr 4, 2019

@shigma I will be sure to add a feature request. Thank you!

@meteorlxy I tried using the "vuepress-plugin-dehydrate" plugin along with the router.addRoutes but it didn't help me. The page still had the same behavior: the url is redirected but the page is 404

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
version: next Planned to do or already included in the next(1.0.0) version
Projects
None yet
Development

No branches or pull requests

9 participants