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

Add support to avoid scroll position calculation on router push #2393

Open
index23 opened this issue Oct 22, 2024 · 8 comments
Open

Add support to avoid scroll position calculation on router push #2393

index23 opened this issue Oct 22, 2024 · 8 comments
Labels
enhancement New feature or request

Comments

@index23
Copy link

index23 commented Oct 22, 2024

What problem is this solving

Description

Vue Router currently calculates the scroll position on every router.push navigation by invoking the computeScrollPosition function, which accesses window.pageXOffset and window.pageYOffset. While this behavior is useful for maintaining scroll position, it triggers layout recalculations that can negatively impact performance, especially on low-powered devices.

Given that JavaScript applications built with Vue.js can run across a variety of platforms — from mobile phones to high-performance computers, embedded devices, and Smart TVs — it's essential to account for environments where layout-intensive operations can hinder the user experience.

Motivation

The layout calculation triggered by accessing scroll-related properties is particularly expensive on embedded devices and Smart TVs, where hardware constraints may limit performance. Reducing unnecessary layout operations is critical for ensuring smooth navigation and an optimal user experience on these platforms.

Applications on such devices couldn't use scroll behaviour at all and such feature is redudant for these platforms.

Currently, Vue Router does not offer a way to skip or control these scroll position calculations, resulting in performance overhead even when maintaining scroll position is unnecessary.

Proposed solution

We propose extending the Vue Router API with an option to disable scroll position calculations on navigation. This could be configured either globally or on a per-route basis, providing developers with more control over performance-critical scenarios.

const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollPositioning: {
    calculateScrollPosition: false, // Disable scroll position calculation
  },
});

This feature would ensure that developers working on performance-sensitive applications — especially for embedded systems or Smart TVs — can reduce the performance impact associated with layout recalculations.

Another alternative solution could be to add third parameter to push function to avoid scroll position computation, like it has the buildState function.

function push(to, data, calculateScrollPosition) {
    // Add to current entry the information of where we are going
    // as well as saving the current position
    const currentState = assign({},
    // use current history state to gracefully handle a wrong call to
    // history.replaceState
    // https://github.com/vuejs/vue-router-next/issues/366
    historyState.value, history.state, {
        forward: to,
        scroll: calculateScrollPosition ? computeScrollPosition() : {
           left:0,
           top: 0
        },
    });
    if ((process.env.NODE_ENV !== 'production') && !history.state) {
        warn(`history.state seems to have been manually replaced without preserving the necessary values. Make sure to preserve existing history state if you are manually calling history.replaceState:\n\n` +
            `history.replaceState(history.state, '', url)\n\n` +
            `You can find more information at https://next.router.vuejs.org/guide/migration/#usage-of-history-state.`);
    }
    changeLocation(currentState.current, currentState, true);
    const state = assign({}, buildState(currentLocation.value, to, null), { position: currentState.position + 1 }, data);
    changeLocation(to, state, false);
    currentLocation.value = to;
}

Describe alternatives you've considered

A workaround could be manually overriding the window.pageXOffset and window.pageYOffset properties to skip layout calculations. However, this approach, modifying window object, could be error prone in the context of entire applications.

Copy link
Member

posva commented Oct 22, 2024

What about not saving the position if no scrollBehavior is provided?

@posva posva added the enhancement New feature or request label Oct 22, 2024 — with Volta.net
@index23
Copy link
Author

index23 commented Oct 23, 2024

I am not sure if I understand how not to save the position, but I will try to answer. I've configured router with scrollBehaviour returning false, but same behaviour happens triggering computeScrollPosition execution.

createRouter({
  history: createWebHashHistory(),
  base: __dirname,
  scrollBehavior () {
    return false
  },
  routes: [
    {},
    // ...
  ]
})

@posva Did you mean this way?

@posva
Copy link
Member

posva commented Oct 23, 2024

No, I mean that if no scrollBehavior option is passed, the router could just not compute the scroll

@index23
Copy link
Author

index23 commented Oct 23, 2024

Ok, understand. This was my initial setup, without scrollBehaviour option, and in that case I've noticed computeScrollPosition execution. So this doesn't help.

@ferferga
Copy link

@index23 I think what @posva means is that, instead of adding a new scrollPositioning option, no computeScrollPosition is triggered if scrollBehaviour is undefined.

@index23
Copy link
Author

index23 commented Oct 25, 2024

@ferferga Thanks for clarification. Unfortunately same behaviour happens, computeScrollPosition triggers, even if scrollBehaviour is undefined.

@posva
Copy link
Member

posva commented Oct 25, 2024

it won't work until it's implemented, that's what I mean by "if no scrollBehavior option is passed, the router could ...". But it's okay, I was planning on implementing it this way already 😄

@index23
Copy link
Author

index23 commented Oct 25, 2024

After one more iteration it is absolutely clear. 😂 That's great, there is no need for API changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: 📆 Planned
Development

No branches or pull requests

3 participants