javascript - 在 Rollup.js 中导入整个目录的静态文件

标签 javascript rollup

我正在开发一个 TypeScript 库,并希望将构建过程从 webpack 迁移到 rollup。

在我的项目中,我有一个 SVG 图标目录,分为几个子目录。我的库应该导出一个 JavaScript 对象,其中包含所有这些图标的 SVG 代码。

对于 webpack,我使用 require.context递归地请求 SVG 文件(配置为 asset/source):

const context = require.context("../../assets/icons");
export const icons: Record<string, Record<string, string>> = {};
for (const key of context.keys() as string[]) {
    const [set, fname] = key.split("/").slice(-2);

    if (!icons[set])
        icons[set] = {};

    icons[set][fname.replace(/\.svg$/, "")] = context(key);
}

如何通过汇总实现此目的?

到目前为止我有几个想法:

  • rollup-plugin-require-context应该将 require.context 引入汇总。然而,它似乎有缺陷并且无法维护,并且在我的测试中它根本没有转换 require.context 调用。
  • rollup-plugin-glob-import似乎适合递归导入目录。我试图将它与 rollup-plugin-string 一起使用以纯文本形式导入 SVG 文件。然而,无论我以什么顺序定义它们,这两个插件似乎都无法相互通信。 glob 导入插件提示我的 SVG 文件没有任何导出。

最佳答案

解决方案 1:rollup-plugin-glob-import

使用rollup-plugin-glob-importrollup-plugin-string 结合以正确的方式配置即可工作。

rollup-plugin-string 生成以字符串作为默认导出的模块,因此 format: 'default' 必须用于 rollup-plugin- glob-import 以正确导入它们。如果子目录路径应保留在生成的包的命名导出中,则可以使用自定义 rename 函数(请注意,导出名称需要是有效的 JavaScript 变量名称,因此使用 驼峰命名法):

import { defineConfig } from 'rollup';
import globImport, { camelCase } from 'rollup-plugin-glob-import';
import { string } from 'rollup-plugin-string';

export default defineConfig({
    ...
    plugins: [
        string({
            include: "assets/icons/**/*.svg"
        }) as any,
        globImport({
            format: 'default',
            rename: (name, id) => name || `${camelCase(basename(dirname(id)))}_${camelCase(basename(id, extname(id)))}`
        })
    ]
});

rollup-plugin-glob-import 生成命名导出,但没有默认导出,因此可以像这样导入导出的文件:

import * as icons from '../../assets/icons/**/*.svg';

解决方案 2:自定义插件

编写自定义 Rollup 插件并不困难,并且具有更大的灵活性。特别是,它可用于导出单个 JSON 对象,而不是每个文件一个命名导出(其名称受 JavaScript 变量名称允许的字符限制)。

在此示例中,我提供了一个名为 custom:icons 的模块,该模块具有包含所有文件的默认导出:

import { defineConfig } from "rollup";
import glob from 'fast-glob';
import { readFile } from 'fs/promises';

export default defineConfig({
    ...
    plugins: [
        {
            name: 'custom:icons',
            resolveId: (id) => {
                if (id === 'custom:icons') {
                    return id;
                }
            },
            load: async (id) => {
                if (id === 'custom:icons') {
                    const icons: Record<string, Record<string, string>> = {};
                    for (const path of await glob('./assets/icons/*/*.svg')) {
                        const [set, fname] = path.split("/").slice(-2);

                        if (!icons[set])
                            icons[set] = {};

                        icons[set][fname.replace(/\.svg$/, "")] = (await readFile(path)).toString();
                    }
                    return `export default ${JSON.stringify(icons, undefined, '\t')}`;
                }
            }
        }
    ]
});

然后可以像这样导入自定义模块:

import icons from 'custom:icons';

关于javascript - 在 Rollup.js 中导入整个目录的静态文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72161807/

相关文章:

socket.io - 如何让 Socket.io 与 Svelte 一起工作?

javascript - 关闭浏览器或窗口时如何触发 Angularjs 事件?

angularjs - npm run rollup 显示错误消息 "Module ag-grid-ng2/main.js does not export AgGridModule"。?

javascript - jQuery 日期范围之间的天数

javascript - Testcafe 从元素中获取文本

reactjs - 使用 Rollup 和 Sass react 可摇树的组件库

javascript - 使用 uglify 保持 javascript 包文件美化

tsql - 如何在新列中显示汇总数据?

javascript - CKEditor, 'enhancedcolorbuttton' 插件导致加载问题

javascript - jquery 在 2 个 div 周围添加包装 div,其中内容可以是可变长度