diff --git a/components/Common/ActiveLocalizedLink/index.tsx b/components/Common/ActiveLocalizedLink/index.tsx index 8e966a09323f8..ff6254e6b05dc 100644 --- a/components/Common/ActiveLocalizedLink/index.tsx +++ b/components/Common/ActiveLocalizedLink/index.tsx @@ -3,7 +3,8 @@ import classNames from 'classnames'; import type { ComponentProps, FC } from 'react'; -import { Link, usePathname } from '@/navigation.mjs'; +import Link from '@/components/Link'; +import { usePathname } from '@/navigation.mjs'; type ActiveLocalizedLinkProps = ComponentProps & { activeClassName: string; diff --git a/components/Common/Badge/index.tsx b/components/Common/Badge/index.tsx index 6d5845cf088b6..258b32312b07d 100644 --- a/components/Common/Badge/index.tsx +++ b/components/Common/Badge/index.tsx @@ -1,7 +1,7 @@ import ArrowRightIcon from '@heroicons/react/24/solid/ArrowRightIcon'; import type { ComponentProps, FC, PropsWithChildren } from 'react'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; import styles from './index.module.css'; diff --git a/components/Common/Banner/index.tsx b/components/Common/Banner/index.tsx index 50b397ed27bfc..6c5f8fb3aacd9 100644 --- a/components/Common/Banner/index.tsx +++ b/components/Common/Banner/index.tsx @@ -1,7 +1,7 @@ import { ArrowUpRightIcon } from '@heroicons/react/24/outline'; import type { FC } from 'react'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; import styles from './index.module.css'; diff --git a/components/Common/Breadcrumbs/BreadcrumbLink/index.tsx b/components/Common/Breadcrumbs/BreadcrumbLink/index.tsx index f776fee68750c..c4cd7ce9beab8 100644 --- a/components/Common/Breadcrumbs/BreadcrumbLink/index.tsx +++ b/components/Common/Breadcrumbs/BreadcrumbLink/index.tsx @@ -1,7 +1,7 @@ import classNames from 'classnames'; import type { ComponentProps, FC } from 'react'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; import styles from './index.module.css'; diff --git a/components/Common/CrossLink/index.tsx b/components/Common/CrossLink/index.tsx index 6eadf16f91285..137eb3e31640f 100644 --- a/components/Common/CrossLink/index.tsx +++ b/components/Common/CrossLink/index.tsx @@ -3,7 +3,7 @@ import { useTranslations } from 'next-intl'; import type { FC } from 'react'; import PrevNextArrow from '@/components/Common/PrevNextArrow'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; import styles from './index.module.css'; diff --git a/components/Common/MetaBar/index.stories.tsx b/components/Common/MetaBar/index.stories.tsx index 25c8d964797cc..c9d5803dbf879 100644 --- a/components/Common/MetaBar/index.stories.tsx +++ b/components/Common/MetaBar/index.stories.tsx @@ -4,7 +4,7 @@ import Image from 'next/image'; import AvatarGroup from '@/components/Common/AvatarGroup'; import MetaBar from '@/components/Common/MetaBar'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; type Story = StoryObj; type Meta = MetaObj; diff --git a/components/Common/MetaBar/index.tsx b/components/Common/MetaBar/index.tsx index 9a8af2ef5e224..96f1ed56c55fb 100644 --- a/components/Common/MetaBar/index.tsx +++ b/components/Common/MetaBar/index.tsx @@ -3,7 +3,7 @@ import { useTranslations } from 'next-intl'; import { Fragment, useMemo } from 'react'; import type { FC } from 'react'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; import styles from './index.module.css'; diff --git a/components/Common/Pagination/PaginationListItem/index.tsx b/components/Common/Pagination/PaginationListItem/index.tsx index fc04f931c99ad..a1fd525c7a58f 100644 --- a/components/Common/Pagination/PaginationListItem/index.tsx +++ b/components/Common/Pagination/PaginationListItem/index.tsx @@ -1,7 +1,7 @@ import { useTranslations } from 'next-intl'; import type { FC } from 'react'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; import styles from './index.module.css'; diff --git a/components/Downloads/DownloadList.tsx b/components/Downloads/DownloadList.tsx index c4287e723335f..018c169d1e111 100644 --- a/components/Downloads/DownloadList.tsx +++ b/components/Downloads/DownloadList.tsx @@ -1,8 +1,8 @@ import { useTranslations } from 'next-intl'; import type { FC } from 'react'; +import Link from '@/components/Link'; import { useSiteNavigation } from '@/hooks/server'; -import { Link } from '@/navigation.mjs'; import type { NodeRelease } from '@/types'; const DownloadList: FC = ({ versionWithPrefix }) => { diff --git a/components/Downloads/PrimaryDownloadMatrix.tsx b/components/Downloads/PrimaryDownloadMatrix.tsx index 59ee9f3c10346..8559d59dfa07f 100644 --- a/components/Downloads/PrimaryDownloadMatrix.tsx +++ b/components/Downloads/PrimaryDownloadMatrix.tsx @@ -4,9 +4,9 @@ import classNames from 'classnames'; import type { FC } from 'react'; import semVer from 'semver'; +import Link from '@/components/Link'; import { WithCurrentOS } from '@/components/withCurrentOS'; import { useClientContext } from '@/hooks'; -import { Link } from '@/navigation.mjs'; import { DIST_URL } from '@/next.constants.mjs'; import type { NodeRelease } from '@/types'; diff --git a/components/Footer.tsx b/components/Footer.tsx index c895290a2a39a..e5572ca12eb2f 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -1,6 +1,6 @@ import type { FC } from 'react'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; type FooterProps = { className?: string }; diff --git a/components/Header.tsx b/components/Header.tsx index 0465d445dcc87..bdac8a701d96c 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -6,8 +6,9 @@ import { useTranslations } from 'next-intl'; import { useTheme } from 'next-themes'; import { useState } from 'react'; +import Link from '@/components/Link'; import { useIsCurrentPathname, useSiteNavigation } from '@/hooks'; -import { Link, usePathname } from '@/navigation.mjs'; +import { usePathname } from '@/navigation.mjs'; import { BASE_PATH } from '@/next.constants.mjs'; import { availableLocales } from '@/next.locales.mjs'; diff --git a/components/Home/HomeDownloadButton.tsx b/components/Home/HomeDownloadButton.tsx index f17c8370ba835..dd4c7afa114e0 100644 --- a/components/Home/HomeDownloadButton.tsx +++ b/components/Home/HomeDownloadButton.tsx @@ -3,8 +3,8 @@ import { useTranslations } from 'next-intl'; import type { FC } from 'react'; +import Link from '@/components/Link'; import { useDetectOS } from '@/hooks'; -import { Link } from '@/navigation.mjs'; import { DIST_URL } from '@/next.constants.mjs'; import type { NodeRelease } from '@/types'; import { downloadUrlByOS } from '@/util/downloadUrlByOS'; diff --git a/components/Link.tsx b/components/Link.tsx new file mode 100644 index 0000000000000..0b1f96dfc474c --- /dev/null +++ b/components/Link.tsx @@ -0,0 +1,31 @@ +import { useMemo } from 'react'; +import type { FC, ComponentProps, HTMLAttributes as Attributes } from 'react'; + +import { Link as LocalizedLink } from '@/navigation.mjs'; + +// This is a wrapper on HTML's `a` tag +const Html: FC> = ({ children, ...p }) => ( + {children} +); + +// This is Next.js's Link Component but with pre-fetch disabled +const Next: FC> = ({ children, ...p }) => ( + {children} +); + +const Link: FC> = ({ + children, + ...props +}) => { + const Component = useMemo( + // Uses a different Link element/tag based on the nature of the Link + // as we don't want prefetch/rsc or etc for external links + () => + !props.href || props.href.toString().startsWith('http') ? Html : Next, + [props.href] + ); + + return {children}; +}; + +export default Link; diff --git a/components/Pagination.tsx b/components/Pagination.tsx index 3c8a20f11b8c9..fd99fa1926a6d 100644 --- a/components/Pagination.tsx +++ b/components/Pagination.tsx @@ -1,7 +1,7 @@ import { useTranslations } from 'next-intl'; import type { FC } from 'react'; -import { Link } from '@/navigation.mjs'; +import Link from '@/components/Link'; type PaginationProps = { prev?: number; next?: number }; diff --git a/components/SideNavigation.tsx b/components/SideNavigation.tsx index b6e3a33a62008..b125ae4b58ea6 100644 --- a/components/SideNavigation.tsx +++ b/components/SideNavigation.tsx @@ -4,8 +4,8 @@ import classNames from 'classnames'; import type { RichTranslationValues } from 'next-intl'; import type { FC } from 'react'; +import Link from '@/components/Link'; import { useIsCurrentPathname, useSiteNavigation } from '@/hooks'; -import { Link } from '@/navigation.mjs'; import type { NavigationKeys } from '@/types'; type SideNavigationProps = { diff --git a/layouts/BlogCategoryLayout.tsx b/layouts/BlogCategoryLayout.tsx index 3af7b8ceb4a32..a08b9d49d7e2f 100644 --- a/layouts/BlogCategoryLayout.tsx +++ b/layouts/BlogCategoryLayout.tsx @@ -3,9 +3,9 @@ import { useMemo } from 'react'; import type { FC } from 'react'; import { Time } from '@/components/Common/Time'; +import Link from '@/components/Link'; import Pagination from '@/components/Pagination'; import { useClientContext, useBlogData } from '@/hooks/server'; -import { Link } from '@/navigation.mjs'; import type { BlogPost } from '@/types'; const BlogCategoryLayout: FC = () => { diff --git a/next.mdx.use.mjs b/next.mdx.use.mjs index 5b2e60118867b..85a86325e73a4 100644 --- a/next.mdx.use.mjs +++ b/next.mdx.use.mjs @@ -4,8 +4,8 @@ import NodeApiVersionLinks from './components/Docs/NodeApiVersionLinks'; import DownloadReleasesTable from './components/Downloads/DownloadReleasesTable'; import Banner from './components/Home/Banner'; import HomeDownloadButton from './components/Home/HomeDownloadButton'; +import Link from './components/Link'; import { WithNodeRelease } from './components/withNodeRelease'; -import { Link } from './navigation.mjs'; /** * A full list of React Components that we want to passthrough to MDX diff --git a/package-lock.json b/package-lock.json index c4b4e0e39a3a6..25cccd6b53bd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,8 +61,8 @@ "@testing-library/react": "~14.0.0", "@testing-library/user-event": "~14.5.1", "@types/jest": "29.5.7", - "@types/react": "^18.2.24", - "@types/react-dom": "^18.2.9", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", "@types/semver": "~7.5.5", "@typescript-eslint/eslint-plugin": "6.9.0", "@typescript-eslint/parser": "6.9.0", @@ -8482,9 +8482,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.24", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.24.tgz", - "integrity": "sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw==", + "version": "18.2.37", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.37.tgz", + "integrity": "sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==", "devOptional": true, "dependencies": { "@types/prop-types": "*", @@ -8493,9 +8493,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.9.tgz", - "integrity": "sha512-6nNhVzZ9joQ6F7lozrASuQKC0Kf6ArYMU+DqA2ZrUbB+d+9lC6ZLn1GxiEBI1edmAwvTULtuJ6uPZpv3XudwUg==", + "version": "18.2.15", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.15.tgz", + "integrity": "sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==", "devOptional": true, "dependencies": { "@types/react": "*" diff --git a/package.json b/package.json index 752cddbb1be45..70fc2861cc6a4 100644 --- a/package.json +++ b/package.json @@ -93,8 +93,8 @@ "@testing-library/react": "~14.0.0", "@testing-library/user-event": "~14.5.1", "@types/jest": "29.5.7", - "@types/react": "^18.2.24", - "@types/react-dom": "^18.2.9", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", "@types/semver": "~7.5.5", "@typescript-eslint/eslint-plugin": "6.9.0", "@typescript-eslint/parser": "6.9.0",