@forge42/seo-tools (英语)
道德操守办公室 工具是一系列工具,可以帮助您完成你的SEO工作. 它包括帮助您获得站点地图、机器人.txt、犬类链接、结构化数据和元数据的工具。 包被分成更小的子模块 这样你只能导入你需要的零件 本着良好的SEO的精神 我们希望你的捆绑尽可能小.
安装
使用您选择的软件包管理器安装软件包.
npm install @forge42/seo-tools
使用量
套件分成更小的子模块 这样你只能导入你需要的部件 本着SEO的精神 尽可能小.
import { generateCanonicalLinks } from '@forge42/seo-tools/canonical';
这意味着我们不包括枪管导出,你需要导入所需的特定模块. 我们这样做只是为了你需要的部分 用于上述捆绑中。 现在,我们将检查每一个子进口 和他们做什么.
连续链接( C)
词条链接是一个链接,它告诉搜索引擎某个URL代表一个页面的主拷贝. 这对SEO有用,因为它有助于搜索引擎避免内容重复问题,并告诉它替代语言/内容.
变压器的功能会还原克能克url和当前替代物,替代物可以是串,对象或其他任何可以传递给变压器.
import { generateCanonicalLinks } from '@forge42/seo-tools/canonical';
const canonicalLinks = generateCanonicalLinks({
// Used to generate the final url, it passes your alternatives, url and domain to the function for you to create whatever link you need
urlTransformer: ({ url, domain, alternative, canonicalUrl }) => `${domain}/${url}?lng=${alternative}`,
// Used to generate the final attributes
altAttributesTransformer: ({ url, domain, alternative, canonicalUrl }) => attributes,
// This takes a generic type and returns it in your transformers
alternatives: ["de", "es"],
domain: "https://example.com",
url: "current-url",
// Used to add additional attributes
canonicalAttributes: {
// These are included by default but you can add additional attributes
rel: 'canonical',
// These are included by default but you can add additional attributes
href: 'https://example.com'
}
},
// Second argument tells the function if it should generate the output as string or as an array of json objects
false
);
console.log(canonicalLinks);
// <link rel="canonical" href="https://example.com/current-url">
// <link rel="alternate" href="https://example.com/current-url?lng=de" hreflang="de">
// <link rel="alternate" href="https://example.com/current-url?lng=es" hreflang="es">
// or as an array of json objects
// [
// { rel: 'canonical', href: 'https://example.com/current-url' },
// { rel: 'alternate', href: 'https://example.com/current-url?lng=de', hreflang: 'de' },
// { rel: 'alternate', href: 'https://example.com/current-url?lng=es', hreflang: 'es' }
// ]
机器人.txt
机器人.txt文件是一个告诉搜索引擎可以和不能索引的页面的文件. 这对SEO有用,因为它有助于搜索引擎避免索引页面,而你不希望它们索引.
import { generateRobotsTxt } from '@forge42/seo-tools/robots';
const robotsTxt = generateRobotsTxt([
{
userAgent: '*',
allow: ['/'],
disallow: ['/admin', '/login'],
crawlDelay: 1,
sitemap: ['https://example.com/sitemap.xml']
},
{
userAgent: 'Googlebot',
allow: ['/'],
disallow: ['/admin', '/login'],
crawlDelay: 1,
sitemap: ['https://example.com/sitemap.xml']
}
]
);
console.log(robotsTxt);
// User-agent: *
// Allow: /
// Disallow: /admin
// Disallow: /login
// Crawl-delay: 1
// Sitemap: https://example.com/sitemap.xml
// User-agent: Googlebot
// Allow: /
// Disallow: /admin
// Disallow: /login
// Crawl-delay: 1
// Sitemap: https://example.com/sitemap.xml
Sitemap.xml (英语)
Sitemap.xml文件是一个告诉搜索引擎应该哪些页面索引的文件. 这对SEO有用,因为它有助于搜索引擎查找您网站上的所有页面.
import { generateSitemap } from '@forge42/seo-tools/sitemap';
const sitemap = generateSitemap(
{
domain: "https://example.com",
// Defines the routes you want to exclude from the sitemap (useful if routes are dynamic or auto-generated)
ignore: ["/dashboard*"]
// Defines the routes you want to include in the sitemap
routes: [
{ url: "/", lastmod: "2020-02-02", changefreq: "monthly", priority: 0.8 },
{ url: "/about", lastmod: "2020-02-02", changefreq: "monthly", priority: 0.8 },
{ url: "/contact", lastmod: "2020-02-02", changefreq: "monthly", priority: 0.8 }
],
// This is a transformer that allows you to generate the url you need
transformer: ({ url, domain }) => `${domain}${url}`
}
);
console.log(sitemap);
// <?xml version="1.0" encoding="UTF-8"?>
// <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
// <url>
// <loc>https://example.com/</loc>
// <lastmod>2020-02-02</lastmod>
// <changefreq>monthly</changefreq>
// <priority>0.8</priority>
// </url>
// <url>
// <loc>https://example.com/about</loc>
// <lastmod>2020-02-02</lastmod>
// <changefreq>monthly</changefreq>
// <priority>0.8</priority>
// </url>
// <url>
// <loc>https://example.com/contact</loc>
// <lastmod>2020-02-02</lastmod>
// <changefreq>monthly</changefreq>
// <priority>0.8</priority>
// </url>
// </urlset>
项目索引
网站映射索引是一个文件,它告诉搜索引擎在哪里找到您网站上的所有网站映射. 这对SEO有用,因为它有助于搜索引擎在您的网站上找到所有站点地图.
import { generateSitemapIndex } from '@forge42/seo-tools/sitemap';
const sitemapIndex = generateSitemapIndex([
{
url: 'https://example.com/sitemap1.xml',
lastmod: '2022-01-01'
},
{
url: 'https://example.com/sitemap2.xml',
lastmod: '2022-01-01'
}
]
);
console.log(sitemapIndex);
// <?xml version="1.0" encoding="UTF-8"?>
// <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
// <sitemap>
// <loc>https://example.com/sitemap1.xml</loc>
// <lastmod>2022-01-01</lastmod>
// </sitemap>
// <sitemap>
// <loc>https://example.com/sitemap2.xml</loc>
// <lastmod>2022-01-01</lastmod>
// </sitemap>
// </sitemapindex>
结构化数据
结构化数据是向搜索引擎提供您网站内容信息的一种方式. 这对SEO有用,因为它有助于搜索引擎了解您网站上的内容并在搜索结果中显示.
为了更好地了解结构化数据, 您可以在此找到您需要的所有信息 : https://developers.google.com/search/docs/exceptance/structured-data/intro-structured-data 互联网档案馆的存檔,存档日期2014-12-22
我们提供下列公用事业以生成结构化数据:
- 面包屑 -
import { breadcrumbs } from '@forge42/seo-tools/structured-data/breadcrumb'; - 第 - 条
import { article } from '@forge42/seo-tools/structured-data/article'; - 车 -
import { car } from '@forge42/seo-tools/structured-data/car'; - 当然
import { course } from '@forge42/seo-tools/structured-data/course'; - 数据集 -
import { dataset } from '@forge42/seo-tools/structured-data/dataset'; - 讨论-论坛
import { discussionForum } from '@forge42/seo-tools/structured-data/discussion-forum'; - 雇主评级
import { employerRating } from '@forge42/seo-tools/structured-data/employer-rating'; - 事件 -
import { event } from '@forge42/seo-tools/structured-data/event'; - 费克 -
import { faq } from '@forge42/seo-tools/structured-data/faq'; - 图像 -
import { image } from '@forge42/seo-tools/structured-data/image'; - 项目列表 -
import { itemList } from '@forge42/seo-tools/structured-data/item-list'; - 职位招聘
import { jobPosting } from '@forge42/seo-tools/structured-data/job-posting'; - 职业
import { occupation } from '@forge42/seo-tools/structured-data/occupation'; - 组织
import { organization } from '@forge42/seo-tools/structured-data/organization'; - 产品 -
import { product } from '@forge42/seo-tools/structured-data/product'; - 配置图 -
import { profile } from '@forge42/seo-tools/structured-data/profile'; - 贾 -
import { qa } from '@forge42/seo-tools/structured-data/qa'; - 食谱 -
import { recipe } from '@forge42/seo-tools/structured-data/recipe'; - 软件应用程序 -
import { softwareApp } from '@forge42/seo-tools/structured-data/software-app'; - 视频 -
import { video } from '@forge42/seo-tools/structured-data/video';
import { article } from '@forge42/seo-tools/structured-data/article';
const structuredData = article({
"@type": "Article",
"headline": "Article headline",
"image": "https://example.com/image.jpg",
"datePublished": "2022-01-01",
});
// Set it somehow in your html
<head>
<script type="application/ld+json">
{structuredData}
</script>
</head>
上面的例子会在搜索结果上方进行相关的google搜索时显示一篇文章.
Remix.run / 反应路由器 v7
我们为 Remix.run / React Router v7 设置了一个专用模块,可以帮助您实现 SEO 生成. 全部位于重混模块中,兼容 使用任何运行时间.
元数据
Meta数据是向搜索引擎提供您网站内容信息的一种方式. 这对SEO有用,因为它有助于搜索引擎了解您网站上的内容并在搜索结果中显示.
我们有一个轻量级的功能,可以帮助您避免为不同的平台多次写出相同的标记. 这将为您生成 twitter & og 标题和描述标签 。 也可以将结构化的数据添加到元标记中,例如下面的例子.
import { generateMeta } from "@forge42/seo-tools/remix/metadata";
import { article } from "@forge42/seo-tools/structured-data/article";
import { course } from "@forge42/seo-tools/structured-data/course";
export const meta: MetaFunction = () => {
// This utility will under the hood generate the twitter & og title and description tags for you.
const meta = generateMeta({
title: "test",
description: "test",
url: "test",
}, [
{
"script:ld+json": article({
"@type": "Article",
headline: "Article headline",
image: "https://example.com/image.jpg",
datePublished: "2021-01-01T00:00:00Z",
})
},
{
"script:ld+json": course({
"@type": "Course",
name: "Course name",
description: "Course description",
})
}
])
return meta
};
语句
此站点映射工具是上面站点映射工具的超级集. 它会根据所有的Remix路线为您生成站点图. 它无视 默认的根路由,任何带有站点映射名称和机器人.txt. 也可以通过自定义变压器生成需要的url. 欲了解更多信息,请参考上述站点图工具.
// routes/sitemap[.]xml.ts
import { generateRemixSitemap } from "@forge42/seo-tools/remix/sitemap"
export const loader = async() => {
const sitemap = await generateRemixSitemap({
domain: "https://example.com",
})
return new Response(sitemap, {
headers: {
"Content-Type": "application/xml",
},
})
}
处理动态路径
如果您想通过运行时创建动态路由在站点映射中生成不同的条目,您可以使用以下方法:
// routes/sitemap[.]xml.ts
import { generateRemixSitemap } from "@forge42/seo-tools/remix/sitemap"
export type SitemapData = {
lang: Language
}
export const loader = async ({ request }) => {
const sitemap = await generateRemixSitemap({
// This gets passed to every handler
sitemapData: {
"lang": request.query.get("lng") as Language
} satisfies SitemapData
})
return new Response(sitemap, {
headers: {
"Content-Type": "application/xml",
},
})
}
// routes/index.tsx
import type { SitemapHandle } from "@forge42/seo-tools/remix/sitemap";
import type { SitemapData } from "~/routes/sitemap[.]xml";
// This utility trumps the default url generation so it's important to at least return the current route from here.
export const handle: SitemapHandle<SitemapData> = {
sitemap: async (domain, url, { lang }) => {
const alternateLanguages = supportedLanguages.filter((language) => language !== lang)
return [
{
route: `${domain}${url}?lng=${lang}`,
changefreq: "monthly",
priority: 1.0,
// Create alternate links for each language
alternateLinks: alternateLanguages.map((lang) => ({
hreflang: lang,
href: `${domain}${url}?lng=${lang}`,
})),
},
]
},
}
处理站点地图索引+动态站点地图+机器人.txt
如果您想要根据语言生成不同的站点映射, 您可以使用以下方法:
// routes/sitemap.$lang[.]xml.ts
import type { LoaderFunctionArgs } from "@remix-run/node"
import { generateRemixSitemap } from "@forge42/seo-tools/remix/sitemap"
// Optionally import routes from the remix build to be consumed by the sitemap generator if the default one throws an error
import { routes } from "virtual:remix/server-build";
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
const domain = `${new URL(request.url).origin}`
const sitemap = await generateRemixSitemap({
// Domain to append urls to
domain,
routes,
// Ignores all dashboard routes
ignore: ["/status"],
// Transforms the url before adding it to the sitemap
urlTransformer: (url) => `${url}?lng=${params.lang}`,
sitemapData: {
lang: params.lang,
},
})
return new Response(sitemap, {
headers: {
"Content-Type": "application/xml; charset=utf-8",
},
})
}
// routes/sitemap-index[.]xml.ts
import type { LoaderFunctionArgs } from "@remix-run/node"
import { generateSitemapIndex } from "@forge42/seo-tools/sitemap"
export const loader = async ({ request }: LoaderFunctionArgs) => {
const domain = new URL(request.url).origin
const sitemaps = generateSitemapIndex([
{
url: `${domain}/sitemap/en.xml`,
lastmod: "2024-07-17",
},
{
url: `${domain}/sitemap/bs.xml`,
lastmod: "2024-07-17",
},
])
return new Response(sitemaps, {
headers: {
"Content-Type": "application/xml; charset=utf-8",
},
})
}
// routes/robots[.]txt.ts
import type { LoaderFunctionArgs } from "@remix-run/node"
import { generateRobotsTxt } from "@forge42/seo-tools/robots"
export async function loader({ request }: LoaderFunctionArgs) {
const isProductionDeployment = process.env.DEPLOYMENT_ENV === "production"
const domain = new URL(request.url).origin
const robotsTxt = generateRobotsTxt([
{
userAgent: "*",
[isProductionDeployment ? "allow": "disallow"]:["/"],
sitemap: [`${domain}/sitemap-index.xml`],
},
])
return new Response(robotsTxt, {
headers: {
"Content-Type": "text/plain",
},
})
}
许可证
捐款
欢迎拉动请求。 对于重大变动,请先开出一个问题来讨论你想要改变什么.
请确保酌情更新测试.
支助
如果你喜欢这个项目并且想要支持它,你可以在GitHub上赞助它,甚至更好的是,打开PR's,为这个项目捐款.