Skip to content

Commit

Permalink
feat: caching of generated images
Browse files Browse the repository at this point in the history
  • Loading branch information
pzerelles committed Mar 27, 2024
1 parent dc25e4b commit 72f7b0a
Show file tree
Hide file tree
Showing 11 changed files with 311 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/quick-roses-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vite-imagetools': patch
---

feat: caching of generated images
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ unclear!

- [Extend Imagetools](guide/extending.md)
- [Sharp's documentation](https://sharp.pixelplumbing.com)
- [Caching](guide/caching.md)
46 changes: 46 additions & 0 deletions docs/guide/caching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Caching

To speed up a build pipeline with many images, the generated images can be cached on disk.
If the source image changes, the cached images will be regenerated.

## How to configure caching

Caching is enabled by default and uses './node_modules/.cache/imagetools' as cache directory.
You can disable caching or change the directory with options.

```
// vite.config.js, etc
...
plugins: [
react(),
imagetools({
cache: {
enabled: true,
dir: './node_modules/.cache/imagetools'
}
})
]
...
```

## Cache retention to remove unused images

When an image is no longer there or the transformation parameters change, the previously
cached images will be removed after a configurable retention period.
The default retention is 1 day (86400 seconds). A value of 0 will disable this mechanism.

```
// vite.config.js, etc
...
plugins: [
react(),
imagetools({
cache: {
enabled: true,
dir: './node_modules/.cache/imagetools',
retention: 172800
}
})
]
...
```
63 changes: 63 additions & 0 deletions docs/interfaces/vite_src_types.CacheOptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[imagetools](../README.md) / [Modules](../modules.md) / [vite/src/types](../modules/vite_src_types.md) / CacheOptions

# Interface: CacheOptions

[vite/src/types](../modules/vite_src_types.md).CacheOptions

## Table of contents

### Properties

- [enabled](vite_src_types.CacheOptions.md#enabled)
- [dir](vite_src_types.CacheOptions.md#dir)
- [retention](vite_src_types.CacheOptions.md#retention)

## Properties

### enabled

**enabled**: `boolean`

Wether caching of transformed images is enabled.

**`Default`**

```ts
true
```

#### Defined in

[packages/vite/src/types.ts:104](https://github.com/JonasKruckenberg/imagetools/blob/4ebc88f/packages/vite/src/types.ts#L104)

### dir

**dir**: `string`

Where to store generated images on disk as cache.

**`Default`**

```ts
'./node_modules/.cache/imagetools'
```

#### Defined in

[packages/vite/src/types.ts:109](https://github.com/JonasKruckenberg/imagetools/blob/4ebc88f/packages/vite/src/types.ts#L109)

### retention

**retention**: `number`

After what time an unused image will be removed from the cache.

**`Default`**

```ts
86400
```

#### Defined in

[packages/vite/src/types.ts:114](https://github.com/JonasKruckenberg/imagetools/blob/4ebc88f/packages/vite/src/types.ts#L114)
18 changes: 18 additions & 0 deletions docs/interfaces/vite_src_types.VitePluginOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
- [include](vite_src_types.VitePluginOptions.md#include)
- [removeMetadata](vite_src_types.VitePluginOptions.md#removemetadata)
- [resolveConfigs](vite_src_types.VitePluginOptions.md#resolveconfigs)
- [cacheRetention](vite_src_types.VitePluginOptions.md#cacheretention)
- [cacheDir](vite_src_types.VitePluginOptions.md#cachedir)

## Properties

Expand Down Expand Up @@ -177,3 +179,19 @@ undefined
#### Defined in

[packages/vite/src/types.ts:79](https://github.com/JonasKruckenberg/imagetools/blob/4ebc88f/packages/vite/src/types.ts#L79)

### cache

**cache**: [`CacheOptions`](./vite_src_types.CacheOptions.md)

Options to enable caching of generated images.

**`Default`**

```ts
undefined
```

#### Defined in

[packages/vite/src/types.ts:97](https://github.com/JonasKruckenberg/imagetools/blob/4ebc88f/packages/vite/src/types.ts#L97)
1 change: 1 addition & 0 deletions docs/modules/vite_src_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### Interfaces

- [VitePluginOptions](../interfaces/vite_src_types.VitePluginOptions.md)
- [CacheOptions](../interfaces/vite_src_types.CacheOptions.md)

### Type Aliases

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 85 additions & 5 deletions packages/vite/src/__tests__/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { build, createLogger } from 'vite'
import { InlineConfig, build, createLogger } from 'vite'
import { imagetools } from '../index'
import { join } from 'path'
import { getFiles, testEntry } from './util'
Expand All @@ -8,6 +8,8 @@ import { JSDOM } from 'jsdom'
import sharp from 'sharp'
import { afterEach, describe, test, expect, it, vi } from 'vitest'
import { createBasePath } from '../utils'
import { existsSync } from 'fs'
import { rm, utimes } from 'fs/promises'

expect.extend({ toMatchImageSnapshot })

Expand Down Expand Up @@ -235,7 +237,8 @@ describe('vite-imagetools', () => {
return (image) => image
}
]
}
},
cache: { enabled: false }
})
]
})
Expand Down Expand Up @@ -263,7 +266,8 @@ describe('vite-imagetools', () => {
return (image) => image
}
]
}
},
cache: { enabled: false }
})
]
})
Expand All @@ -289,7 +293,8 @@ describe('vite-imagetools', () => {
return (image) => image
}
]
}
},
cache: { enabled: false }
})
]
})
Expand Down Expand Up @@ -327,6 +332,8 @@ describe('vite-imagetools', () => {
})

