[Au2] Is anyone using router (not lite) in production?

Hi, after some initial doubts I’ve chosen au2 for a new project that started almost a year ago.
While the overall experience is surprisingly smooth (well, not that surprisingly after all, given how stable was au1), we’re worried about the router.
First of all, there are some major issues with load attribute - it basically doesn’t work even in the most basic scenario. I’ve filled the bug report, it’s been confirmed almost a year ago but is still not resolved.
Second, we’re experiencing some strange issues in the edge cases (very hard to reproduce) where the content of new route is rendered, but the old one is not removed yet - we end up having two views stacked together.

This makes me wonder whether anyone here uses the router (again, not lite) in the production?
Or is the router-lite a better way to go? We could probably plan switching the router if that is more stable; giving up a little of modularity for the stability of the solution

please advise :slight_smile:

I use the router-lite package for my routing needs as I don’t use any of the direct routing functionality or other features that come in the core @aurelia/router package. The @aurelia/router-lite router gets you functionality that is more akin to v1 routing or routing in other frameworks/libraries.

I can’t speak for the aforementioned issues, but I do know that the lite router is in good shape and there is a good chance you were probably not using direct routing anyways.

1 Like

I know of several projects that use the router successfully. As far as I know, the issues you’ve mentioned are resolved, but I’ll try and find some time this upcoming week to verify that.

1 Like

@dwaynecharrington thanks for the input on the router-lite. Will see how it goes with the router but either way it’s good to know there’s a safe plan B :slight_smile:

@jwx thank you, looking forward to it.
I’m afraid the duplicated content is still there, I’ve seen it myself one or two times in our app in the recent days, I’ll try to prioritize the investigation into it to provide you with a repro.
as for the other issue ( Router load attribute: broken when using id & parameters.bind · Issue #1902 · aurelia/aurelia · GitHub ) I’ve updated the repro code to use the beta 23 and the bug is still there.

You can check yourself here - Aurelia Recipes Completed (forked) - StackBlitz

1 Like

TL:DR :sweat_smile: Sorry @migajek no solution found yet, but a rather extended analysis of the route handling that caused the issue.

Curious to see what was happening, I’ve just started the StackBlitz environment.
I’ve opened the developer console, and one of the things mentioned is the loadloading deprecation/advise. It’s mentioned on each followed route.

Next step was to reproduce the error, indeed, simply by clicking one of the recipes. Error was triggered.

I’ve set a breakpoint on the error handling function (createUnresolvedinstructionsError, line 8171 atm) to see the stack.

On first break, like the error mentions, there is one route left to handle.

And for the stack at that time:

Checking the stack for possible issues, the location of the 100-iterations guard actually contains several TODO’s. @ devs, might be worth checking those?

Right. This initially broke on the error, so let’s see what we can figure out between a few of the do-while runs. :slight_smile:

Set a new breakpoint on the first line within the do-while loop, see previous screenshot for the actual line. Rerunning the application.
While rerunning, with this breakpoint in place, I noticed that the do-while was ended because this.matchedInstructions.length became 0 (as expected).

Now, let’s try the Beef Stroganoff (getting hungry :stuck_out_tongue: )

So first thing is to see what scope contains. No clue yet where to look… so just a screenshot.


Interesting part (little more to the bottom), is the routerInstruction. It’s not the same in one of the trees, but slightly different

So let’s see where the loop iteration ends and see what might be causing the issue.

  • local var matchedEndpoints starts with an empty array.
  • clearEndpoints is empty as well
  • hooked is empty array, so === false check fails.
  • Trying to step into the else-if actually kills the iframe! Bummer! (reproducable!) Let’s see if info can be retrieved.
  • Baking a tart this time. hooked is not true, and hooked !== this.matchedInstructions is false. So not going into the else if.
  • since this.matchedInstructions is [], the for loop is not run.
  • skipping and skippingWithMore are empty arrays too.
  • … leading to a quite explicit Todo: { // TODO: !!!!!! && !foundRoute.hasRemaining))
    foundRoute actually is undefined there, so might be “just” a cleanup issue?
  • the next part is actually run, because the route is unrestricted (according to data)
    image
  • the finalEndpoint() sets this.hasAllEndpoints to true, and handles some states
  • this.run() → this.entities is empty, this.running is set to true
  • this.hasAllEndpoints = true, so inside if. guardedUnload is undefined, so no promise.
  • Right, reaching the end of the first iteration. this.cancelled is false, no changedEndpoints
  • Another TODO here!
    TODO: Use a better solution here (by checking and waiting for relevant viewports
  • this.matchingInstructions is still empty, this.instructions is not. And ofc this.running still true.
  • clearEndpoints is an empty array, so no change to this.instructions.
  • And last line of the original do-while: changedEndpoints still not containing any data.
  • In the while check, the getInstructionsForScope(scope) still returns the original instruction.

Conclusion

Right, reaching a conclusion of this analysis :slight_smile:
No changes in next iterations - as expected. The instruction is still the same. Guard count ofc decreasing to 0 which in the end will trigger the error.

So, what is causing the actual issue? Some possible culprits:

  • this.processedInstructions still empty
  • this.matchedInstructions still empty
  • since the setNextContent is within the matchedInstructions for-loop, I think this is where the check actually fails.
  • with one step earlier, the local const clearEndpoints might also be improperly set

Without deep knowledge it is a bit hard to exactly pinpoint, or to find a solution. But I hope this analysis helps a bit.

2 Likes

Thanks for letting me know and updating the repro! I’ll look into this as soon as possible and report back.

1 Like

This is helpful, thanks!

1 Like

O, btw, you might have noticed already, but I did not do an analysis about the actual calling code. So although I doubt it, it can still be a matter of misconfiguration or perhaps a little road instead of the happy path.

If that is case, the code does need to be made more monkey-proof. So either way changes needed :wink: Looking forward to your changes and opinion.

Second, we’re experiencing some strange issues in the edge cases (very hard to reproduce) where the content of new route is rendered, but the old one is not removed yet - we end up having two views stacked together.

I have seen this as well, but switched to the router-lite and haven’t seen it happen since.

1 Like

The Aurelia 2 documentation references direct routing but I couldn’t find anything that defined what it is so I wasn’t sure what it meant other than implying that there was some form of indirect routing.

A deeper search came up with some unlinked documentation on routing that seems to define what it is:
(Direct Routing | aurelia-direct-router)

There is another mention in the source repository docs/user-docs/routing/direct-routing.md, but I don’t actually see this on the docs.aurelia.io site