single-spa / single-spa-vue

a single-spa plugin for vue.js applications
MIT License
182 stars 42 forks source link

Vue 3 with router (vue-router 4) throws Navigation cancelled when navigating. #85

Closed Bornegrim closed 3 years ago

Bornegrim commented 3 years ago

Here is an example that reproduces the issue: GitHub repo.

The repo is created with Vue-CLI (vue create) and single-spa is added with (vue add single-spa).

To reproduce the issue:

  1. Start the application with npm run serve:standalone
  2. Navigate to the about page and press the browser back button.

Our team has been using single-spa in our application and recently started updating spas to Vue 3. During this upgrade, we have been facing some issues regarding routing. When you route using router-link or router.push the router navigates multiple times and throws this error:

Error: Navigation canceled from "/about" to "/about" with new navigation.
    at createRouterError (vue-router.esm-bundler.js?6c02:826)
    at checkCanceledNavigation (vue-router.esm-bundler.js?6c02:2908)
    at checkCanceledNavigationAndReject (vue-router.esm-bundler.js?6c02:3025)
    at eval (vue-router.esm-bundler.js?6c02:3362)

The error is printed by adding this code to the router config: Vue navigation failure docs

router.afterEach((to, from, failure) => {
  if (isNavigationFailure(failure)) {
    console.log('failed navigation', failure);
  }
});

The router navigates properly to the destination but when you use the browser back button (or router.go(-1)) the navigation stays on the same page without any errors. It changes the URL to where we want to go but it's not navigating back. It is possible to navigate backward by pressing the browser back button multiple times. If you navigate by typing the URL manually it works as expected.

If you create the app the same way (with Vue-CLI + vue add single-spa) but choose Vue 2 instead of Vue 3 it works as expected.

How do you integrate Vue 3 + Vue router with single-spa?

joeldenning commented 3 years ago

This sounds similar to https://github.com/single-spa/create-single-spa/issues/311. In that issue, I showed a workaround that involves modifying vue-router. I plan on submitting a pull request to vue-router to fix issues related to cancellation.

I'll take a look at your demonstration repo to see if it's the same issue.

joeldenning commented 3 years ago

I confirmed that the same workaround I described in #311 works for this case, too. I'll have to think more carefully about what the best approach is to fix, this, though. Not 100% sure if it's vue-router's fault or single-spa's fault.

joeldenning commented 3 years ago

I looked into this further and found a way to fix this without any need to modify vue-router. The bug only occurs when single-spa's urlRerouteOnly option is set to false. In single-spa@5, false is the default, but in single-spa@6 we've changed the default to true.

I've created https://github.com/Bornegrim/vue3-single-spa/pull/1 which I verified works in your demonstration repo.

To fix, you must ensure that single-spa's start() function is called with urlRerouteOnly set to true. There are three ways to do that.

  1. Upgrade to single-spa@6 (optional, just changes the default value of urlRerouteOnly)
  2. Modify your root config's start() call to be start({urlRerouteOnly: true})
  3. Upgrade to vue-cli-plugin-single-spa@3, which upgrades to standalone-single-spa-webpack-plugin@3 that changes standalone mode to set urlRerouteOnly to true by default.

Relevant links:

joeldenning commented 3 years ago

This is documented at https://github.com/single-spa/single-spa.js.org/pull/477

Kusou1 commented 2 years ago

i try modify to be start({urlRerouteOnly: true}),router-link is work, but router-view still not work,Any idea why?

miradnan commented 1 year ago

Thanks @joeldenning I spent a day on this issue. This finally helped getting through it.