/// import dts from 'vite-plugin-dts'; import { copyFileSync } from 'node:fs'; import { defineConfig, LibraryOptions, LibraryFormats, Plugin } from 'vite'; import glob from 'fast-glob'; import { build, Format } from 'esbuild'; import { resolve } from 'path'; import { umdWrapper } from 'esbuild-plugin-umd-wrapper'; // don't empty out dir if --watch flag is passed const emptyOutDir = !process.argv.includes('--watch'); function minifyAndUMDPlugin({ name, outDir, }: { name: LibraryOptions['name']; outDir: string; }): Plugin { return { name: 'minify-plugin', async writeBundle(outputOptions, bundle) { for (const file of Object.values(bundle)) { if ( file.type === 'asset' && (file.fileName.endsWith('.cjs.map') || file.fileName.endsWith('.css')) ) { const isCSS = file.fileName.endsWith('.css'); const inputFilePath = resolve( outputOptions.dir!, file.fileName, ).replace(/\.map$/, ''); const baseFileName = file.fileName.replace( /(\.cjs|\.css)(\.map)?$/, '', ); const outputFilePath = resolve(outputOptions.dir!, baseFileName); // console.log(outputFilePath, 'minifying', file.fileName); if (isCSS) { await buildFile({ input: inputFilePath, output: `${outputFilePath}.min.css`, minify: true, isCss: true, outDir, }); } else { await buildFile({ name, input: inputFilePath, output: `${outputFilePath}.umd.cjs`, minify: false, isCss: false, outDir, }); await buildFile({ name, input: inputFilePath, output: `${outputFilePath}.umd.min.cjs`, minify: true, isCss: false, outDir, }); } } } }, }; } async function buildFile({ name, input, output, minify, isCss, outDir, }: { name?: LibraryOptions['name']; input: string; output: string; outDir: string; minify: boolean; isCss: boolean; }) { await build({ entryPoints: [input], outfile: output, minify, sourcemap: true, format: isCss ? undefined : ('umd' as Format), target: isCss ? undefined : 'es2017', treeShaking: !isCss, plugins: [ umdWrapper({ libraryName: name, }), ], }); const filename = output.replace(new RegExp(`^.+/(${outDir}/)`), '$1'); console.log(filename); console.log(`${filename}.map`); } export default function ( entry: LibraryOptions['entry'], name: LibraryOptions['name'], options?: { outputDir?: string; fileName?: string; plugins?: Plugin[] }, ) { const { fileName, outputDir: outDir = 'dist', plugins = [] } = options || {}; let formats: LibraryFormats[] = ['es', 'cjs']; return defineConfig(() => ({ build: { // See https://vitejs.dev/guide/build.html#library-mode lib: { entry, name, fileName, // TODO: turn on `umd` for rrweb when https://github.com/schummar/vite/tree/feature/libMultiEntryUMD gets merged // More info: https://github.com/vitejs/vite/pull/7047#issuecomment-1288080855 // formats: ['es', 'umd', 'cjs'], formats, }, outDir, emptyOutDir, // Leaving this unminified so you can see what exactly gets included in // the bundles minify: false, sourcemap: true, // rollupOptions: { // output: { // manualChunks: {}, // }, // }, }, plugins: [ dts({ insertTypesEntry: true, rollupTypes: true, afterBuild: (emittedFiles: Map) => { // To pass publint (`npm x publint@latest`) and ensure the // package is supported by all consumers, we must export types that are // read as ESM. To do this, there must be duplicate types with the // correct extension supplied in the package.json exports field. const files: string[] = Array.from(emittedFiles.keys()); files.forEach((file) => { const ctsFile = file.replace('.d.ts', '.d.cts'); copyFileSync(file, ctsFile); }); }, }), minifyAndUMDPlugin({ name, outDir }), ...plugins, ], })); }