Nuxt.js 生成sitemap站点地图文件

nuxt,js,生成,sitemap,站点,地图,文件 · 浏览次数 : 52

小编点评

**代码摘要** ```js // 1、加载当前目录下所有路径,包含文件夹和文件 const data = loadFiles(dir); // 2、拼接绝对路径 const absolutePath = path.join(dir, item) // 3、获取文件基本信息 const stat = statFile(absolutePath); // 4、如果是文件,处理基本信息 if (stat.isFile()) { // 5、获取文件大小和时间 list.push({ size: stat.size, time: stat.ctime, ...path.parse(stat.path) }) } // 5、目录递归进行处理 handleFiles(stat.path, list, excludes); ``` **主要代码** 1. **加载当前目录下所有路径**:使用 `loadFiles` 函数加载当前目录下所有路径,并将其存储在 `data` 中。 2. **拼接绝对路径**:使用 `path.join` 函数拼接绝对路径,并将其存储在 `absolutePath` 中。 3. **获取文件基本信息**:使用 `statFile` 函数获取文件基本信息,并将其存储在 `stat` 中。 4. **如果是文件,处理基本信息**:如果文件是,使用 `stat` 获取文件大小和时间,并将其存储在 `list` 中。 5. **目录递归进行处理**:使用 `handleFiles` 函数递归处理所有目录路径,并将其存储在 `list` 中。 **关键函数** * `loadFiles`:加载当前目录下所有路径。 * `path.join`:拼接绝对路径。 * `statFile`:获取文件基本信息。 * `handleFiles`:处理所有目录路径。 **其他** * 代码使用 `ejs` 模板引擎对 HTML 模板进行渲染。 * `nuxt` 模块提供 `generate:done` 事件,用于执行生成完成后的操作。

正文

Nuxt.js 生成sitemap站点地图文件

背景介绍

​ 使用nuxt框架生成静态文件支持SEO优化,打包之后需要生成一个 sitemap.xml 文件方便提交搜索引擎进行收录。官网有提供一个插件sitemap 但是如果是动态路由需要手动一个个配置比较麻烦,无法自动检索生成。所以自己编写一个生成 sitemap 模块

准备工作

创建nuxt项目,参考中文官网。安装JavaScript模板ejs工具

$ npm install ejs

相关网站

sitemap模块

项目根目录创建 modules 目录,以及对应文件,详细文件内容放在文末。

├─modules
│  └─robots.ejs // robots模板
│  └─sitemap.js // 站点地图js
│  └─template.ejs //sitemap 模板

配置 nuxt.config.js

modules 数组增加以下内容 modules/sitemap 刚才自定义模块,excludes 需要排除的目录,hostname 站点域名

nuxt.config.js

export default {
  ...省略
  // Modules: https://go.nuxtjs.dev/config-modules
  modules: [
    ...省略,
    ['modules/sitemap',
      {
        excludes: ['_nuxt', 'img'],
        hostname: 'https://www.example.com'
      }
    ],
  ],
}

执行命令生成静态资源

$npm run generate

打开项目根目录下dist(默认输出路径),会多出两个文件

├─robots.txt
├─sitemap.xml

结果展示

sitemap

robots

官方示例 modules

编写自己的模块

模块就是函数。它们可以打包为 npm 模块或直接包含在项目源代码中。

nuxt.config.js

export default {
  exampleMsg: 'hello',
  modules: [
    // Simple usage
    '~/modules/example',
    // Passing options directly
    ['~/modules/example', { token: '123' }]
  ]
}

modules/example.js

export default function ExampleModule(moduleOptions) {
  console.log(moduleOptions.token) // '123'
  console.log(this.options.exampleMsg) // 'hello'

  this.nuxt.hook('ready', async nuxt => {
    console.log('Nuxt is ready')
  })
}

// REQUIRED if publishing the module as npm package
module.exports.meta = require('./package.json')

1) ModuleOptions

moduleOptionsmodules 这是用户使用数组传递的对象 。我们可以用它来定制它的行为。

顶级选项

有时,如果我们可以在注册模块时使用顶级选项会更方便 nuxt.config.js。这使我们能够组合多个选项源。

nuxt.config.js

export default {
  modules: [['@nuxtjs/axios', { anotherOption: true }]],

  // axios module is aware of this by using `this.options.axios`
  axios: {
    option1,
    option2
  }
}

2) this.options

this.options:您可以使用此参考直接访问 Nuxt 选项。nuxt.config.js 这是分配有所有默认选项的用户内容 。它可用于模块之间的共享选项。

模块.js

export default function (moduleOptions) {
  // `options` will contain option1, option2 and anotherOption
  const options = Object.assign({}, this.options.axios, moduleOptions)

  // ...
}

modules文件

modules/robots.ejs

