Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions packages/loader/src/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { join } from 'node:path'
import { SrcSetCacheStorage } from '@srcset/core'

const storages = new Map<string, SrcSetCacheStorage>()

/**
* Get the disk cache storage shared between loader runs.
* Every run of a compilation gets the same storage, so a variant
* generated for one module is a hit for the next one.
* @param context - Root context directory of the compiler.
* @returns Cache storage.
*/
export function getSharedCache(context: string) {
let storage = storages.get(context)

if (!storage) {
storage = new SrcSetCacheStorage(join(context, 'node_modules', '.cache', 'srcset'))
storages.set(context, storage)
}

return storage
}
45 changes: 44 additions & 1 deletion packages/loader/src/loader.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
describe,
it,
expect
expect,
vi
} from 'vitest'
import sharp from 'sharp'
import webpack from 'webpack'
Expand Down Expand Up @@ -155,6 +156,48 @@ describe('loader', () => {
expect(assets).toEqual(['image.jpg.webp'])
})

it('should reuse the disk cache across builds when enabled', async () => {
const dir = await createFixtureProject(defaultEntry)
const optimize = vi.fn((contents: Buffer) => contents)
const options = {
cache: true,
optimization: {
jpg: optimize
}
}

await compile(createCompiler, dir, options)

const generatedCalls = optimize.mock.calls.length

expect(generatedCalls).toBeGreaterThan(0)

const { assets } = await compile(createCompiler, dir, options)

expect(optimize.mock.calls.length).toBe(generatedCalls)
expect(assets.length).toBeGreaterThan(0)
})

it('should regenerate without the cache option', async () => {
const dir = await createFixtureProject(defaultEntry)
const optimize = vi.fn((contents: Buffer) => contents)
const options = {
optimization: {
jpg: optimize
}
}

await compile(createCompiler, dir, options)

const generatedCalls = optimize.mock.calls.length

expect(generatedCalls).toBeGreaterThan(0)

await compile(createCompiler, dir, options)

expect(optimize.mock.calls.length).toBe(generatedCalls * 2)
})

it('should export placeholder data-url when enabled', async () => {
const dir = await createFixtureProject(defaultEntry)
const { exports } = await compile(createCompiler, dir, {
Expand Down
13 changes: 9 additions & 4 deletions packages/loader/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ import {
resolvePublicPath
} from './paths.ts'
import { getSharedLimit } from './limit.ts'
import { getSharedCache } from './cache.ts'

async function generateModule(ctx: SrcSetLoaderContext, contents: Buffer) {
const options = ctx.getOptions()
const {
context = ctx.rootContext,
emitFile = true,
name = getDefaultName(ctx.mode),
cache = false,
concurrency,
outputPath,
publicPath
} = options
publicPath,
...moduleOptions
} = ctx.getOptions()
const source = {
path: ctx.resourcePath,
contents
Expand Down Expand Up @@ -56,7 +58,10 @@ async function generateModule(ctx: SrcSetLoaderContext, contents: Buffer) {
return generateSrcSetModule(
source,
query,
options,
{
...moduleOptions,
cache: cache ? getSharedCache(ctx.rootContext) : undefined
},
emitImage,
limit
)
Expand Down
8 changes: 7 additions & 1 deletion packages/loader/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ export interface SrcSetLoaderContext {
async(): (error?: Error | null, content?: string | Buffer) => void
}

export interface SrcSetLoaderOptions extends SrcSetModuleOptions {
export interface SrcSetLoaderOptions extends Omit<SrcSetModuleOptions, 'cache'> {
/**
* Cache generated variants on disk, in `node_modules/.cache/srcset`:
* repeated builds skip the generation. Disabled by default - the
* persistent cache of the bundler covers it, when it is enabled.
*/
cache?: boolean
/**
* Output file name template.
* Supports `[name]`, `[postfix]`, `[ext]`, `[path]`, `[sourceext]` and
Expand Down