Skip to content

Commit

Permalink
Merge pull request #5 from naranjamecanica/feature-cache
Browse files Browse the repository at this point in the history
Add caching feature
  • Loading branch information
vHeemstra authored Nov 14, 2023
2 parents 6329148 + c49a25c commit c37100b
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 11 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ Default: `true`

> Ignore the optimized output if it is larger than the original file.
### cache

Type: `boolean`<br>
Default: `true`

> Skip optimizing the input if it did not change since the last run.
### makeAvif / makeWebp

Type: `object`<br>
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"node": ">=16.0.0"
},
"dependencies": {
"@file-cache/core": "^1.1.4",
"chalk": "^5.2.0",
"fast-glob": "^3.2.12",
"fs-extra": "^11.1.1",
Expand Down
72 changes: 61 additions & 11 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import path from 'node:path'
import { lstatSync, readdirSync, unlinkSync /*, rmSync */ } from 'node:fs'
import {
existsSync,
lstatSync,
readdirSync,
unlinkSync /*, rmSync */,
} from 'node:fs'
import { readFile, writeFile } from 'node:fs/promises'
import { Buffer } from 'node:buffer'
import { performance } from 'node:perf_hooks'
import chalk from 'chalk'
import { normalizePath, createFilter } from 'vite'
import imagemin from 'imagemin'
import isAPNG from 'is-apng'
import { createCache } from '@file-cache/core'

import {
isFunction,
isBoolean,
Expand Down Expand Up @@ -34,6 +41,7 @@ import type {
ProcessResult,
ProcessFileReturn,
} from './typings'
import { CacheInterface } from '@file-cache/core/mjs/CacheInterface'

export const parsePlugins = (rawPlugins: PluginsConfig) => {
let plugins: false | ResolvedPluginsConfig = false
Expand Down Expand Up @@ -131,6 +139,7 @@ export const parseOptions = (
skipIfLarger: isBoolean(_options?.skipIfLarger)
? _options.skipIfLarger
: true,
cache: isBoolean(_options?.cache) ? _options.cache : true,
plugins,
makeAvif,
makeWebp,
Expand Down Expand Up @@ -179,6 +188,7 @@ export async function processFile({
precisions,
bytesDivider,
sizeUnit,
cache,
}: ProcessFileParams): ProcessFileReturn {
// const start = performance.now()

Expand All @@ -200,6 +210,23 @@ export async function processFile({
}) as Promise<ErroredFile>
}

const result = await cache.getAndUpdateCache(baseDir + filePathFrom)
if (!result.changed) {
// just to be sure the outputs (still) exists
const outputExists = fileToStack.every(item => {
return existsSync(baseDir + item.toPath)
})

if (outputExists) {
return Promise.reject({
oldPath: filePathFrom,
newPath: fileToStack[0].toPath,
error: '',
errorType: 'cache',
}) as Promise<ErroredFile>
}
}

let oldBuffer: Buffer
let oldSize = 0

Expand Down Expand Up @@ -612,6 +639,9 @@ export function logErrors(
file.error,
)
break
case 'cache':
logArray.push(chalk.black.bgBlue(' CACHED '), ' ', file.error)
break
case 'warning':
logArray.push(
chalk.bgYellow(' WARNING '),
Expand Down Expand Up @@ -653,6 +683,9 @@ export function logErrors(
file.error,
)
break
case 'cache':
logArray.push(chalk.black.bgBlue(' CACHED '), ' ', file.error)
break
case 'warning':
logArray.push(
chalk.bgYellow(' WARNING '),
Expand Down Expand Up @@ -716,6 +749,8 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
let hadFilesToProcess = false
// const mtimeCache = new Map<string, number>()

let cache: CacheInterface

return {
name: 'vite-plugin-imagemin',
enforce: 'post',
Expand Down Expand Up @@ -746,6 +781,17 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
const baseDir = `${root}/`
const rootRE = new RegExp(`^${escapeRegExp(baseDir)}`)

// create cache for this run
cache = (await createCache({
noCache: options.cache === false,
mode: 'content',
keys: [
() => {
return JSON.stringify(options)
},
],
})) as CacheInterface

// Get all input files to (potentially) process
const files = getAllFiles(processDir, logger)
.filter(filter)
Expand Down Expand Up @@ -852,6 +898,7 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
precisions,
bytesDivider,
sizeUnit,
cache,
}),
),
) as Promise<ProcessResult[]>
Expand Down Expand Up @@ -965,6 +1012,9 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
logResults(processedFiles[k], logger, maxLengths)
})

// write cache state to file for persistence
await cache.reconcile()

Object.keys(erroredFiles)
.sort((a, b) => a.localeCompare(b)) // TODO: sort by (sub)folder and depth?
.forEach(k => {
Expand All @@ -989,16 +1039,16 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
totalDuration.length,
) + 2
const totalRatio = (totalSize.to / totalSize.from - 1) * 100
const totalRatioString =
totalRatio < 0
? chalk.green(
`-${Math.abs(totalRatio).toFixed(precisions.ratio)} %`,
)
: totalRatio > 0
? chalk.red(
`+${Math.abs(totalRatio).toFixed(precisions.ratio)} %`,
)
: `${Math.abs(totalRatio).toFixed(precisions.ratio)} %`

const totalRatioString = isNaN(totalRatio)
? '0 %'
: totalRatio < 0
? chalk.green(
`-${Math.abs(totalRatio).toFixed(precisions.ratio)} %`,
)
: totalRatio > 0
? chalk.red(`+${Math.abs(totalRatio).toFixed(precisions.ratio)} %`)
: `${Math.abs(totalRatio).toFixed(precisions.ratio)} %`

logger.info('')

Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/typings.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Logger as ViteLogger, FilterPattern } from 'vite'
import type { Plugin as ImageminPlugin } from 'imagemin'
import { CacheInterface } from '@file-cache/core/mjs/CacheInterface'

// type Required<T> = {
// [P in keyof T]-?: T[P]
Expand Down Expand Up @@ -79,6 +80,12 @@ export interface ConfigOptions {
*/
verbose?: boolean

/**
* Only optimize contents if it was updated.
* @default true
*/
cache?: boolean

/**
* Only use optimized contents if smaller than original.
* @default true
Expand Down Expand Up @@ -128,6 +135,7 @@ export interface ResolvedConfigOptions {
onlyAssets: boolean
verbose: boolean
skipIfLarger: boolean
cache: boolean
plugins: ResolvedPluginsConfig
makeAvif: false | ResolvedMakeConfigOptions
makeWebp: false | ResolvedMakeConfigOptions
Expand Down Expand Up @@ -162,6 +170,7 @@ export type ProcessFileParams = {
}
bytesDivider: number
sizeUnit: string
cache: CacheInterface
}

export type ProcessedFile = {
Expand Down

0 comments on commit c37100b

Please sign in to comment.