# robots.txt
User-agent: Baiduspider
Disallow:
User-agent: Sosospider
Disallow:
User-agent: sogou spider
Disallow:
User-agent: YodaoBot
Disallow:
User-agent: Googlebot
Disallow:
User-agent: Bingbot
Disallow:
User-agent: Slurp
Disallow:
User-agent: Teoma
Disallow:
User-agent: ia_archiver
Disallow:
User-agent: twiceler
Disallow:
User-agent: MSNBot
Disallow:
User-agent: Scrubby
Disallow:
User-agent: Robozilla
Disallow:
User-agent: Gigabot
Disallow:
User-agent: googlebot-image
Disallow:
User-agent: googlebot-mobile
Disallow:
User-agent: yahoo-mmcrawler
Disallow:
User-agent: yahoo-blogs/v3.9
Disallow:
User-agent: psbot
Disallow:
Disallow: /bin/
Disallow: /js/
Disallow: /img/
Sitemap: <%= hostname %>/sitemap.xml

modules/sitemap.js

/**
 * @description 生成 sitemap robots 模块
 * @author 方圆百里
 * @time 2023年10月12日
 */

const path = require('path');
const fs = require('fs');
const ejs = require('ejs');
/**
 * @description 获取当前目录下载的所有路径 -同步
 * @author 方圆百里
 *
 * @param {String} dir 文件路径
 * @returns {Array} 返回路径数组
 */
const loadFiles = (dir) => {
  try {
    const data = fs.readdirSync(dir);
    return data;
  } catch (e) {
    console.error('获取目录路径异常', e)
    return undefined;
  }
}

/**
 * @description 获取文件信息
 * @author 方圆百里
 *
 * @param {String} dir 文件路径
 * @returns {Array} 返回路径数组
 */
const statFile = (full_path) => {
  try {
    const stat = fs.statSync(full_path);
    stat.path = full_path;
    return stat;
  } catch (e) {
    console.error('获取目录路径异常', e)
    return undefined;
  }
}

/**
 * @description 递归处理文件路径
 * @author 方圆百里
 *
 * @param {String} dir 文件路径
 * @param {String} list 文件信息数组
 * @returns {Array} 返回路径数组
 */
const handleFiles = (dir, list = [], excludes) => {
  // 1、加载当前目录下所有路径,包含文件夹和文件
  const data = loadFiles(dir);
  if (data) {
    data.forEach(item => {
      if (!excludes.includes(item)) {
        // 2、拼接绝对路径
        const absolutePath = path.join(dir, item)
        // 3、获取文件基本信息
        const stat = statFile(absolutePath);
        // 4、如果是文件,处理基本信息
        if (stat.isFile()) {
          list.push({
            size: stat.size,
            time: stat.ctime,
            ...path.parse(stat.path)
          })
        } else { // 5、目录递归进行处理
          handleFiles(stat.path, list, excludes);
        }
      }
    })
  }
  return list;
}

/**
 * @description 格式化日期
 * @author 方圆百里
 *
 * @param {Date} date 日期
 * @returns {String} 2023-10-12
 */
