In the current implementation, `idleTimeout` will always be thrown even if it didn't time out and `Promise.race` was resolved. This causes the error `Error: Route did not complete loading` on every route transition and Chrome Devtools will pause code execution if you have "Pause on exceptions" enabled.
This PR adds `resolvePromiseWithTimeout` which does the same thing as `Promise.race` and `idleTimeout`, but it cancels the rejection when it resolves successfully, in which case the error won't be thrown.
Fixes#21543.
Currently, the image component doesn't handle use of the `sizes` property with `layout="fill"` and `layout="responsive"` very well for small viewports. It will never include sizes smaller than the smallest viewport (640px) in the srcset, so even if you specify `sizes="30vw"` in your image, you have to download the full-viewport-width image on small devices.
This PR adds logic such that if you use `layout="fill"` and include a `sizes` property, the image component will include the full range of image sizes in the `srcset`.
It also includes an optimization where it finds the smallest `vw` value in the sizes value and combines that with the smallest viewport width, and uses that as the floor of the srcset. It does this so it doesn't unnecessarily increase transfer size by including ALL sizes. This is still a conservative optimization--for 95% of cases, taking the _largest_ `vw` size would work, but I don't see a way to do that without breaking a few corner cases.
The case of a sizes prop with `px` values is fixed but not optimized--though generally that case is less of a good fit for the fill or responsive layout anyway.
Fixes#16864
The `router` can be missing in a test environment when trying to render a `Link` component. This PR bails out of `router.prefetch()` when `router` is missing.
The alternative is for users to mock `next/link` or to mock the `router` and wrap their test components.
Please let me know any feedback.
This is a #19325 reconfigured to support a loader passed in via a `loader` prop on the Image component, rather than using a config-based approach.
The idea is that applications wanting to use a custom loader will create a wrapper element for the image component that incorporates that loader. See a simple example of this pattern in the integration tests.
This solution is similar to the one prototyped by @ricokahler in #20213 and described at https://github.com/vercel/next.js/issues/18606#issuecomment-720149156
---
Closes#19325Fixes#18606
This pull request correctly assigns boolean attributes for `<script />` to match the element as it is created by a server-side render.
Prior to this pull request, we'd double-execute `<script>` tags with the `async`, `defer`, or `nomodule` property.
---
Fixes#9070
This PR fixes a bug where we'd accidentally pass-through the user-provided `srcSet` if the image was lazy, just to then replace it when we hydrate.
---
Fixes#19041
This pull request adjusts our experimental scroll restoration behavior to use `sessionStorage` as opposed to `History#replaceState` to track scroll position.
In addition, **it eliminates a scroll event listener** and only captures when a `pushState` event happens (thereby leaving state that needs snapshotted).
These merely adjusts implementation detail, and is covered by existing tests:
```
test/integration/scroll-back-restoration/
```
---
Fixes#16690Fixes#17073Fixes#20486
This ensures we render the locale domain on the `href` when using `next/link` previously the provided `href` was stilling being rendered which differed from the resulting `href` that was navigated to.
Fixes: https://github.com/vercel/next.js/issues/20612
This pull request adds an `elements.delete` operation to the `useIntersection`'s cleanup function: `unobserve`.
Without this delete operation, next.js holds onto an unreachable reference of every observed element indefinitely (automatically every Link and Image is observed, so that means every rendered Link and Image element adds to the leak). I found this memory leak when building out an infinite feed in next.js with thousands of Link elements.
The final code block of the `unobserve` function body:
```tsx
// Destroy observer when there's nothing left to watch:
if (elements.size === 0) {
observer.disconnect()
observers.delete(id)
}
```
Is effectively unreachable without this delete operation, as the `elements` map will never decrease in size as it is currently. This means that there will always be at least one IntersectionObserver instance in memory if useIntersection has been used once, regardless of if there are currently any components still using the hook.
This ensures we detect domain specific locales and redirect them client-side. Tests have been added in the `i18n` suite to ensure the domain redirect is applied correctly during a client-side navigation
Fixes: https://github.com/vercel/next.js/issues/19174
This moves the scroll reset behavior to happen synchronously with the DOM commit, instead of a few ticks after the render completes.
This is necessary for components that read scroll state on mount.
---
Fixes#6462
This fixes `next/image` to properly ignore inherited styles applied to the `img` tag by a parent element.
Image styling should **always** be done by a wrapper element—not to the image itself!
---
Fixes#19817Fixes#19964
This removes `import type` usage from our core files since `import type` requires a higher TypeScript version than currently expected.
Fixes: https://github.com/vercel/next.js/issues/19300
Currently if sizes is not defined, Next.js is setting sizes as:
```
(max-width: 640px) 640px, (max-width: 750px) 750px, (max-width: 828px) 828px, (max-width: 1080px) 1080px, (max-width: 1200px) 1200px, (max-width: 1920px) 1920px, (max-width: 2048px) 2048px, 3840px'
```
This pull request will make sizes be `100vw` by default, which will allow us to download "smaller" images than what's currently happening.
In a demo app I have, the difference is between downloading 488KB vs 1.4MB (in images)
This makes sure SSG data is correctly prefetched for the default locale and other locales on the same page. Tests for this behavior have been added for catch-all and normal pages.
Closes: https://github.com/vercel/next.js/issues/19048
Fixes#18720
This removes image preloading. It doesn't work correctly on any browser other than Chrome (with Chrome's real engine). On all other browsers, it triggers 2x the bytes to be downloaded. The tradeoff isn't worth it here IMO.
Chrome itself should be smart enough to bump an `<img />` tag's priority over other preloads that are script type during the preparse phase.
We can reintroduce this when we don't hurt non-Chrome users.
This fixes a few things related to optional catch-all routes and i18n. The first thing is it ensures the correct data route is generated on the client so that the locale isn't duplicated for an optional catch-all route, the next is it ensures the browser history is updated correctly when only a locale change is occurring, and then it also ensures we handle the locales and normalizing for fallback optional catch-all pages correctly.
Tests have been added to ensure these cases are covered properly and we don't regress on them, these changes were also tested on Vercel [here](https://next-js-bug-i18n-root-params-nybg44l0b.vercel.app/)
Fixes: https://github.com/vercel/next.js/issues/18633
Fixes: https://github.com/vercel/next.js/issues/19059
This pull request completely replaces our old page loader with a brand new route loader.
Our existing comprehensive test suite means I did not need to add a bunch of tests. I did add them where behavior was added or fixed.
Summary of the changes:
- Eagerly evaluates prefetched pages in browser idle time (speeds up transitions)
- Router is **no longer frozen** indefinitely if the Build Manifest never arrives
- Router is **no longer frozen** indefinitely if a page fails to bootstrap
- New `withFuture` utility instead of ad-hoc deduping per resource
- Prefetching is now delayed until browser idle time to not impact TTI
- Browsers without `prefetch` now fall back to eager evaluation instead of using `preload`
- We're now ready to serve non-static assets **with `no-store` without breaking prefetching**
- **Application can now hydrate without fetching CSS assets—this is a huge performance win that was previously blocking hydration**
---
The minor size increase here is unfortunate, but we have to incur it for correctness.
---
Fixes#18389Fixes#18642
This PR fixes two bugs causing HTML validators to complain.
- Error: Bad value data:image/svg+xml;charset=utf-8, for attribute src on element img: Illegal character in scheme data: < is not allowed.
- Fixed by using base64 for svg during `layout=intrinsic` to avoid angle brackets
- Error: Element img is missing required attribute src.
- Fixed by using base64 transparent gif for `loading=lazy` placeholder
Fixes#18850
This pull request fixes `<Image />` not updating when new props are passed by removing external DOM mutations and relying on React to do it instead.
As an added bonus, I've extracted the intersection observer from both the `<Image />` and `<Link />` component, as their instance can be shared!
The increase in size is minor (+3B), and actually a decrease for apps using both `<Image />` and `<Link />`.
---
Fixes#18698Fixes#18369
While we were fixing how Next.js handled CSS, we added a complex prefetch, preload, fetch sequence to acquire the CSS asset.
This unnecessarily overcomplicated what could've been only a `fetch()` from the very start!
---
Fixes#16932
This pull request speeds up Next.js' rendering pipeline by fetching data, parsing it, and loading it into memory instead of only doing the network request.
This will mainly result in improved Firefox/Safari performance since they handled prefetch incorrectly—only Chrome did it right. This also gets us closer to being able to use `no-store` in our caching headers!
---
Fixes#18639
x-ref #18802
This adds ncc inlining optimizations for the following dependencies:
* cacache
* schema-utils
* find-cache-dir
* mkdirp
* neo-async
* web-vitals
The slight increase in output in the reports here is due to the variation of the bundled version of web-vitals.
In addition, this moves ast-types to be a devDependencies entry instead of in dependencies as it was before https://github.com/vercel/next.js/pull/14746 as I could not see any production usage (ping @prateekbh). Happy to separate that out into a separate PR if preferred too.
This PR prints a pretty error when the Image `src` property is a [protocol-relative URL](https://www.paulirish.com/2010/the-protocol-relative-url/).
> Update 2014.12.17:
> Now that SSL is encouraged for everyone and doesn’t have performance concerns, this technique is now an anti-pattern. If the asset you need is available on SSL, then always use the https:// asset.
Fixes#18536
Next.js would try to "recover" if its CSS assets went missing (i.e. a deployment occured) **while the page was initially loading**.
This handled a rare case where we'd try to let the Next.js complete hydrating even though a deployment occured.
However, in practice, this never worked: if the `fetch()` failed, that means the original assets never downloaded themselves (because the `fetch()` should be coming from disk cache).
Instead of letting Next.js get itself into a weird state, let's just stop hydration so that the page doesn't accidentally delete its styles.
The handle-no-styles behavior is already tested in `test/integration/css/test/index.test.js`. There was never a branch for it using its cached styles, so nothing else needs updated.
---
Fixes#17930
When visiting a non-locale prefixed path (`/hello` instead of `/fr/hello`) we don't trigger locale redirects currently so if another locale is matched we need to ensure this is reset to the `defaultLocale` for rendering to prevent a mis-match on the client and the server.
This also fixes hydration errors from occurring with `asPath` for `getServerSideProps` pages due to `normalizeLocalePath` expecting only a pathname and `asPath` containing `hash` and `query values also.
Fixes: https://github.com/vercel/next.js/issues/18337
Fixes: https://github.com/vercel/next.js/issues/18510
This PR deprecates the `unsized` property from NextImage because the property did not accomplish the desired effect.
Users should rely on one of the new layouts instead:
- `<Image layout="fixed" />`
- `<Image layout="intrinsic" />`
- `<Image layout="responsive" />`
- `<Image layout="fill" />`
The `unsized` property will continue to work as-is in production but is deprecated and will throw in dev.
---
### TODO:
- [x] test `layout=fill` in typescript types
- [x] test `layout=fill` render behavior
- [x] test that `unsized` switches to `layout=fill`
- [x] test `next dev` erroring on `unsized`
- [ ] layout docs (tracked in issue #18554)
- [ ] both `layout=fill` and `layout=responsive` use all deviceWidths in the srcset
---
Fixes#18541
Co-authored-by: Steven <steven@ceriously.com>
This PR introduces a new `layout` property.
This allows 3 possible values (`fixed`, `intrinsic`, or `responsive`) which solve many use cases we have seen since 10.0.0 and will hopefully avoid usage of `unsized`.
Fixes#18351
Co-authored-by: Joe Haddad <joe.haddad@zeit.co>
* Add err.sh for missing images domain
* Apply suggestions from code review
Co-authored-by: Steven <steven@ceriously.com>
* Update test
Co-authored-by: Steven <steven@ceriously.com>
This does two things:
- Rename `iconSizes` to `imageSizes`.
- Give priority to `imageSizes` regardless of `deviceSizes` as a means to opt-out of the srcset behavior.
This separates the `next.config.js` property `images.sizes` into to properties: `images.deviceSizes` and `images.iconSizes`.
The purpose is for images that are not intended to take up the majority of the viewport.
Related to #18122
There was a bug when the user defines a width on the Image component, but a larger size image is requested.
This is because the browser uses the `srcset` to decide which image size to request and we had the srcset basically hardcoded.
This PR fixes the behavior so that the `srcset` will never be larger than the `width` defined on the component.
It also fixes a bug where the preload srcset did not match the img srcset.
- Related to #18147
- Related to #18122
For many users refactoring from `<img>` to `<Image>`, we can often support their properties as-is.
The exception was width/height.
This PR allows the `<Image>` component to accept strings for `width` and `height` just like `<img>`.
Related to #18122
This PR updates the `<Image>` component to follow the same property naming as native `<img>`.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#attr-loading
This currently allows two values,`loading=lazy` and `loading=eager`, but there might be new values added in a future spec.
cc @atcastle
This makes sure that we detect the correct default locale for domain specific locales since a domain can have a different default locale residing at the root and we need to check this on the client for prerendered/auto-static pages. This also makes sure we disable the built-in redirect handling when on Vercel since it's handled already.
Tests for this are tricky since we need to load the browser with a custom domain which requires editing the host file. Existing tests should ensure this doesn't break non-domain specific locale behavior though. This was also tested manually while testing https://github.com/vercel/vercel/pull/5298
x-ref: https://github.com/vercel/next.js/pull/17370
This PR adjust the Web Vitals reporting to be called *after* rendering occurs. It used to work like this, but React's render method is no longer synchronous—so we have to do it in an effect.
Existing tests should cover this code path, and IMO it's unfeasible to test that it's invoked _after_ hydration.
Also removed the `&& ST` condition which is not relevant to Web Vitals.
This adds the `locale` prop for `next/link` to allow transitioning between locales client-side and also allows passing the locale to `router.push/replace` via the transition options similar to `shallow` e.g. `router.push('/another', '/another, { locale: 'nl' })`
x-ref: https://github.com/vercel/next.js/pull/17370
While working on https://github.com/vercel/next.js/pull/17755 noticed a couple of cases that needed fixing and broke them out to this PR to make that one easier to review. One fix is for `ssgCacheKey` where it wasn't having the `locale` prefix stripped correctly due to the locales no longer being populated under the server instances `renderOpts` and the second fix is for the `asPath` not being set to `/` when the `locale` is the only part in the URL e.g. `/en` became an empty string `""`
x-ref: https://github.com/vercel/next.js/pull/17370