Vue SSR / Vue-Router always rebuilds server [SOLVED]

I am trying to switch my front-end to VueJS because of SSR, but noticed that when I change a client file it always restarts the server, which is sub-optimal (I am running with NO_HMR=1)

Is this because of SSR? I am using the usual

akryum:vue-component
akryum:vue-ssr

I have two test projects with identical code, 1.9.3 and 1.10.2, and even when I only edit a client .vue file the server restarts.

I found other threads about similar behavior in the Rect category, but I don’t know if it related.

My package.json has the following defined, and all the code is in an imports folder

  "meteor": {
    "mainModule": {
      "client": "client/main.js",
      "server": "server/main.js"
    },
    "testModule": "tests/main.js"
  },

Any tips?

This is just a guess, as I’m not an expert in SSR right now. I don’t use it in my own projects, but I know @cloudspider might be able to add more info. I remember noticing the caution :warning: in the Meteor Vue SSR docs which make a good reminder that with SSR, there is no client really, everything happens on the server and is compiled for the client.

So to me it makes sense that the server would be watching your changes and restarting if needed, because with SSR your client files are “server files”. At least this is how I understand it.

So I don’t think you want any code in your client folder other than what is recommended to start your app in the docs:

Link to SSR docs

Thanks for your response. I had copied the structure from some demo. No code is in /imports/client. SSR works, ie. the page is fully hydrated upon first load.

What doesn’t work is the client/server separation of hot code reload. Wherever I make changes it restarts the server

I hadn’t noticed this before, but you’re right! I think it’s to do with the router - even routes which use dynamic import seem to trigger server re-builds.

Here’s what I tried to figure that out:

  • Edit client/main.js - the client refreshes but the server doesn’t get re-built, as expected.
  • Edit imports/ui/EditTeam.vue - this file is not included in any SSR, BUT the server is re-built!!
  • Remove the dynamically imported route from routes.js:
// { path: '/admin/team/:teamId', component: () => import('./EditTeam.vue'), props: true, meta: {auth: 'teamAdmin'}},
  • Edit imports/ui/EditTeam.vue again - server NOT rebuilt - success!

Actually, also ignore the NO_HMR=1 extra addition, this turns off HMR support…

For extra docs, make sure to read the vue-component docs: https://github.com/meteor-vue/vue-meteor/tree/master/packages/vue-component

This describes the ‘NO_HMR=1’ toggle… just leave that out. I guess we should have caught this in the Meteor Guide. I’ve ignored that for a while now, that was a config option, so should not be recommended to everyone. There was a tiny bug in Meteor 1.8 I think were this was helpful until the update was made.

Hey @cloudspider I think you are updating the Meteor Vue Guide now or soon. Could you remove the “NO_HMR=1” instruction from the updated guide? I think we want users to start out with HMR on since it’s the best dev experience. :sunglasses::tada:. I’m also now set up to edit the Guide & Meteor docs, so let me know if this is not on your agenda :+1:

1 Like

Are you saying you can’t use dynamic loading with vue-router?

You can use it, and I use it for all of my non-sales routes to minimise bundle size. It just seems that it triggers a server rebuild when you change one.

This was driving me absolutely crazy. So we are sure it is vue-router then?

I don’t think it’s vue-router’s fault, I think it’s a natural by-product of the dynamic import build process.

Routes, components or any .js file which is in the /client folder becomes part of the app.js client bundle, so if they change then only the client bundle needs to be re-built. The server doesn’t need to know about those at all.

However, any route, component or .js file which is dynamically imported needs to be available on the server so the client can fetch it when required. Therefore, changing any file which is dynamically imported will cause the server bundle to be re-built.

That’s my guess at what’s going on.

I think I have gotten a little closer. There is a .cache directory in my Meteor project, and every time I edit a file a new json file gets added to that directory, which would result in the server restarting.

According to vue-component I should be able to override the location of the .cache folder by setting BABEL_CACHE_DIR, which works, but the Meteor server still restarts when I edit a client file.

Meteor creates a list of all files that could be used when building the architecture, and adds them to the watch set. In some cases it can detect which files were unused and ignore them when checking for changes. A few ways this can be improved:

  • Allow disabling SSR in development by wrapping the code with if (Meteor.isProduction) and ignoring those imports when building for development
  • Skip restarting the server if only dynamic imports were modified, and they haven’t been imported.

@zodern I tried that, but it does not change the server restart issue.

Hi @zodern, how do you do that?

Sorry, I wasn’t clear. It was ideas on how we could change the meteor tool to work better in this situation. Right now the only option is to comment out or remove the dynamic imports so Meteor doesn’t see them when building the server and make sure the files are in imports.

I would recommend ‘not’ to use the vue-router2 package as described in the vue-meteor repo. Its quite dated. The normal vue-router should work.

Need to test some of the dynamic stuff. Been a while. I know the internals of vue-router, so I might be able to fix anything I would face

Absolutely correct, the vue-router2 only works on the client side, so it crashes with SSR enabled.

However, even without SSR the vue-router npm package somehow triggers the Meteor server process to restart with every change

That’s with dynamic imports? Or just normal ones as well? Need to reproduce

I tried it with both and it made not difference, but I have this in a live project I am working on and not in an isolated repro, so your mileage may vary. As @wildhart mentioned, he got it to work by “commenting out” a route, but I just don’t understand how I can work on a client side file if the route doesn’t work :wink:

Ok, I think I solved this. If the server imports the app.js it uses for SSR, then the server will restart, which in hindsight makes total sense.

Here is a github repo for my test

1 Like