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

[✨] Critical DX/UX improvement to SPA navigation in Qwik City #3244

Merged
merged 5 commits into from Jun 6, 2023

Conversation

billykwok
Copy link
Contributor

@billykwok billykwok commented Mar 3, 2023

What is it?

  • Feature / Enhancement
  • Bug / Fixes
  • Docs / tests

Overview

This is a relatively straightforward change that addresses a number of interrelated issues around SPA navigation in Qwik City. Some are already mentioned in other issues (#2162, #2050, #3149, #2202, #2203), while some are newly reported here.

Support MPA-like and customizable scroll restoration in SPA

Before: Qwik City always scrolls to the top upon SPA navigation, unless there is a hash segment in the URL. This is not consistent with how browsers handle MPA scroll restoration on popstate and creates bad UX when users return to a page with a resetted scroll position. Moreover, the behavior is hard-coded into the Qwik City navigation logic, even though different applications have their own needs (e.g. app-like and page-like UIs should restore scroll positions differently).

After: The default behavior now mimics how browsers handle scroll restoration in MPA - scroll to the top for new pages (e.g. <Link />), but to the last-visited scroll position for popstate navigation (e.g. back/next button). Moreover, users can customize scroll restoration with the built-in scroll restorer toTopAlways and toLastPositionOnPopState or even their own implementation. The 'before' behavior is equivalent to toTopAlways.

Race condition when restoring scroll positions

Before: Scroll position is restored after the DOM is 'settled' in order to synchronize content update and scroll position update. However, the current implementation relies on a series of hard-coded setTimeout(), which very often results in either early scrolling or late scrolling.

After: 'DOM Settled' is accurately detected using useLocation() and useVisibleTask$(). Scroll and content updates are now always in-sync.

Prevent full-page reload when popstate happens before manual navigation

Before: Qwik City registers a temporary popstate event listener to reload the page if there is any popstate navigation before the first pushState is called. This essentially turns all SPAs into MPA whenever users refresh the page. This also makes page navigation inconsistent before and after the first pushState. In addition, there are unnecessary popstate listener registration/unregistration, because the temporary listener will be replaced by a real listener anyway after the first pushState.

After: Instead of a temporary popstate listener that does full-page refreshes, Qwik City now directly sets up the real popstate listener that updates the page without full-page refreshes.

  • This makes Qwik City consistent with all other SPA frameworks in the market.
  • This also makes page transition animation across 'popstate' possible.

Improve hash navigations

Before: Hash navigation is neither updating the URL hash nor written into the session history. The 'hashchange' event is also never fired.

After: The new behavior now mimics native behavior - clicking <a href="#some-hash" /> now updates the page URL hash without triggering unnecessary re-rendering. It also gets written into session history like what browsers would natively do. The 'hashchange' event is also fired.

Backward-compatible API Changes

const navigate = useNavigate();
// New signature that accepts an options object
type Options = { type: 'form' | 'link' | 'popstate'; forceReload: boolean; };
const defaultOptions: Options = { type: 'link', forceReload: false };
navigate('/some/pathname', defaultOptions);

// Old signature still works
navigate('/some/pathname', true /* equivalent { forceReload: true } */);
navigate('/some/pathname', false /* equivalent { forceReload: false } */);
import {
  QwikCityProvider,
  RouterOutlet,
  ServiceWorkerRegister,
  toTopAlways
} from '@builder.io/qwik-city';
import { RouterHead } from './components/router-head/router-head';

export default function Root() {
  return (
    <QwikCityProvider>
      <head>
        <meta charSet="utf-8" />
        <link rel="manifest" href="/manifest.json" />
        <RouterHead />
      </head>
      <body>
        //            ⬇️ New (optional): toTopAlways or toLastPositionOnPopState (default)
        <RouterOutlet restoreScroll$={toTopAlways} />
        <ServiceWorkerRegister />
      </body>
    </QwikCityProvider>
  );
}

Demo

Scroll restoration after popstate

Before the change:

  • always to the top
CleanShot.2023-03-18.at.01.07.05.mp4

After the change:

  • scroll to the last-visited positions
CleanShot.2023-03-18.at.00.57.29.mp4

popstate after reload

Before the change:

  • full-page reload the second time
CleanShot.2023-03-18.at.01.07.49.mp4

After the change:

  • re-rendering
CleanShot.2023-03-18.at.01.38.36.mp4

Checklist

  • My code follows the developer guidelines of this project
  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • Added new tests to cover the fix / functionality

@stackblitz
Copy link

stackblitz bot commented Mar 3, 2023

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@billykwok billykwok force-pushed the scroll-restoration branch 2 times, most recently from 830e7f6 to e36e111 Compare March 3, 2023 09:39
@zanettin
Copy link
Collaborator

zanettin commented Mar 3, 2023

Hi @billykwok 👋 thank you very much for creating this PR 🙏

I just have a question based on the description:

Currently, pages are always scrolled to the top (or hashed element if specified in URLs) upon navigation. While this makes sense for -triggered navigation, popstate-triggered navigation fails to restore previous scroll positions. This does not match the native behavior of browsers nor that of competing frameworks.

you mention, that the restore for MPA (popstate) navigations does not work atm, which i can't confirm so far. At least not on the available browsers 😄 The <Link> component driven navigations are the SPA (pushstate) ones which you also show in the video.

MPA navigation scroll position restore

Mar-03-2023.13-13-31.mp4

Is the description wrong in that case or do i miss something? 👼
Thanks again for your time and contribution 🙏

@zanettin zanettin added STATUS-2: waiting for an answer Further information is requested COMP: qwik-city labels Mar 3, 2023
@billykwok
Copy link
Contributor Author

billykwok commented Mar 3, 2023

Thanks for checking out my change. It is intended for SPA scrolling only. When I said popstate, I was referring to popstate navigation in SPA (e.g. same-page re-rendering due to pressing back button after pushState). MPA does not need manual scroll restoration because browsers handle it by default. Hope this clarifies the change.

@zanettin zanettin removed the STATUS-2: waiting for an answer Further information is requested label Mar 3, 2023
@billykwok billykwok force-pushed the scroll-restoration branch 4 times, most recently from c16c48a to f22793c Compare March 6, 2023 03:38
@billykwok billykwok changed the title feat(qwik-city): support scroll restoration feat(qwik-city): support proper scroll restoration Mar 6, 2023
@billykwok billykwok marked this pull request as draft March 8, 2023 17:45
@billykwok billykwok changed the title feat(qwik-city): support proper scroll restoration feat(qwik-city): support advanced scroll restoration and navigation events Mar 8, 2023
@billykwok
Copy link
Contributor Author

Converted to draft for now as I found a new way to implement the change that is more flexible and robust.
Will update it with the new implementation in the coming days.

@billykwok billykwok force-pushed the scroll-restoration branch 11 times, most recently from 74ab896 to 5c68954 Compare March 16, 2023 04:15
@billykwok billykwok force-pushed the scroll-restoration branch 2 times, most recently from 044ac09 to bcda354 Compare April 24, 2023 08:50
@billykwok
Copy link
Contributor Author

billykwok commented Apr 24, 2023

I just pushed an update to address all of the comments so far.

  • There is now an even simpler way to detect DOM settlement accurately based on just useLocation() and useVisibleTask$(). The MutationObserver is no longer there.
  • The hash issue mentioned in feat: View Transition API #3691 is now addressed.
  • I removed the proposed 'qinit'/'qsettled' event API to reduce the scope.

@manucorporat Thank you for spending time looking at it previously. Hope you manage to squeeze some time on it again.

…change' navigations in SPAs

- Support MPA-like and customizable scroll restoration in SPA
- Race condition when restoring scroll positions
- Prevent full-page reload when popstate happens before manual navigation
- Fix hash navigation in SPA
@manucorporat
Copy link
Contributor

I want to merge this PR, but there are so problems, the thing i am more against is the usage of useVisibleTask and useWindowOn() in RouterOutlet, right now, QwikCity apps download no js, adding this changes the baseline, which affects demos and simple apps.

@billykwok
Copy link
Contributor Author

billykwok commented May 9, 2023

Thanks for following up. I appreciate the pursuit of avoiding the initial JS load at all costs. However, there is probably no simple way to achieve the intended result of this PR with Qwik's current design/APIs.

While I agree that the current implementation may not fully align with Qwik's vision, the UX issues in scroll restoration mentioned in the original post should still be fixed ASAP. It is not desirable and hurts adoption if this is left hanging. There might be some clever tricks that I'm not aware of (perhaps through some unknown internal APIs). Unfortunately, I've decided to move on from this.

For the hard refresh issue specifically, it may not be that big of a concern after all. Since Qwik embraces and optimizes for MPA more than most JS frameworks (except Astro), maybe triggering a hard page refresh on popstate is acceptable for most Qwik adopters (unfortunately I am not among this crowd).

Qwik has introduced so many innovative solutions to improve the initial page load experience, and it has so much potential IMO. I am happy to revisit it one day when it is more compatible with SPA. But until then, if someone cares enough about the SPA Scrolling UX in Qwik and has a solution that fits into Qwik's vision, please feel free to pick this up and fix it once and for all.

I am closing this PR for now. Thank everyone who has put time into it.

@billykwok billykwok closed this May 9, 2023
@manucorporat manucorporat reopened this May 9, 2023
@manucorporat
Copy link
Contributor

Hey! actually i am working on it, i think it's possible

@manucorporat
Copy link
Contributor

We will get it merged!

@manucorporat
Copy link
Contributor

Just pushed a bunch of changes! can you review and get your thoughts? @billykwok

@manucorporat
Copy link
Contributor

Do you think we could merge and iterate, seems like this PR would fix some issues + add a cool feature, what if we leave for a second PR:

  • Fix flickering
  • Fix the popstate (very tricky one)

@manucorporat
Copy link
Contributor

This PR tried to do many things at the same time and it makes it very hard to merge, might be a good moment to merge and iterate

@manucorporat
Copy link
Contributor

let me try to find him in discord!

@manucorporat manucorporat merged commit 3daee3d into QwikDev:main Jun 6, 2023
22 checks passed
@manucorporat
Copy link
Contributor

Let's do it! merged this for the 1.2.0 window! cc @jordanw66

@thejackshelton
Copy link
Member

thejackshelton commented Jun 6, 2023

@billykwok @jordanw66 @manucorporat this is INCREDIBLE. Thank you guys so much for the contributions!!

kodiakhq bot pushed a commit to ascorbic/unpic-img that referenced this pull request Jul 9, 2023
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@builder.io/qwik](https://qwik.builder.io/) ([source](https://togithub.com/BuilderIO/qwik)) | [`1.1.5` -> `1.2.6`](https://renovatebot.com/diffs/npm/@builder.io%2fqwik/1.1.5/1.2.6) | [![age](https://badges.renovateapi.com/packages/npm/@builder.io%2fqwik/1.2.6/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@builder.io%2fqwik/1.2.6/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@builder.io%2fqwik/1.2.6/compatibility-slim/1.1.5)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@builder.io%2fqwik/1.2.6/confidence-slim/1.1.5)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>BuilderIO/qwik (@&#8203;builder.io/qwik)</summary>

### [`v1.2.6`](https://togithub.com/BuilderIO/qwik/releases/tag/v1.2.6)

[Compare Source](https://togithub.com/BuilderIO/qwik/compare/v1.2.5...v1.2.6)

##### What's Changed

-   feat(server-functions): routeAction$ validation based on RequestEvent by [@&#8203;tzdesign](https://togithub.com/tzdesign) in [QwikDev/qwik#4727
-   fix: visual cms starter by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4731
-   feat: add jokes by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4734
-   docs: fix example in Best Practices Guide by [@&#8203;octoper](https://togithub.com/octoper) in [QwikDev/qwik#4733
-   fix: force spa-init into client symbols in dev builds by [@&#8203;jordanw66](https://togithub.com/jordanw66) in [QwikDev/qwik#4738
-   fix: cli accept empty folder by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4740
-   fix: configure jsx import by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4741
-   chore: update deps by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4742
-   fix: case for images by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4744
-   1.2.6 by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4743

##### New Contributors

-   [@&#8203;octoper](https://togithub.com/octoper) made their first contribution in [QwikDev/qwik#4733

**Full Changelog**: QwikDev/qwik@v1.2.5...v1.2.6

### [`v1.2.5`](https://togithub.com/BuilderIO/qwik/releases/tag/v1.2.5)

[Compare Source](https://togithub.com/BuilderIO/qwik/compare/v1.2.4...v1.2.5)

#### What's Changed

-   Insights by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4707
-   docs(cart): remove padding-left from cart overlay by [@&#8203;gioboa](https://togithub.com/gioboa) in [QwikDev/qwik#4705
-   docs: correct the capture index for qrl by [@&#8203;wtlin1228](https://togithub.com/wtlin1228) in [QwikDev/qwik#4706
-   fix: add .pnpm-store to .prettierignore by [@&#8203;jordanw66](https://togithub.com/jordanw66) in [QwikDev/qwik#4710
-   docs: add route handler menu + ecpsystem case studies  by [@&#8203;hamatoyogi](https://togithub.com/hamatoyogi) in [QwikDev/qwik#4713
-   fix(aws): bundle all without express by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4691
-   fix: multiple cookies in azure by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4716
-   fix: vite csr mode by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4719
-   fix: clear attribute when undefined by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4721
-   docs: fixed typo in labs index.mdx by [@&#8203;Craiqser](https://togithub.com/Craiqser) in [QwikDev/qwik#4573
-   fix: routes plugins with tsx by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4726
-   fix: update pandacss dep by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4725
-   1.2.5 by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4729
-   fix(vite): \n escaping in  vite plugin by [@&#8203;FlatMapIO](https://togithub.com/FlatMapIO) in [QwikDev/qwik#4730

**Full Changelog**: QwikDev/qwik@v1.2.4...v1.2.5

### [`v1.2.4`](https://togithub.com/BuilderIO/qwik/releases/tag/v1.2.4)

[Compare Source](https://togithub.com/BuilderIO/qwik/compare/v1.2.3...v1.2.4)

##### What's Changed

-   fix(eslint): useMethod rule for regular functions by [@&#8203;shairez](https://togithub.com/shairez) in [QwikDev/qwik#4666
-   fix: typo by [@&#8203;yaikohi](https://togithub.com/yaikohi) in [QwikDev/qwik#4655
-   fix: the property parameter can be symbol by [@&#8203;wtlin1228](https://togithub.com/wtlin1228) in [QwikDev/qwik#4668
-   docs css: fix shop cart floating button by [@&#8203;gioboa](https://togithub.com/gioboa) in [QwikDev/qwik#4669
-   shop: added colors to icons and small changes by [@&#8203;the-r3aper7](https://togithub.com/the-r3aper7) in [QwikDev/qwik#4670
-   doc: optional font by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4672
-   fix: image tools improvements by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4671
-   perf: preload css fonts by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4673
-   chore: update deps by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4674
-   fix(optimizer): ssr transform for rollup by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4675
-   fix: add loc to symbol manifest by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4676
-   fix: add crossorigin attribute by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4677
-   docs(request-handling): cookie has method by [@&#8203;tzdesign](https://togithub.com/tzdesign) in [QwikDev/qwik#4632
-   feat(labs): add clustering to symbols by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4648
-   fix: inlined signals in library mode by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4684
-   fix: always try relative path for mapped hooks by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4686
-   fix: configurable getOrigin for node servers by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4687
-   fix: staticFile() api in node middleware by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4693
-   fix(entry.deno.ts): fix wrong parameters by [@&#8203;arkhvoid](https://togithub.com/arkhvoid) in [QwikDev/qwik#4696
-   fix: migrate to modern Deno Server by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4697
-   fix: add vanilla node server by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4699
-   1.2.4 by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4690
-   docs(mdx): fixed path to counter component by [@&#8203;YannickFricke](https://togithub.com/YannickFricke) in [QwikDev/qwik#4680
-   chore: add aws badge by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4703
-   chore: fix \n is pure text in console by [@&#8203;minsoo-web](https://togithub.com/minsoo-web) in [QwikDev/qwik#4700
-   fix: PROTOCOL and HOST header are case insensitive by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4704

##### New Contributors

-   [@&#8203;yaikohi](https://togithub.com/yaikohi) made their first contribution in [QwikDev/qwik#4655
-   [@&#8203;tzdesign](https://togithub.com/tzdesign) made their first contribution in [QwikDev/qwik#4632
-   [@&#8203;arkhvoid](https://togithub.com/arkhvoid) made their first contribution in [QwikDev/qwik#4696
-   [@&#8203;YannickFricke](https://togithub.com/YannickFricke) made their first contribution in [QwikDev/qwik#4680
-   [@&#8203;minsoo-web](https://togithub.com/minsoo-web) made their first contribution in [QwikDev/qwik#4700

**Full Changelog**: QwikDev/qwik@v1.2.3...v1.2.4

### [`v1.2.3`](https://togithub.com/BuilderIO/qwik/releases/tag/v1.2.3)

[Compare Source](https://togithub.com/BuilderIO/qwik/compare/v1.2.2...v1.2.3)

#### What's Changed

-   docs(utilities): adding documentation for the `new` cli command  by [@&#8203;thejackshelton](https://togithub.com/thejackshelton) in [QwikDev/qwik#4649
-   docs: aws lambda documentation by [@&#8203;leifermendez](https://togithub.com/leifermendez) in [QwikDev/qwik#4642
-   fix: server$ error when request is closed by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4653
-   docs: resumable by [@&#8203;aboudard](https://togithub.com/aboudard) in [QwikDev/qwik#2780
-   fix: add dependencies to pkg by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4656
-   fix: navigation crash with plugins by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4657
-   fix: unit test jsx image by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4660
-   docs: ecosystem improvements by [@&#8203;the-r3aper7](https://togithub.com/the-r3aper7) in [QwikDev/qwik#4659
-   fix(slot): rendering variable slot projection by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4661
-   fix: svg rendering + test by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4663
-   1.2.3 by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4662

#### New Contributors

-   [@&#8203;aboudard](https://togithub.com/aboudard) made their first contribution in [QwikDev/qwik#2780

**Full Changelog**: QwikDev/qwik@v1.2.2...v1.2.3

### [`v1.2.2`](https://togithub.com/BuilderIO/qwik/releases/tag/v1.2.2)

[Compare Source](https://togithub.com/BuilderIO/qwik/compare/v1.2.1...v1.2.2)

#### What's Changed

-   fix: csstypes dep by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4644
-   feat(qwik): encode the manifest hash into the container. by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4647

**Full Changelog**: QwikDev/qwik@v1.2.1...v1.2.2

### [`v1.2.1`](https://togithub.com/BuilderIO/qwik/releases/tag/v1.2.1)

[Compare Source](https://togithub.com/BuilderIO/qwik/compare/v1.2.0...v1.2.1)

#### What's Changed

-   docs header: add shop link by [@&#8203;gioboa](https://togithub.com/gioboa) in [QwikDev/qwik#4641
-   fix: tailwind integration by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4640

**Full Changelog**: QwikDev/qwik@v1.2.0...v1.2.1

### [`v1.2.0`](https://togithub.com/BuilderIO/qwik/releases/tag/v1.2.0)

[Compare Source](https://togithub.com/BuilderIO/qwik/compare/v1.1.5...v1.2.0)

##### What's Changed

-   docs: fix link to `speculative-module-fetching` by [@&#8203;Craiqser](https://togithub.com/Craiqser) in [QwikDev/qwik#4421
-   fix: use levenshtein distance to provide even better 404 by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4389
-   feat: serialize support for Set and Map by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4375
-   \[✨] Critical DX/UX improvement to SPA navigation in Qwik City by [@&#8203;billykwok](https://togithub.com/billykwok) in [QwikDev/qwik#3244
-   docs: add CodeSandbox demo to Modular Forms guide by [@&#8203;fabian-hiller](https://togithub.com/fabian-hiller) in [QwikDev/qwik#4095
-   docs: fix link to `Bundle Optimization` by [@&#8203;Craiqser](https://togithub.com/Craiqser) in [QwikDev/qwik#4418
-   feat: image performance dev tools by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4424
-   fix: slow test by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4431
-   docs: qwiksand-box by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4429
-   fix: image-size dep by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4435
-   docs: fix example to match by [@&#8203;hamatoyogi](https://togithub.com/hamatoyogi) in [QwikDev/qwik#4439
-   chore: remove unused starter file by [@&#8203;adamdbradley](https://togithub.com/adamdbradley) in [QwikDev/qwik#4446
-   fix: set qwik builder counter initial value by [@&#8203;adamdbradley](https://togithub.com/adamdbradley) in [QwikDev/qwik#4449
-   fix: cli background install by [@&#8203;adamdbradley](https://togithub.com/adamdbradley) in [QwikDev/qwik#4450
-   feat: client info API by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4433
-   fix: jsx rendering order by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4458
-   Reorganize .gitignore by [@&#8203;szepeviktor](https://togithub.com/szepeviktor) in [QwikDev/qwik#4456
-   docs: Routing - Change getLocation() to useLocation() by [@&#8203;chsanch](https://togithub.com/chsanch) in [QwikDev/qwik#4454
-   fix: visible task execution after removal by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4459
-   Fix typo in MDX example code by [@&#8203;erikras](https://togithub.com/erikras) in [QwikDev/qwik#4457
-   feat(adapter): aws starter adapter by [@&#8203;leifermendez](https://togithub.com/leifermendez) in [QwikDev/qwik#4390
-   fix(use-on.ts): fixed useOn methods to pass correct eventName to \_useOn by [@&#8203;OrenSayag](https://togithub.com/OrenSayag) in [QwikDev/qwik#4453
-   docs: routeLoader adjustment by [@&#8203;hamatoyogi](https://togithub.com/hamatoyogi) in [QwikDev/qwik#4462
-   fix: root gitignore file by [@&#8203;zanettin](https://togithub.com/zanettin) in [QwikDev/qwik#4460
-   fix: add missing nonce to popstate script by [@&#8203;DustinJSilk](https://togithub.com/DustinJSilk) in [QwikDev/qwik#4468
-   feat: CLI option `new` by [@&#8203;zanettin](https://togithub.com/zanettin) in [QwikDev/qwik#4273
-   Include a woman in the "community" emoji by [@&#8203;erikras](https://togithub.com/erikras) in [QwikDev/qwik#4471
-   docs: Update the middleware / endpoint documentation by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4442
-   fix: prefetch urls with different search queries by [@&#8203;DustinJSilk](https://togithub.com/DustinJSilk) in [QwikDev/qwik#4474
-   refactor: improve DX of "qwik new" by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4472
-   fix: bundling for testing by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4475
-   feat: image vite transform by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4479
-   refactor: containerState for appendHeadStyle by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4478
-   fix: implicitly end middleware chain on response by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4441
-   refactor: visible tasks can run in parallel by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4477
-   Update pages.json by [@&#8203;hexa-it](https://togithub.com/hexa-it) in [QwikDev/qwik#4473
-   feat: update starter dev-tools by [@&#8203;adamdbradley](https://togithub.com/adamdbradley) in [QwikDev/qwik#4483
-   perf: optimizer knows non-variadic components by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4484
-   Add new documentation for deprecated features. by [@&#8203;nsdonato](https://togithub.com/nsdonato) in [QwikDev/qwik#4476
-   feat: add no-unnecessary-condition eslint rule by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4485
-   fix(parse-pathname): path segment encoding by [@&#8203;Varixo](https://togithub.com/Varixo) in [QwikDev/qwik#4486
-   docs(\*): update contribution docs by [@&#8203;Wimpert](https://togithub.com/Wimpert) in [QwikDev/qwik#4490
-   Allow replace state when navigating by [@&#8203;Wimpert](https://togithub.com/Wimpert) in [QwikDev/qwik#4488
-   fix: test bundle mode by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4491
-   fix: 'Numberish' type used for width/height didn't allow % by [@&#8203;KenAKAFrosty](https://togithub.com/KenAKAFrosty) in [QwikDev/qwik#4434
-   fix: missing navigation update to static page by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4493
-   🦄 by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4495
-   feat: add image to starter by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4497
-   fix: $localize optimizer bug by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4498
-   docs(adding content security policy to the advanced topics) by [@&#8203;the-zimmermann](https://togithub.com/the-zimmermann) in [QwikDev/qwik#4440
-   fix: clientConn types by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4501
-   Pr docs qwik city by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4494
-   chore: fix dev release by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4511
-   refactor: simplify new templates by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4512
-   fix: cli new interactive by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4516
-   feat: svg optimization with esm by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4526
-   fix: spa redirects from non-pages by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4518
-   docs: fix typos in Overview and State files. by [@&#8203;eecopa](https://togithub.com/eecopa) in [QwikDev/qwik#4524
-   docs: fixed a typo in image link by [@&#8203;avanderpluijm](https://togithub.com/avanderpluijm) in [QwikDev/qwik#4514
-   docs: fixed small typos in qwik-city documentation. by [@&#8203;VinuB-Dev](https://togithub.com/VinuB-Dev) in [QwikDev/qwik#4522
-   feat: pandacss integration by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4515
-   docs: added custom icons  by [@&#8203;LoganAffleck](https://togithub.com/LoganAffleck) in [QwikDev/qwik#4513
-   Update app.tsx in runtime-less example by [@&#8203;primeagen-rustaceans](https://togithub.com/primeagen-rustaceans) in [QwikDev/qwik#4467
-   docs: fix typos by [@&#8203;enesflow](https://togithub.com/enesflow) in [QwikDev/qwik#4500
-   docs: move think-qwik page to concepts route by [@&#8203;moinulmoin](https://togithub.com/moinulmoin) in [QwikDev/qwik#4499
-   feat: frame-perfect and state-backed durable SPA scroll restoration by [@&#8203;jordanw66](https://togithub.com/jordanw66) in [QwikDev/qwik#4509
-   docs: fixed typos in comments and docs by [@&#8203;ehrencrona](https://togithub.com/ehrencrona) in [QwikDev/qwik#4430
-   doc: add redirect to new think-qwik docs by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4533
-   fix: missing component in layout by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4535
-   fix(router): use encodeURI instead by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4534
-   fix: click to component for svg by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4537
-   fix: regression when navigating to / by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4538
-   fix: save scrollState on visibilitychange by [@&#8203;jordanw66](https://togithub.com/jordanw66) in [QwikDev/qwik#4536
-   feat: automatically set qwik icons by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4539
-   fix: renderToString mode is always ignored and returns an empty page by [@&#8203;ncharalampidis](https://togithub.com/ncharalampidis) in [QwikDev/qwik#4528
-   fix: image?jsx strip export default by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4541
-   fix(router): redirect handling by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4543
-   chore: update deps by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4540
-   chore: create `@builder.io/qwik-labs` by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4545
-   perf: leverage modulepreload for common chunks by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4546
-   fix: perfect hash scroll by [@&#8203;jordanw66](https://togithub.com/jordanw66) in [QwikDev/qwik#4550
-   perf: enable navigationPreload by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4548
-   Sidebar style by [@&#8203;LoganAffleck](https://togithub.com/LoganAffleck) in [QwikDev/qwik#4554
-   fix: QwikIntrinsicElements does not include ref by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4555
-   docs: add panda css by [@&#8203;anubra266](https://togithub.com/anubra266) in [QwikDev/qwik#4544
-   feat(insights): create a new insights application by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4547
-   docs: add ss-link to showcase by [@&#8203;Leizhenpeng](https://togithub.com/Leizhenpeng) in [QwikDev/qwik#2689
-   fix: navigationPreload waitUntil by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4561
-   feat: layout shift detection by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4560
-   docs: add resource + fix css by [@&#8203;hamatoyogi](https://togithub.com/hamatoyogi) in [QwikDev/qwik#4562
-   fix(qwik-city buildtime): make generated file ids unique by [@&#8203;hbendev](https://togithub.com/hbendev) in [QwikDev/qwik#4564
-   feat: transform compiler architecture by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4566
-   feat(insights): basic UI for seeing symbols by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4565
-   docs: Add Qwik Labs section by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4568
-   chore: fix broken lock file by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4574
-   fix: route new template by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4576
-   docs(qwik-labs edit link route): fixed qwik labs "edit page" link & so… by [@&#8203;thejackshelton](https://togithub.com/thejackshelton) in [QwikDev/qwik#4571
-   feat(labs): typed routes by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4580
-   docs(labs): add typed routes by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4582
-   chore: fix saving of artifacts to build by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4583
-   chore(labs): fix distribution build by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4584
-   Internal renaming suggestions by [@&#8203;shairez](https://togithub.com/shairez) in [QwikDev/qwik#4581
-   fix(labs): encodeencodeURIComponent for params by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4587
-   feat: panda css use vite-macro plugin by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4588
-   Qwik shop 🎁 by [@&#8203;gioboa](https://togithub.com/gioboa) in [QwikDev/qwik#4225
-   fix: shop cache by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4590
-   docs(advanced & concepts docs improvements): clarity / structure changes by [@&#8203;thejackshelton](https://togithub.com/thejackshelton) in [QwikDev/qwik#4592
-   Add replaceState to link component by [@&#8203;Wimpert](https://togithub.com/Wimpert) in [QwikDev/qwik#4492
-   docs: simplify menu by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4593
-   fix: improve pandacss integration by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4594
-   fix: default prettier format for starters by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4595
-   chore(labs): copy build artifacts into the build git repo by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4589
-   chore: update deps by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4597
-   docs: fix insights docs by [@&#8203;gioboa](https://togithub.com/gioboa) in [QwikDev/qwik#4598
-   chore(labs): include package.json in full build by [@&#8203;mhevery](https://togithub.com/mhevery) in [QwikDev/qwik#4599
-   docs: Dynamic og image implementation by [@&#8203;mrhoodz](https://togithub.com/mrhoodz) in [QwikDev/qwik#4579
-   fix: correct documentation URLs for rules created by ESLintUtils.RuleCreator by [@&#8203;wtlin1228](https://togithub.com/wtlin1228) in [QwikDev/qwik#4604
-   feat: bulletproof SPA recovery by [@&#8203;jordanw66](https://togithub.com/jordanw66) in [QwikDev/qwik#4558
-   fix: Social and Vendor are production only components by [@&#8203;wtlin1228](https://togithub.com/wtlin1228) in [QwikDev/qwik#4610
-   docs: image optimization by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4608
-   chore: change useStore link by [@&#8203;GustavoMelloGit](https://togithub.com/GustavoMelloGit) in [QwikDev/qwik#4601
-   fix(qwik-core): add types for the style attribute by [@&#8203;hbendev](https://togithub.com/hbendev) in [QwikDev/qwik#4577
-   docs: Update deprecation information about the basePathname by [@&#8203;julianobrasil](https://togithub.com/julianobrasil) in [QwikDev/qwik#4437
-   docs: fix typos on Qwik City home by [@&#8203;corydeppen](https://togithub.com/corydeppen) in [QwikDev/qwik#4602
-   feat: improve error message for duplicated loaders by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4619
-   docs: dynamic ogImage feature url format fix and clean up by [@&#8203;mrhoodz](https://togithub.com/mrhoodz) in [QwikDev/qwik#4617
-   fix: detect invalid html by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4623
-   1.2.0 by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4600
-   fix: image devtools by [@&#8203;manucorporat](https://togithub.com/manucorporat) in [QwikDev/qwik#4626
-   feat: qwik add builder.io by [@&#8203;adamdbradley](https://togithub.com/adamdbradley) in [QwikDev/qwik#4627
-   feat: scroll opt-out on nav() and Link by [@&#8203;jordanw66](https://togithub.com/jordanw66) in [QwikDev/qwik#4622

##### New Contributors

-   [@&#8203;erikras](https://togithub.com/erikras) made their first contribution in [QwikDev/qwik#4457
-   [@&#8203;OrenSayag](https://togithub.com/OrenSayag) made their first contribution in [QwikDev/qwik#4453
-   [@&#8203;hexa-it](https://togithub.com/hexa-it) made their first contribution in [QwikDev/qwik#4473
-   [@&#8203;the-zimmermann](https://togithub.com/the-zimmermann) made their first contribution in [QwikDev/qwik#4440
-   [@&#8203;eecopa](https://togithub.com/eecopa) made their first contribution in [QwikDev/qwik#4524
-   [@&#8203;avanderpluijm](https://togithub.com/avanderpluijm) made their first contribution in [QwikDev/qwik#4514
-   [@&#8203;VinuB-Dev](https://togithub.com/VinuB-Dev) made their first contribution in [QwikDev/qwik#4522
-   [@&#8203;LoganAffleck](https://togithub.com/LoganAffleck) made their first contribution in [QwikDev/qwik#4513
-   [@&#8203;primeagen-rustaceans](https://togithub.com/primeagen-rustaceans) made their first contribution in [QwikDev/qwik#4467
-   [@&#8203;enesflow](https://togithub.com/enesflow) made their first contribution in [QwikDev/qwik#4500
-   [@&#8203;moinulmoin](https://togithub.com/moinulmoin) made their first contribution in [QwikDev/qwik#4499
-   [@&#8203;jordanw66](https://togithub.com/jordanw66) made their first contribution in [QwikDev/qwik#4509
-   [@&#8203;ehrencrona](https://togithub.com/ehrencrona) made their first contribution in [QwikDev/qwik#4430
-   [@&#8203;ncharalampidis](https://togithub.com/ncharalampidis) made their first contribution in [QwikDev/qwik#4528
-   [@&#8203;anubra266](https://togithub.com/anubra266) made their first contribution in [QwikDev/qwik#4544
-   [@&#8203;Leizhenpeng](https://togithub.com/Leizhenpeng) made their first contribution in [QwikDev/qwik#2689
-   [@&#8203;mrhoodz](https://togithub.com/mrhoodz) made their first contribution in [QwikDev/qwik#4579
-   [@&#8203;corydeppen](https://togithub.com/corydeppen) made their first contribution in [QwikDev/qwik#4602

**Full Changelog**: QwikDev/qwik@v1.1.5...v1.2.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 9pm on sunday" (UTC), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/ascorbic/unpic-img).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi41LjMiLCJ1cGRhdGVkSW5WZXIiOiIzNi41LjMiLCJ0YXJnZXRCcmFuY2giOiJtYWluIn0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants