Estoy desarrollando una biblioteca de TypeScript y quiero migrar el proceso de compilación del paquete web al resumen.
En mi proyecto, tengo un directorio de iconos SVG, ordenados en varios subdirectorios. Mi biblioteca debería exportar un objeto JavaScript que contenga el código SVG de todos estos íconos.
Con webpack, estaba usando require.context para requerir recursivamente los archivos SVG (que se configuraron como 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); }¿Cómo puedo lograr esto con rollup?
He tenido varias ideas hasta ahora:
require.context al resumen. Sin embargo, parece tener errores y falta de mantenimiento, y en mis pruebas no transformó la llamada require.context en absoluto.rollup-plugin-glob-importEl uso de rollup-plugin-glob-import en combinación con rollup-plugin-string funciona cuando se configura de la manera correcta.
rollup-plugin-string genera módulos con una cadena como su exportación predeterminada, por lo que se debe usar format: 'default' para rollup-plugin-glob-import para importarlos correctamente. Si las rutas de los subdirectorios deben conservarse en las exportaciones con nombre del paquete resultante, se puede usar una función de cambio de rename personalizado (tenga en cuenta que el nombre de la exportación debe ser un nombre de variable de JavaScript válido, de ahí el uso de camelCase aquí):
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 genera exportaciones con nombre pero no una exportación predeterminada, por lo que los archivos exportados se pueden importar de esta manera:
import * as icons from '../../assets/icons/**/*.svg';Escribir un complemento de resumen personalizado no es difícil y permite una mayor flexibilidad. En particular, se puede usar para exportar un solo objeto JSON en lugar de una exportación con nombre por archivo (cuyo nombre está restringido por los caracteres permitidos para los nombres de variables de JavaScript).
En este ejemplo, proporciono un módulo llamado custom:icons , que tiene una exportación predeterminada que contiene todos los archivos:
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')}`; } } } ] });El módulo personalizado se puede importar así:
import icons from 'custom:icons';