关于seo:低成本单页应用-SEOSimpleSpaSeo
背景本我的项目,低成本预渲染: 非侵入式,无需改变业务代码屏蔽框架差别,无依赖,单文本实现,间接拷贝粘贴本脚本即可实现性能简略,开源代码,无编译,脚本代码量仅一百多行,二次集成门槛低,代码清晰易懂留神本我的项目仅适宜低成本的中小型我的项目,大型商业我的项目可参考以下成熟计划SSG 预渲染:Prerender SPA Plugin,和本工具相似,但集成了 puppeteer,主动运行我的项目,截取内容,生产页面元素SSR 服务端渲染:Next.js React 应用程序的服务器渲染框架,Nuxt.js Vue.js 应用程序的服务器渲染框架 成果在指定目录生成与 index.html 为模版的入口文件在每个入口文件中,实现各自定制的 seo 配置,实现 title、keywords、description 等信息的自定义 性能【pageLinkNum】主动生成页面间的超链接跳转,实现页面间关联成果,设置为 0 则敞开该性能【path】须要对外裸露的门路,脚本将主动在相对路径生成对应入口文件。留神,无需刻意携带文件后缀,通过后文 nginx 的一行配置,可将无后缀文件对立以 html 文件类型返回。让浏览器失常解析。【title】指定页面的 title,<title>m3u8 downloader</title>【keywords】指定页面的 seo 关键字,<meta name="keywords" content="m3u8 下载工具,毛静文的博客,Momo's Blog">【description】指定页面的 seo 摘要,<meta name="description" content="无需后端反对,一个页面即可实现 m3u8 视频下载,遍历下载 ts 碎片,实现 ts 碎片文件整合,生成残缺视频文件。">【img】设置页面的图片,实现搜索引擎收录,展现成果时,展现缩略图【link】设置页面的超链接跳转,使得搜索引擎的蜘蛛爬虫能够依照超链接找到零碎中其余页面的链接,提供相干页面的入口【content】设置页面主体文案内容,使得搜索引擎可匹配关键字【html】其余自定义标签,提供自定义插入特定 html 代码性能{ path: '/m3u8-downloader/index.html', // 拜访链接 title: 'm3u8 downloader', keywords: "m3u8 下载工具,毛静文的博客,Momo's Blog", description: '无需后端反对,一个页面即可实现 m3u8 视频下载,遍历下载 ts 碎片,实现 ts 碎片文件整合,生成残缺视频文件。', // 页面形容 img: [ 'https://upyun.luckly-mjw.cn/Assets/blog/m3u8-downloader-121-75.jpeg', 'https://upyun.luckly-mjw.cn/Assets/blog/m3u8-downloader.jpeg' ], link: [{ text: '点击这里跳转', href: '/tool-show/nginx-online-config-debug/index.html', }], content: [{ tag: 'h1', text: '特大视频原格局下载,边下载边保留,彻底解决大文件下载内存不足问题', }, { tag: 'div', text: '举荐一个 m3u8 网页版提取工具,无需下载软件,关上网站即可下载,自动检测,一键下载。', }], html: ` 页面加载中,请急躁期待... <h1 style="white-space: pre;"> 举荐一个 m3u8 网页版提取工具,无需下载软件,关上网站即可下载,自动检测,一键下载。 工具链接:https://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html 工具教程:https://segmentfault.com/a/1190000021847172?_ea=32289224 <img src="https://upyun.luckly-mjw.cn/Assets/blog/m3u8-downloader-121-75.jpeg" alt="m3u8 视频下载工具" title="logo"/> <a target="_blank" href="https://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html">点击跳转</a> </h1>`, }用法拷贝我的项目的 seo.js 文件,批改配置项执行脚本,node seo.js集成 package script增加 nginx 配置,default_type text/html; 使无后缀文件以 html 类型返回源代码/* eslint-disable prettier/prettier */const fs = require('fs');const path = require('path');const pageLinkNum = 3; // 主动生成页面间的超链接跳转的个数,设置为 0 则敞开该性能const appendTagId = 'app'; // 页面 seo 元素(超链接,图片,文字等)插入的容器 idconst outputBasePath = path.join(__dirname, 'dist'); // 新建的 seo 入口文件,放在那个文件夹下const templatePath = path.join(__dirname, 'dist', 'index.html'); // 以那个文件作为模版,个别是 spa 我的项目的 index.html 文件// SEO 参考资料:https://github.com/madawei2699/awesome-seo/blob/main/README_CN.md// 定义数组对象const pageConfigs = [ { // 参考资料:https://developers.google.com/search/docs/crawling-indexing/url-structure?hl=zh-cn path: '/m3u8-downloader/index.html', // 拜访链接 // 页面题目:搜索引擎通常显示页面题目的前 55 至 60 个字符,超出此范畴的文本可能会失落 // 参考资料:https://developers.google.com/search/docs/appearance/title-link?hl=zh-cn // 参考资料:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title#page_titles_and_seo title: 'm3u8 downloader', // 页面关键字,google 曾经弃用该字段 // https://zhuanlan.zhihu.com/p/382454488 // https://developers.google.com/search/docs/crawling-indexing/special-tags?hl=zh-cn keywords: "m3u8 下载工具,毛静文的博客,Momo's Blog", // 页面摘要 // https://developers.google.com/search/docs/appearance/snippet?hl=zh-cn description: '无需后端反对,一个页面即可实现 m3u8 视频下载,遍历下载 ts 碎片,实现 ts 碎片文件整合,生成残缺视频文件。', // 页面形容 // 自定插入的图片 img: [ 'https://upyun.luckly-mjw.cn/Assets/blog/m3u8-downloader-121-75.jpeg', 'https://upyun.luckly-mjw.cn/Assets/blog/m3u8-downloader.jpeg' ], // 自定义超链接跳转 // 参考资料:https://developers.google.com/search/docs/appearance/sitelinks?hl=zh-cn link: [{ text: '点击这里跳转', href: '/tool-show/nginx-online-config-debug/index.html', }], // 自定义插入的标签 content: [{ tag: 'h1', text: '特大视频原格局下载,边下载边保留,彻底解决大文件下载内存不足问题', }, { tag: 'div', text: '举荐一个 m3u8 网页版提取工具,无需下载软件,关上网站即可下载,自动检测,一键下载。', }], // 自定义插入的 html // 参考资料:https://zhuanlan.zhihu.com/p/391844443 html: ` 页面加载中,请急躁期待... <h1 style="white-space: pre;"> 举荐一个 m3u8 网页版提取工具,无需下载软件,关上网站即可下载,自动检测,一键下载。 工具链接:https://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html 工具教程:https://segmentfault.com/a/1190000021847172?_ea=32289224 <img src="https://upyun.luckly-mjw.cn/Assets/blog/m3u8-downloader-121-75.jpeg" alt="m3u8 视频下载工具" title="logo"/> <a target="_blank" href="https://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html">点击跳转</a> </h1>`, },];// 生成页面间随机页面跳转pageLinkNum && pageConfigs.forEach(config => { config.link = config.link || []; const pageLinks = [...pageConfigs]; for (let index = 0; index < Math.min(pageConfigs.length, pageLinkNum); index++) { const pageConfig = pageLinks.splice(Math.floor(Math.random() * pageLinks.length), 1)[0]; config.link.push({ // 自定义插入的标签 text: pageConfig.title || pageConfig.keywords || pageConfig.description, href: pageConfig.path, }) }})const appendTagRegex = new RegExp(`(id="${appendTagId}"[^>]*>)`);const templateStr = fs.readFileSync(templatePath, 'utf8');pageConfigs.forEach(data => { // 读取指标文件内容 let fileContent = templateStr; // 替换 title 标签 if (data.title) { fileContent = fileContent.replace(/<title>.*<\/title>/, `<title>${data.title}</title>`); } // 替换 meta name="keywords" 标签 if (data.keywords) { fileContent = fileContent.replace(/name="keywords"[^>]+/, `name="keywords" content="${data.keywords}"`); } // 替换 meta name="description" 标签 if (data.description) { fileContent = fileContent.replace(/name="description"[^>]+/, `name="description" content="${data.description}"`); } // 插入自定义 html 标签 if (data.html) { fileContent = fileContent.replace(appendTagRegex, `$1\n${data.html}`); } // 插入 content 标签 if (data.content) { const contentTags = data.content.map(contentConf => typeof contentConf === 'object' ? `\n<${contentConf.tag}>${contentConf.text}</${contentConf.tag}>` : `\n<div>${content}</div>`).join(''); fileContent = fileContent.replace(appendTagRegex, `$1${contentTags}`); } // 插入 a 标签,设置超链接跳转 if (data.link) { const aTags = data.link.map(linkConf => `\n<a target="_blank" href="${linkConf.href}">${linkConf.text}</a>`).join(''); fileContent = fileContent.replace(appendTagRegex, `$1${aTags}`); } // 插入 img 标签 if (data.img) { const imgTags = data.img.map(imgUrl => `\n<img src="${imgUrl}"/>`).join(''); fileContent = fileContent.replace(appendTagRegex, `$1${imgTags}`); } // 将批改后的内容写入指标文件 const targetPath = path.join(outputBasePath, data.path); fs.mkdirSync(targetPath.substring(0, targetPath.lastIndexOf('/')), { recursive: true }); fs.writeFileSync(targetPath, fileContent, 'utf8'); console.log(`SEO 入口文件生成:${targetPath}`);}); ...