const formatYear = (date) => {
  // 获取年、月和日
  const year = date.getFullYear();
  const month = (date.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始,需要加1,同时确保两位数格式
  const day = date.getDate().toString().padStart(2, '0'); // 确保两位数格式
  // 格式化日期
  return `${year}-${month}-${day}`;
}

/**
 * @description 生成站点地图
 * @author 方圆百里
 *
 * @param {String} dist 打包后文件路径
 * @param {String} hostname 主机名称
 * @param {Array} excludes 排除路径
 *
 */
const generateSitemap = (dist, hostname, excludes) => {
  const data = handleFiles(dist, [], excludes)
  const set = new Set();
  for (var i = 0; i < data.length; i++) {
    const f = data[i];
    if (f.ext === '.html') {
      const relative = f.dir.replace(dist, "")
      if (relative) {
        const paths = relative.split(path.sep);
        let loc = hostname;
        for (var x = 1; x < paths.length; x++) {
          loc += "/" + paths[x];
        }
        set.add({
          loc: loc,
          time: formatYear(f.time)
        });
      }
    }
  }
  // 读取模板文件
  const template = fs.readFileSync('modules/template.ejs', 'utf-8');
  // 提供模板数据
  const datas = {
    urls: set
  };
  // 使用模板引擎渲染模板
  const renderedContent = ejs.render(template, datas);
  // 写入生成的文件
  fs.writeFileSync(path.join(dist, 'sitemap.xml'), renderedContent);
  console.log('sitemap.xml 生成成功!');

  const robotsRendered = ejs.render(fs.readFileSync('modules/robots.ejs', 'utf-8'), {
    hostname
  });
  // 写入生成的文件
  fs.writeFileSync(path.join(dist, 'robots.txt'), robotsRendered);
  console.log('robots.txt 生成成功!');
}
export default function ExampleModule(moduleOptions) {
  const dist = this.options.generate?.dir || 'dist'; // 打包输出路径
  const hostname = moduleOptions.hostname || 'https://www.example.com'; // 主机名称
  const excludes = moduleOptions.excludes || ['.nuxt']; // 排除路径
  console.log('打包输出路径:=====>', dist)
  console.log('主机名称:=====>', hostname)
  console.log('排除路径:=====>', excludes)

  this.nuxt.hook('generate:done', async generator => {
    // 这将在Nuxt生成页面之之后调用
    console.log('执行 generate 完成')
    generateSitemap(dist, hostname, excludes)

  })
}

// 将模块发布为npm包
module.exports.meta = require('../package.json')

modules/template.ejs

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
  xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"
  xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
  xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
  <url>
    <% urls.forEach(function(item) { %>
       <loc><%= item.loc %></loc>
       <lastmod><%= item.time %></lastmod>
       <changefreq>monthly</changefreq>
       <priority>0.8</priority>
    <% }); %>
  </url>
</urlset>

与Nuxt.js 生成sitemap站点地图文件相似的内容:

Nuxt.js 生成sitemap站点地图文件

Nuxt.js 生成sitemap站点地图文件 背景介绍 ​ 使用nuxt框架生成静态文件支持SEO优化,打包之后需要生成一个 sitemap.xml 文件方便提交搜索引擎进行收录。官网有提供一个插件sitemap 但是如果是动态路由需要手动一个个配置比较麻烦,无法自动检索生成。所以自己编写一个生成

Nuxt.js头部魔法:轻松自定义页面元信息,提升用户体验

title: Nuxt.js头部魔法:轻松自定义页面元信息,提升用户体验 date: 2024/7/16 updated: 2024/7/16 author: [ cmdragon ](https://cmdragon.cn) excerpt: 摘要:“Nuxt.js头部魔法:轻松自定义页面元信息,

Nuxt.js 深入浅出:目录结构与文件组织详解

摘要:本文详述了Nuxt.js框架中关键目录与配置文件的作用及使用方法,包括布局设定、页面结构管理、插件集成、静态资源处理、 Vuex状态管理、项目配置文件nuxt.config.js详解以及package.json、.eslintrc.js、.babelrc等辅助配置文件的配置方式,为构建高效Nu...

轻松掌握useAsyncData获取异步数据

摘要:本文详细介绍Nuxt.js中的useAsyncData组合式函数,它用于在服务端渲染(SSR)过程中异步获取数据,确保客户端正确水合,避免重复请求。内容包括基本概念、参数说明(key, handler, options)、示例用法、如何监听参数变化自动刷新数据及返回值详解,展示了在页面组件中使...

Nuxt3 的生命周期和钩子函数(二)

摘要:本文深入介绍了Nuxt.js框架中几个关键的生命周期钩子函数,包括app:redirected(SSR环境下重定向前触发)、app:beforeMount(CSR下应用挂载前)、app:mounted(CSR下Vue应用在浏览器挂载时)、app:suspense:resolve(CSR中Sus...

初学者必读:如何使用 Nuxt 中间件简化网站开发

本文概述了Nuxt 3框架的升级特点,对比Nuxt 2,详细解析中间件应用、配置策略与实战示例,涵盖功能、错误管理、优化技巧,并探讨与Nuxt 3核心组件集成方法,给出最佳实践和问题解决方案,强调利用Vue 3和Serverless Functions提升中间件效能。

掌握 Nuxt 3 中的状态管理:实践指南

摘要:该文指南详述了Nuxt 3的概况与安装,聚焦于在Nuxt 3框架下运用Vuex进行高效的状态管理,涵盖基础配置、模块化实践至高阶策略,助力开发者构建高性能前后端分离应用。

Nuxt 3 路由系统详解:配置与实践指南

摘要:本文是一份关于Nuxt 3路由系统的详尽指南。它从介绍Nuxt 3的基本概念开始,包括Nuxt 3与Nuxt 2的区别和选择Nuxt 3的理由。然后,它详细解释了安装和配置Nuxt 3的步骤,以及Nuxt 3路由系统的基础知识,如动态路由和嵌套路由。接着,它介绍了路由中间件的作用和编写自定义中...

Nuxt 3组件开发与管理

摘要:本文深入探讨了Nuxt 3的组件开发与管理,从基础概念、安装配置、目录结构、组件分类与开发实践、生命周期与优化,到测试与维护策略。详细介绍了Nuxt 3的核心特点,如服务器端渲染(SSR)、静态站点生成(SSG)以及与Vue生态系统的无缝集成。文章以Nuxt 3为基础,指导开发者如何高效构建高...

nuxt3正确使用keepalive页面缓存组件缓存

最近使用 nuxt@3.x 版本做SEO优化项目比较多,之前也踩坑过,所以记录一下在 nuxt3 中路由缓存的正确使用方法,本人也之前在GitHub社区中提交过反馈问题,最后是在 3.8.2 版本解决了路由缓存问题。下面讲解如何正确使用keepalive做到页面缓存,组件缓存。 # 环境版本如下 n