在 Astro 中寫 MDX 產生內容時非常方便且快速,但時常內容可能包含外部連結,這時候我們可能會希望自動為這些外部連結加上 rel='nofollow'
和 target='_blank'
屬性,讓用戶在點擊外部連結時不會離開我們的網站和提升網站 SEO。
如何實作
由於在 Astro 中 HTML 最終會經過 rehype plugins 處理,因此其實我們可以在這裡掛上一個 plugin 來幫我們自動為外部連結加上 rel='nofollow'
和 target='_blank'
屬性。
實作有以下兩種方向:
- 直接使用開源寫好的 💁♂️ rehype-external-links
# 安裝 rehype-external-links
npm install rehype-external-links
// astro.config.ts
markdown: {
// 加上以下這段設定
rehypePlugins: [
[
rehypeExternalLinks,
{
target: "_blank",
},
],
]
},
- 照 rehype plugin 文件 自己開發一個 Plugin ✏️
// src/externalLink.ts
import type { RehypePlugin } from "@astrojs/markdown-remark";
import { visit } from "unist-util-visit";
import type { Element } from "hast";
interface Options {
domain: string; // The domain to check against for determining if a link is external
}
// Define the Rehype plugin for processing external links
const externalLink: RehypePlugin = (options?: Options) => {
const siteDomain = options?.domain ?? "";
return tree => {
// Visit each node in the syntax tree
visit(tree, node => {
// If the node is not an element, skip processing
if (node.type != "element") {
return;
}
const element = node as Element;
// Check if the element is an anchor tag; if not, skip processing
if (!isAnchor(element)) {
return;
}
// Get the URL from the anchor element
const url = getUrl(element);
// Check if the URL is external; if so, set the target attribute to "_blank"
if (isExternal(url, siteDomain)) {
element.properties!["target"] = "_blank";
}
});
};
};
// Helper function to determine if an element is an anchor tag
const isAnchor = (element: Element) =>
element.tagName == "a" && element.properties && "href" in element.properties;
// Helper function to extract the URL from an anchor element
const getUrl = (element: Element) => {
if (!element.properties) {
return "";
}
const url = element.properties["href"];
if (!url) {
return "";
}
return url.toString();
};
// Helper function to determine if a URL is external
const isExternal = (url: string, domain: string) => {
return url.startsWith("http") && !url.includes(domain);
};
export default externalLink;
// import externalLink plugin
import externalLink from "./src/externalLink";
...
// astro.config.ts
markdown: {
// 加上你自己寫的 plugin 設定
rehypePlugins: [
[
rehypeExternalLinks,
{
target: "_blank",
},
],
],
}
1 應該會是最快也最簡單的方式,但如果你想要更多彈性與調整
2 則會是一個練習自己寫 rehype plugin 的不錯機會!
這樣調整完後,就不用在 MDX 文件中特別為每個外部連結手動寫 HTML 加上 rel='nofollow'
和 target='_blank'
屬性了 🎉