Skip to content

Commit

Permalink
Run <link> GC
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkirsz committed Apr 28, 2023
1 parent f54b076 commit 94ad596
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 51 deletions.
Expand Up @@ -4,6 +4,7 @@ import type { ReactElement } from 'react'
import { version } from 'next/package.json'
import { createFromReadableStream } from 'next/dist/compiled/react-server-dom-webpack/client'
import { callServer } from 'next/dist/client/app-call-server'
import { linkGc } from 'next/dist/client/app-link-gc'

import { HeadManagerContext } from 'next/dist/shared/lib/head-manager-context'

Expand Down Expand Up @@ -153,6 +154,8 @@ function hydrate() {
ReactDOMClient.hydrateRoot(appElement, reactEl)
})
}

linkGc()
}

window.next = {
Expand Down
53 changes: 2 additions & 51 deletions packages/next/src/client/app-index.tsx
Expand Up @@ -10,6 +10,7 @@ import { GlobalLayoutRouterContext } from '../shared/lib/app-router-context'
import onRecoverableError from './on-recoverable-error'
import { callServer } from './app-call-server'
import { isNextRouterError } from './components/is-next-router-error'
import { linkGc } from './app-link-gc'

// Since React doesn't call onerror for errors caught in error boundaries.
const origConsoleError = window.console.error
Expand Down Expand Up @@ -297,55 +298,5 @@ export function hydrate() {
reactRoot.render(reactEl)
}

// TODO-APP: Remove this logic when Float has GC built-in in development.
if (process.env.NODE_ENV !== 'production') {
const callback = (mutationList: MutationRecord[]) => {
for (const mutation of mutationList) {
if (mutation.type === 'childList') {
for (const node of mutation.addedNodes) {
if (
'tagName' in node &&
(node as HTMLLinkElement).tagName === 'LINK'
) {
const link = node as HTMLLinkElement
if (link.dataset.precedence === 'next.js') {
const href = link.getAttribute('href')
if (href) {
const [resource, version] = href.split('?v=')
if (version) {
const allLinks = document.querySelectorAll(
`link[href^="${resource}"]`
) as NodeListOf<HTMLLinkElement>
for (const otherLink of allLinks) {
if (otherLink.dataset.precedence === 'next.js') {
const otherHref = otherLink.getAttribute('href')
if (otherHref) {
const [, otherVersion] = otherHref.split('?v=')
if (!otherVersion || +otherVersion < +version) {
otherLink.remove()
const preloadLink = document.querySelector(
`link[rel="preload"][as="style"][href="${otherHref}"]`
)
if (preloadLink) {
preloadLink.remove()
}
}
}
}
}
}
}
}
}
}
}
}
}

// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback)
observer.observe(document.head, {
childList: true,
})
}
linkGc()
}
53 changes: 53 additions & 0 deletions packages/next/src/client/app-link-gc.ts
@@ -0,0 +1,53 @@
export function linkGc() {
// TODO-APP: Remove this logic when Float has GC built-in in development.
if (process.env.NODE_ENV !== 'production') {
const callback = (mutationList: MutationRecord[]) => {
for (const mutation of mutationList) {
if (mutation.type === 'childList') {
for (const node of mutation.addedNodes) {
if (
'tagName' in node &&
(node as HTMLLinkElement).tagName === 'LINK'
) {
const link = node as HTMLLinkElement
if (link.dataset.precedence === 'next.js') {
const href = link.getAttribute('href')
if (href) {
const [resource, version] = href.split('?v=')
if (version) {
const allLinks = document.querySelectorAll(
`link[href^="${resource}"]`
) as NodeListOf<HTMLLinkElement>
for (const otherLink of allLinks) {
if (otherLink.dataset.precedence === 'next.js') {
const otherHref = otherLink.getAttribute('href')
if (otherHref) {
const [, otherVersion] = otherHref.split('?v=')
if (!otherVersion || +otherVersion < +version) {
otherLink.remove()
const preloadLink = document.querySelector(
`link[rel="preload"][as="style"][href="${otherHref}"]`
)
if (preloadLink) {
preloadLink.remove()
}
}
}
}
}
}
}
}
}
}
}
}
}

// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback)
observer.observe(document.head, {
childList: true,
})
}
}

0 comments on commit 94ad596

Please sign in to comment.