Skip to content

Commit

Permalink
Update: cleanup + fix caching
Browse files Browse the repository at this point in the history
  • Loading branch information
vHeemstra committed Nov 16, 2023
1 parent 21df2d6 commit e0c1d30
Show file tree
Hide file tree
Showing 27 changed files with 93 additions and 842 deletions.
386 changes: 0 additions & 386 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-vitest-globals": "^1.4.0",
"imagemin-avif": "^0.1.4",
"imagemin-gif2webp": "^3.0.0",
"imagemin-gifsicle": "^7.0.0",
"imagemin-mozjpeg": "^10.0.0",
Expand Down
14 changes: 7 additions & 7 deletions packages/core/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,8 @@ describe('getAllFiles', () => {
const files = getAllFiles(join(root, 'public'), mockLogger)
expect(spy).not.toHaveBeenCalled()
expect(files).toHaveLength(23)
expect(files).toContain(join(root, 'public', 'vite.svg'))
// expect(files).toEqual(['vite.svg'])
expect(files).toContain(join(root, 'public', 'from_public.svg'))
// expect(files).toEqual(['from_public.svg'])
})

it('logs ENOENT error on non-existing path', () => {
Expand Down Expand Up @@ -735,7 +735,7 @@ describe('processFile', () => {
['smallest' as const, [true, true, false]] as const,
].forEach(([skipMode, expected]) => {
const stack: ProcessFileParams = {
filePathFrom: 'public/vite.svg',
filePathFrom: 'public/from_public.svg',
fileToStack: [],
baseDir: normalizePath(root) + '/',
bytesDivider: 1000 as const,
Expand All @@ -754,7 +754,7 @@ describe('processFile', () => {
// smaller
() => Promise.resolve(Buffer.from('less')),
{
oldPath: 'public/vite.svg',
oldPath: 'public/from_public.svg',
oldSize: 1497,
newSize: 4,
oldSizeString: '1.50 kB',
Expand All @@ -766,7 +766,7 @@ describe('processFile', () => {
// equal
mockPlugin,
{
oldPath: 'public/vite.svg',
oldPath: 'public/from_public.svg',
oldSize: 1497,
newSize: 1497,
oldSizeString: '1.50 kB',
Expand All @@ -779,7 +779,7 @@ describe('processFile', () => {
(b: Buffer) =>
Promise.resolve(Buffer.concat([b, Buffer.from('more')])),
{
oldPath: 'public/vite.svg',
oldPath: 'public/from_public.svg',
oldSize: 1497,
newSize: 1501,
oldSizeString: '1.50 kB',
Expand Down Expand Up @@ -1368,7 +1368,7 @@ describe('logErrors', () => {
* dist/images/opaque-1.png.avif
*/

// TODO: add tests using cache
// TODO: add tests for usage with cache
// TODO: expand after-build checks

describe.skipIf(skipBuilds)('viteImagemin', () => {
Expand Down
110 changes: 79 additions & 31 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import path from 'node:path'
import {
existsSync,
mkdirSync,
lstatSync,
readdirSync,
unlinkSync /*, rmSync */,
copyFileSync,
} from 'node:fs'
import { readFile, writeFile } from 'node:fs/promises'
import { Buffer } from 'node:buffer'
Expand Down Expand Up @@ -43,6 +45,15 @@ import type {
} from './typings'
import { CacheInterface } from '@file-cache/core/mjs/CacheInterface'

// export const pathIsWithin = (parentPath: string, childPath: string) => {
// try {
// const relative = path.relative(parentPath, childPath)
// return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
// } catch (e) {
// return false
// }
// }

export const parsePlugins = (rawPlugins: PluginsConfig) => {
let plugins: false | ResolvedPluginsConfig = false
if (rawPlugins && isObject(rawPlugins)) {
Expand Down Expand Up @@ -188,7 +199,8 @@ export async function processFile({
precisions,
bytesDivider,
sizeUnit,
cache,
cacheDir = '',
cache = null,
}: ProcessFileParams): ProcessFileReturn {
// const start = performance.now()

Expand All @@ -211,13 +223,24 @@ export async function processFile({
}

if (cache) {
const result = await cache.getAndUpdateCache(baseDir + filePathFrom)
if (!result.changed) {
const outputsStillExist = fileToStack.every(item => {
return existsSync(baseDir + item.toPath)
// Check if input file hasn't changed
const inputFileCache = await cache.getAndUpdateCache(baseDir + filePathFrom)
if (!inputFileCache.changed) {
// Check if output files are in cache and use them if they haven't changed
const outputFilesExist = fileToStack.every(async item => {
if (existsSync(cacheDir + item.toPath)) {
const outputFileCache = await cache.getAndUpdateCache(
cacheDir + item.toPath,
)
if (!outputFileCache.changed) {
copyFileSync(cacheDir + item.toPath, baseDir + item.toPath)
return existsSync(baseDir + item.toPath)
}
}
return false
})

if (outputsStillExist) {
if (outputFilesExist) {
return Promise.reject({
oldPath: filePathFrom,
newPath: '',
Expand Down Expand Up @@ -324,7 +347,13 @@ export async function processFile({
}
return Promise.reject(e)
})
.then(() => {
.then(async () => {
// Add to/update in cache
if (cache) {
copyFileSync(baseDir + filePathTo, cacheDir + filePathTo)
await cache.getAndUpdateCache(cacheDir + filePathTo)
}

const duration = performance.now() - start
const ratio = newSize / oldSize - 1
return Promise.resolve({
Expand Down Expand Up @@ -714,11 +743,11 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
}

let config: ResolvedConfig
let root: string
let rootDir: string
// let sourceDir: string
let distDir: string
let outDir: string
let assetsDir: string
// let publicDir = ''
// let publicDir: string
// const entry = options.entry
const onlyAssets = options.onlyAssets
const verbose = options.verbose
Expand Down Expand Up @@ -751,23 +780,32 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
// const mtimeCache = new Map<string, number>()

let cache: CacheInterface
let cacheDir = ''

return {
name: 'vite-plugin-imagemin',
enforce: 'post',
apply: 'build',
configResolved: resolvedConfig => {
config = resolvedConfig
root = options.root || config.root

// sourceDir = normalizePath(path.resolve(root, entry))
distDir = normalizePath(path.resolve(root, config.build.outDir))
assetsDir = normalizePath(path.resolve(distDir, config.build.assetsDir))
rootDir = options.root || config.root
rootDir = normalizePath(
path.isAbsolute(rootDir)
? rootDir
: path.resolve(process.cwd(), rootDir),
)

// if (typeof config.publicDir === 'string') {
// publicDir = config.publicDir
// }
// publicDir = normalizePath(publicDir)
cacheDir =
normalizePath(
path.resolve(rootDir, './node_modules/.vite-plugin-imagemin/'),
) + '/'
// sourceDir = normalizePath(path.resolve(rootDir, entry))
outDir = normalizePath(path.resolve(rootDir, config.build.outDir))
assetsDir = normalizePath(path.resolve(outDir, config.build.assetsDir))
// publicDir = normalizePath(path.resolve(rootDir, config.publicDir))

// const emptyOutDir = config.build.emptyOutDir || pathIsWithin(rootDir, outDir)

if (verbose) {
logger = options.logger || config.logger
Expand All @@ -778,20 +816,24 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {

logger.info('')

const processDir = onlyAssets ? assetsDir : distDir
const baseDir = `${root}/`
const processDir = onlyAssets ? assetsDir : outDir
const baseDir = `${rootDir}/`
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
// Create cache
if (options.cache !== false) {
mkdirSync(cacheDir.slice(0, -1), { recursive: true })

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)
Expand Down Expand Up @@ -881,6 +923,9 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {

// Ensure all destination (sub)directories are present
smartEnsureDirs(toPaths.map(file => baseDir + file))
if (options.cache !== false) {
smartEnsureDirs(toPaths.map(file => cacheDir + file))
}

// Process stack
const {
Expand All @@ -899,6 +944,7 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
precisions,
bytesDivider,
sizeUnit,
cacheDir,
cache,
}),
),
Expand Down Expand Up @@ -1014,7 +1060,9 @@ export default function viteImagemin(_options: ConfigOptions): PluginOption {
})

// Write cache state to file for persistence
await cache.reconcile()
if (options.cache !== false) {
await cache.reconcile()
}

Object.keys(erroredFiles)
.sort((a, b) => a.localeCompare(b)) // TODO: sort by (sub)folder and depth?
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ export type ProcessFileParams = {
}
bytesDivider: number
sizeUnit: string
cache: CacheInterface
cacheDir?: string
cache?: CacheInterface | null
}

export type ProcessedFile = {
Expand Down
4 changes: 2 additions & 2 deletions packages/playground/index.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/from_public.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
Expand Down
File renamed without changes
4 changes: 2 additions & 2 deletions packages/playground/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import reactLogo from './assets/from_tsx.svg'
import './App.css'

function App() {
Expand All @@ -9,7 +9,7 @@ function App() {
<div className="App">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" className="logo" alt="Vite logo" />
<img src="/from_public.svg" className="logo" alt="Vite logo" />
</a>
<a href="https://reactjs.org" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
Expand Down
Binary file removed packages/playground/src/assets/animated-opaque-1.gif
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes
File renamed without changes
Binary file removed packages/playground/src/assets/opaque-1.png
Binary file not shown.
Binary file removed packages/playground/src/assets/static-1.jpg
Binary file not shown.
Loading

0 comments on commit e0c1d30

Please sign in to comment.