diff --git a/src/api.ts b/src/api.ts index 1b04697..510579c 100644 --- a/src/api.ts +++ b/src/api.ts @@ -11,6 +11,7 @@ const debug = { load: createDebugger('image-presets:load'), write: createDebugger('image-presets:write'), total: createDebugger('image-presets:total'), + cache: createDebugger('image-presets:cache'), } export const VIRTUAL_ID = '/@imagepresets/' @@ -25,14 +26,35 @@ export function createImageApi (config: Config) { const imageFilenamesById: Record> = {} return { + get config () { + return config + }, async getImageById (id: string) { return await requestedImagesById[id] }, async waitForImages () { debug.total('%i image(s)', generatedImages.length) - const assets = await Promise.all(generatedImages) - cleanCacheDir(assets.map(asset => asset.name!)) - return assets + return await Promise.all(generatedImages) + }, + async writeImages (outDir: string) { + const images = await Promise.all(generatedImages.map(async imagePromise => { + const image = await imagePromise + fs.writeFile(join(outDir, image.fileName), image.source) + return image + })) + this.purgeCache(images) + }, + async purgeCache (assets: OutputAsset[]) { + if (!config.purgeCache) + return + + const usedFiles = new Set(assets.map(asset => asset.name!)) + const cachedFiles = await fs.readdir(config.cacheDir) + const unusedFiles = cachedFiles.filter(file => !usedFiles.has(file)) + debug.cache('%i unused files', unusedFiles.length) + unusedFiles.forEach(file => { + fs.rm(resolve(config.cacheDir, file), { force: true }) + }) }, async resolveImage (filename: string, params: Record): Promise { const presetName = params[config.urlParam] @@ -83,9 +105,8 @@ export function createImageApi (config: Config) { } async function writeImageFile (filename: string, image: Image): Promise { - const { cacheDir, assetsDir, outDir } = config + const { cacheDir, assetsDir } = config const cachedFilename = join(cacheDir, filename) - const destFilename = join(outDir, assetsDir, filename) if (!await exists(cachedFilename)) { debug.write('%s', filename) @@ -93,7 +114,7 @@ export function createImageApi (config: Config) { } return { - fileName: relative(config.outDir, destFilename), + fileName: join(config.assetsDir, filename), name: filename, source: await fs.readFile(cachedFilename) as any, isAsset: true, @@ -115,13 +136,4 @@ export function createImageApi (config: Config) { return VIRTUAL_ID + id } - - async function cleanCacheDir (newFiles: string[]) { - const usedFiles = new Set(newFiles) - const cachedFiles = await fs.readdir(config.cacheDir) - cachedFiles.forEach(file => { - if (!usedFiles.has(file)) - fs.rm(resolve(config.cacheDir, file), { force: true }) - }) - } } diff --git a/src/index.ts b/src/index.ts index 8875ac2..0e7b647 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,15 +20,18 @@ export default function ImagePresetsPlugin (presets?: ImagePresets, options?: Op name: 'image-presets', enforce: 'pre', get api () { return api }, - async configResolved ({ base, command, root, build: { outDir, assetsDir } }) { + async configResolved ({ base, command, root, build: { assetsDir } }) { + if (api) return // NOTE: When reusing plugins for SSR build. + config = { presets: presets!, urlParam: 'preset', base, root, - outDir: resolve(root, outDir), assetsDir, cacheDir: join(root, 'node_modules', '.images'), + purgeCache: true, + writeToBundle: true, isBuild: command === 'build', ...options, } @@ -67,8 +70,11 @@ export default function ImagePresetsPlugin (presets?: ImagePresets, options?: Op }) }, async generateBundle (_, output) { - const images = await api.waitForImages() - images.forEach(asset => { output[asset.fileName] = asset }) + if (config.writeToBundle) { + const images = await api.waitForImages() + images.forEach(asset => { output[asset.fileName] = asset }) + api.purgeCache(images) + } }, } } diff --git a/src/types.ts b/src/types.ts index 3f6540d..25c3e7c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -82,11 +82,20 @@ export interface Options { * @default 'preset' */ urlParam?: string + /** + * Whether to remove cached files that are no longer used. + * @default true + */ + purgeCache?: boolean + /** + * Whether to write generated images in the bundle. + * @default true + */ + writeToBundle?: boolean } export interface Config extends Required { isBuild: boolean - outDir: string base: string root: string }