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


    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

    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">
    <% urls.forEach(function(item) { %>
    <%= item.loc %>
    <%= item.time %>
    monthly
    0.8
    <% }); %>
  • 相关阅读:
    C++ 运算符
    项目实战:组件扫描(4)-筛选带有RequestMapping注解的bean实例
    在线演示前端demo | github如何搭建个人vue项目进行展示
    Redis----布隆过滤器
    金融强化学习与finRL开发包
    分治法、动态规划、贪心算法区别
    spring tx:advice事务配置—— tx:advice中不允许出现属性 ‘transaction-manager‘
    springboot实现转发和重定向
    cookie和session区别
    Java计算机毕业设计电影院购票系统源码+系统+数据库+lw文档
  • 原文地址:https://www.cnblogs.com/bxmm/p/17759702.html