test('false leaves private metadata', async () => {
const dir = './node_modules/.cache/imagetools_test_false_leaves_private_metadata'
await rm(dir, { recursive: true, force: true })
const bundle = (await build({
root: join(__dirname, '__fixtures__'),
logLevel: 'warn',
Expand All @@ -337,7 +344,8 @@ describe('vite-imagetools', () => {
window.__IMAGE__ = Image
`),
imagetools({
removeMetadata: false
removeMetadata: false,
cache: { dir }
})
]
})) as RollupOutput | RollupOutput[]
Expand Down Expand Up @@ -458,6 +466,56 @@ describe('vite-imagetools', () => {
expect(window.__IMAGE__).toHaveProperty('hasAlpha')
})
})
describe('cache.retention', () => {
test('is used to clear cache with default 86400', async () => {
const dir = './node_modules/.cache/imagetools_test_cache_retention'
await rm(dir, { recursive: true, force: true })
const root = join(__dirname, '__fixtures__')
const config: (width: number) => InlineConfig = (width) => ({
root,
logLevel: 'warn',
build: { write: false },
plugins: [
testEntry(`
import Image from "./pexels-allec-gomes-5195763.png?w=${width}"
export default Image
`),
imagetools({ cache: { dir } })
]
})
await build(config(300))
expect(existsSync(`${dir}/436a701f0301386167e47006781708d0ed589f03`)).toBe(true)

await build(config(200))
expect(existsSync(`${dir}/b8e9e77ecb7bc3cb7b552021ca9c9352814cc8de`)).toBe(true)

const date = new Date(Date.now() - 86400000)
await utimes(`${dir}/436a701f0301386167e47006781708d0ed589f03`, date, date)
await build(config(200))
expect(existsSync(`${dir}/436a701f0301386167e47006781708d0ed589f03`)).toBe(false)
})
})
describe('cache.dir', () => {
test('is used', async () => {
const dir = './node_modules/.cache/imagetools_test_cache_dir'
await rm(dir, { recursive: true, force: true })
const root = join(__dirname, '__fixtures__')
await build({
root,
logLevel: 'warn',
build: { write: false },
plugins: [
testEntry(`
import Image from "./pexels-allec-gomes-5195763.png?w=300"
export default Image
`),
imagetools({ cache: { dir } })
]
})

expect(existsSync(`${dir}/436a701f0301386167e47006781708d0ed589f03`)).toBe(true)
})
})
})

test('relative import', async () => {
Expand Down Expand Up @@ -516,6 +574,28 @@ describe('vite-imagetools', () => {
expect(files[0].source).toMatchImageSnapshot()
})

test('import with space in identifier and cache', async () => {
const dir = './node_modules/.cache/imagetools_test_import_with_space'
await rm(dir, { recursive: true, force: true })
const config: InlineConfig = {
root: join(__dirname, '__fixtures__'),
logLevel: 'warn',
build: { write: false },
plugins: [
testEntry(`
import Image from "./with space.png?w=300"
export default Image
`),
imagetools({ cache: { dir } })
]
}
await build(config)
const bundle = (await build(config)) as RollupOutput | RollupOutput[]

const files = getFiles(bundle, '**.png') as OutputAsset[]
expect(files[0].source).toMatchImageSnapshot()
})

test('non existent file', async () => {
const p = build({
root: join(__dirname, '__fixtures__'),
Expand Down
Loading

0 comments on commit 72f7b0a

Please sign in to comment.