我正在开发一个 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-import与 rollup-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/