mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
fix(nuxt): don't set default rel
for same-site external links (#25600)
This commit is contained in:
parent
82173ad1a9
commit
b78e1cb206
@ -57,7 +57,13 @@ In this example, we use `<NuxtLink>` component to link to a website.
|
||||
|
||||
## `target` and `rel` Attributes
|
||||
|
||||
In this example, we use `<NuxtLink>` with `target`, `rel`, and `noRel` props.
|
||||
A `rel` attribute of `noopener noreferrer` is applied by default to absolute links and links that open in new tabs.
|
||||
- `noopener` solves a [security bug](https://mathiasbynens.github.io/rel-noopener/) in older browsers.
|
||||
- `noreferrer` improves privacy for your users by not sending the `Referer` header to the linked site.
|
||||
|
||||
These defaults have no negative impact on SEO and are considered [best practice](https://developer.chrome.com/docs/lighthouse/best-practices/external-anchors-use-rel-noopener).
|
||||
|
||||
When you need to overwrite this behavior you can use the `rel` and `noRel` props.
|
||||
|
||||
```vue [app.vue]
|
||||
<template>
|
||||
|
@ -20,7 +20,6 @@ import { nuxtLinkDefaults } from '#build/nuxt.config.mjs'
|
||||
|
||||
const firstNonUndefined = <T> (...args: (T | undefined)[]) => args.find(arg => arg !== undefined)
|
||||
|
||||
const DEFAULT_EXTERNAL_REL_ATTRIBUTE = 'noopener noreferrer'
|
||||
const NuxtLinkDevKeySymbol: InjectionKey<boolean> = Symbol('nuxt-link-dev-key')
|
||||
|
||||
/**
|
||||
@ -229,7 +228,9 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||
})
|
||||
|
||||
// Lazily check whether to.value has a protocol
|
||||
const isProtocolURL = computed(() => typeof to.value === 'string' && hasProtocol(to.value, { acceptRelative: true }))
|
||||
const isAbsoluteUrl = computed(() => typeof to.value === 'string' && hasProtocol(to.value, { acceptRelative: true }))
|
||||
|
||||
const hasTarget = computed(() => props.target && props.target !== '_self')
|
||||
|
||||
// Resolving link type
|
||||
const isExternal = computed<boolean>(() => {
|
||||
@ -239,7 +240,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||
}
|
||||
|
||||
// When `target` prop is set, link is external
|
||||
if (props.target && props.target !== '_self') {
|
||||
if (hasTarget.value) {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -248,7 +249,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||
return false
|
||||
}
|
||||
|
||||
return to.value === '' || isProtocolURL.value
|
||||
return to.value === '' || isAbsoluteUrl.value
|
||||
})
|
||||
|
||||
// Prefetching
|
||||
@ -333,7 +334,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||
// converts `""` to `null` to prevent the attribute from being added as empty (`href=""`)
|
||||
const href = typeof to.value === 'object'
|
||||
? router.resolve(to.value)?.href ?? null
|
||||
: (to.value && !props.external && !isProtocolURL.value)
|
||||
: (to.value && !props.external && !isAbsoluteUrl.value)
|
||||
? resolveTrailingSlashBehavior(joinURL(config.app.baseURL, to.value), router.resolve) as string
|
||||
: to.value || null
|
||||
|
||||
@ -342,10 +343,16 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
||||
|
||||
// Resolves `rel`
|
||||
checkPropConflicts(props, 'noRel', 'rel')
|
||||
const rel = (props.noRel)
|
||||
? null
|
||||
const rel = firstNonUndefined<string | null>(
|
||||
// converts `""` to `null` to prevent the attribute from being added as empty (`rel=""`)
|
||||
: firstNonUndefined<string | null>(props.rel, options.externalRelAttribute, href ? DEFAULT_EXTERNAL_REL_ATTRIBUTE : '') || null
|
||||
props.noRel ? '' : props.rel,
|
||||
options.externalRelAttribute,
|
||||
/*
|
||||
* A fallback rel of `noopener noreferrer` is applied for external links or links that open in a new tab.
|
||||
* This solves a reverse tabnapping security flaw in browsers pre-2021 as well as improving privacy.
|
||||
*/
|
||||
(isAbsoluteUrl.value || hasTarget.value) ? 'noopener noreferrer' : ''
|
||||
) || null
|
||||
|
||||
const navigate = () => navigateTo(href, { replace: props.replace })
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user