Closed zspecza closed 8 years ago
Hi, thanks for filling this issue.
Since this is trivial to do in React-land
I'm not very familiar with react, would you mind posting a link to their docs/examples about this? Thanks!
Can you test with the syntax provided on the docs: http://router.vuejs.org/en/advanced/lazy-loading.html?
const Foo = resolve => require(['./Foo.vue'], resolve)
I'm not very familiar with react, would you mind posting a link to their docs/examples about this? Thanks!
There are some docs for code-splitting / dynamic routes (by dynamic they mean lazy). There is also a section that mentions async routes on the server that I think describes the issue I'm running into with vue-router:
Server rendering works identically when using async routes. However, the client-side rendering needs to be a little different to make sure all of the async behavior has been resolved before the initial render, to avoid a mismatch between the server rendered and client rendered markup.
I think that bundling in JS per vue route using require
only on the server half fixes the problem, allowing renders to work but because of the async behavior not resolving in time, a mismatch occurs between the server and client-rendered markup.
Can you test with the syntax provided on the docs: http://router.vuejs.org/en/advanced/lazy-loading.html?
I've tested this syntax as well as require.ensure
, all 3 syntaxes behave in the same fashion.
I took a look at the docs you provided and it doesn't seem to be the case here. code-splitting / dynamic routes (by dynamic they mean lazy)
only happen on the client and async routes on the server
only happens on the server (and it also doesn't mean lazy loading, it's just async loading, like getting data before rendering a route). So I doubt it's trivial.
But navigating directly to /foo or /bar to trigger a server render crashes the app with "module 0.server-bundle.js not found".
I think if you can just solve this problem then everything will be fine. This means giving the server access to the chunked js bundle files (in this case 0.server-bundle.js
) created by webpack.
So I doubt it's trivial.
It is. The docs have changed since I last looked at them, but I've been able to accomplish this in many projects in no time at all following a similar approach to this article: https://medium.com/react-weekly/code-chunking-with-webpack-a-pragmatic-approach-e17e8bcc6453#.f51ppe4ja
(note: I've tried the require.ensure
shim seen in that article with vue-router
as well, and ran into the module not found error)
I think if you can just solve this problem then everything will be fine. This means giving the server access to the chunked js bundle files (in this case 0.server-bundle.js) created by webpack.
How, exactly? Shouldn't it be available on the server already? The only way I could think is to point to the ./dist/
folder instead of the root, but this seems overly complex - considering the server build does not output chunks to that folder in development mode - seems like they're served from in-memory (remember that I modelled the structure of the app after the HackerNews example)
It is. The docs have changed since I last looked at them, but I've been able to accomplish this in many projects in no time at all following a similar approach to this article: https://medium.com/react-weekly/code-chunking-with-webpack-a-pragmatic-approach-e17e8bcc6453#.f51ppe4ja
This link doesn't talk about server side rendering either, everything is running on the client side. I just googled about it, and I guess this is what you actually refered to: http://henleyedition.com/implicit-code-splitting-with-react-router-and-webpack/ It's basically the same approach compared to vue's, since it's all about configuring webpack and the rendering server and not about the framework itself. The problem here is that the webpack config in vue-hackernews-2.0 wasn't properly configured for isomorphic code splitting. I'll take a look and make a fork when I'm free.
Since it's not about vue-router, I'm closing this issue, but feel free to continue discussion here.
@fnlctrl the article you've linked to does not differ from the strategy I'm using - the use of bundle-loader
simply removes the boilerplate of having to write this statement out for each router-view
:
const Foo = BROWSER_BUILD ? () => System.import('../views/Foo.vue') : require('../views/Foo.vue')
Instead allowing you to just import '../views/Foo.vue
and get the same behavior. The downside to that approach is the inability to prevent the code from being chunked on the server (despite being loaded in synchronously as the article suggests, the module that is synchronously loaded in is just a module that asynchronously loads the actual chunk) which brings me back to the first problem: the server crashes because module [id].server-bundle.js not found
.
The System.import
vs require
depending on whether we're running on server or client works and the server does not crash, but Vue complains about hydration.
Following that article's instructions on a React project, everything works as expected.
I'm intrigued by your idea of making the chunk available to the server - but given that webpack is bundling the server as well, I'm confused as to why this isn't the case already :confused:
Lazy loading chunks that work in SSR is a valid and known use-case - What can we do to make it a little more straightforward? If you can point me in the right direction, I'm happy to help out.
EDIT: I have a lingering suspicion that this stems from the way the bundle renderer handles module dependencies in vue-server-renderer
- I'll be posting up a tiny example repo and will rehash the issue there. Thanks for attempting to help me, anyway. When/if I find anything I'll contribute a PR tovue-router
documenting how to accomplish this.
Hi @declandewet
I actually have the same error as you and trying to figure this out too. I will be happy if you found a way of fixing this issue 🔥
Hi @Atinux - Unfortunately I haven't found a solution, but I have found out a lot more info regarding the status of the issue - If you head over to https://github.com/vuejs/vue/projects/3, you'll see a card in the "Core" column that says:
Better support for Webpack code-splitting in SSR
According to the Github API endpoint for Vue's project cards, that card was added on October 17th.
There is also this post on the forums: http://forum.vuejs.org/t/vue-ssr-how-to-support-lazy-loading/1647
Blake from our core team is working on that, we hope to support than soon.
This indicates that a combination of SSR + code splitting is not yet supported in Vue, but will, at some point, be worked on.
In the meantime, here is a collection of my findings:
Ok you looked deep into it. I will try to find a way to do it, I'm actually working on a copy of next.js for vue. So I have to find a way of doing it while it's not implemented on Vue yet. I'll keep you informed of my progress!
Yes, I called it nuxt.js :)
https://github.com/Atinux/nuxt.js
2016-10-29 15:42 GMT+02:00 Declan de Wet notifications@github.com:
This next.js https://zeit.co/blog/next?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/vuejs/vue-router/issues/820#issuecomment-257092329, or mute the thread https://github.com/notifications/unsubscribe-auth/AA3OFGz-ttITSiSz79QsN_cARa9lCPhHks5q400_gaJpZM4Kd6v1 .
Hi @declandewet
I did it and it's working for vue-hackernews-2.0: https://github.com/Atinux/vue-hackernews-2.0-lazy
Live demo: https://vue-hn-lazy.now.sh
I'll let you check the code, if you have any question, I will be happy to answer them!
@Atinux this is awesome - great work! I think I understand the majority of what you've done here - if I have any questions I'll let you know. :smile: Thanks for your efforts. I think though that others might benefit from a Medium post - if you're interested in writing one? 😃
BTW, great job on vue-meta @declandewet I think I will add it to nuxt.js, I wanted to create a
component like they did for next.js, but vue-meta will do the job as well 🔥Thanks @Atinux - it's just a proof of concept right now, I'm sure there are tons of critical bugs - but vue-meta
is something I'm gonna be needing soon, so its definitely not a throwaway project :)
@Atinux borrowed your ideas in the app I'm using to test vue-meta
and it seems it fails to perform DOM updates on the client. Mind jumping in and helping me out? I'm a little stuck and I think you might know what the issue is :smile: This is the line causing the issue: https://github.com/declandewet/vue-meta/blob/7fe58438d88074c991579a452221aa377e29e056/src/client/updaters/updateTagAttributes.js#L10
EDIT: fixed it! https://github.com/declandewet/vue-meta/commit/a6b0148f88e1f9b3800e1c5af8cd5555163ceb4d
@declandewet I can't reproduce this issue, could you create an example so I can reproduce the issue on my side?
@Atinux it was just me being silly and referencing tag elements before they were loaded in the DOM, I fixed it some time ago. :)
Back on topic, I think we should raise an issue regarding the functions you're borrowing from vue-router
to enable isomorphic lazy loading.
I agree, I answer on the issue about lazy loading in vue-hackernews-2.0, Evan have seen it, let's see what he is thinking about and his team. I trust them to find an elegant way of doing it.
On Thursday, 3 November 2016, Declan de Wet notifications@github.com wrote:
@Atinux https://github.com/Atinux it was just me being silly and referencing tag elements before they were loaded in the DOM, I fixed it some time ago. :)
Back on topic, I think we should raise an issue regarding the functions you're borrowing from vue-router to enable isomorphic lazy loading.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/vuejs/vue-router/issues/820#issuecomment-258285500, or mute the thread https://github.com/notifications/unsubscribe-auth/AA3OFNa86QaKFca1tuYGZmWxSFOR30Z8ks5q6lfbgaJpZM4Kd6v1 .
@Atinux thanks!According to your demonstration, the code has been separated, but css(c.0 & c.1) still in js. i want to split them to c.0.css & c.1.css, you have a way?
Hi @wuchang1123
Do you have this config? https://github.com/Atinux/vue-hackernews-2.0-lazy/commit/01094366ccbd1075426dad2a8b6b401ea6748344
If so, the c.0.js and c.1.js should not have any embedded CSS.
@Atinux Yes, I tried, but it is all the css are concentrated, I look forward to is the case app.css, c.0.css, c.1.css
Actually I found no other solution with Webpack 😞
I you find one I'd love to see it!
@Atinux,thanks again
@Atinux I tried your solution of separate css and it works, THANKS a lot
Hey guys, I am experiencing a similar issue, SSR doesn't work with lazy-loaded components in vue-router. Rather than writing it all here, please check it in https://github.com/JeffreyWay/laravel-mix/issues/2245. @Atinux can you please check this? 🙏
I'd be grateful for any help.
I built off the HackerNews (Vue 2.0 SSR) example and modified the routes to be rendered out lazily:
src/router/index.js
When navigating directly to
/
, app loads fine. Clicking on the links to/foo
as well as/bar
works - the chunks for the respective routes are loaded in lazily as expected. But navigating directly to/foo
or/bar
to trigger a server render crashes the app with "module 0.server-bundle.js not found".I figured this might be my cue to prevent code splitting on the server, so I defined a constant via webpack in both client and server configs:
webpack.client.config.js
webpack.server.config.js
...Then modified the router file to look like this:
src/router/index.js
This worked. Server renders rendered the right UI components depending on the route, and renders on the client fetched lazy chunks as intended.
However, upon closer inspection, it seems that this little trick causes the HTML rendered by the server to mismatch the VNode tree created by the client - which prevents efficient hydration on the client, instead re-rendering the entire app, which is less than ideal 😛
I've tried to get help on Gitter as well as on the forum (http://forum.vuejs.org/t/2-0-help-needed-with-server-rendered-lazy-routes/906) but those avenues didn't get much attention.
Since this is trivial to do in React-land, I'm assuming this might be a bug.