How to Implement a Custom sourceImageParser for Image Paths in next-export-optimize-images
A custom sourceImageParser allows you to intercept and transform image paths before the optimizer processes them, enabling support for CDN prefixes, query strings, or custom directory structures by returning { pathWithoutName, name, extension }.
The sourceImageParser configuration option in dc7290/next-export-optimize-images provides a powerful extensibility hook for projects with non-standard image storage conventions. When the optimizer encounters an image import, it uses this parser to extract the directory path, filename, and extension—information that drives filename generation and output directory calculation. By overriding the default parser in export-images.config.js, you can rewrite paths to handle CDN domains, cache-busting query parameters, or custom folder mappings.
What is sourceImageParser?
By default, next-export-optimize-images uses defaultImageParser to split every image src into three components:
- pathWithoutName: The directory path excluding the filename
- name: The filename without extension
- extension: The file extension (e.g.,
png,jpg)
The built-in parser handles typical static imports like src="/images/foo.png". However, if your images reside on external CDNs, include version query strings, or require path rewriting, the sourceImageParser option lets you replace this logic entirely.
According to the source code in src/utils/getConfig.ts, the library evaluates your custom parser from export-images.config.js at runtime. Then, in src/utils/buildOutputInfo.ts, the optimizer calls your parser (or falls back to the default) to obtain these three values for every processed image.
The Parser API and Return Types
Your custom parser must conform to the following TypeScript signature:
type SourceImageParser = (props: {
src: string
defaultParser: DefaultImageParser
}) => {
pathWithoutName: string
name: string
extension: string
}
type DefaultImageParser = (src: string) => {
pathWithoutName: string
name: string
extension: string
}
The function receives two arguments:
src: The raw image source string (after optionalbasePathstripping)defaultParser: A reference to the built-in parser, useful for delegating standard path logic
You must return an object containing exactly three string properties. These values determine the final output paths and filenames generated during the export phase.
Common Use Cases
Stripping CDN Domains
When images are stored under a CDN prefix like https://cdn.example.com/assets/, you typically want to remove the domain before the optimizer calculates output directories:
sourceImageParser: ({ src, defaultParser }) => {
const cleanSrc = src.replace(/^https?:\/\/cdn\.example\.com\//, '');
const { pathWithoutName, name, extension } = defaultParser(cleanSrc);
return { pathWithoutName, name, extension };
}
Removing Query Parameters for Cache Busting
If your build system appends version query strings (e.g., /img/photo.png?v=123), strip them before parsing to ensure the optimizer recognizes the correct extension:
sourceImageParser: ({ src, defaultParser }) => {
const cleanSrc = src.split('?')[0];
return defaultParser(cleanSrc);
}
Rewriting Output Directories
To map all images from a source folder like /static/media/ to a different output location such as assets/:
sourceImageParser: ({ src, defaultParser }) => {
const { pathWithoutName, name, extension } = defaultParser(src);
return {
pathWithoutName: `assets/${pathWithoutName}`,
name,
extension
};
}
Step-by-Step Implementation
-
Create or edit
export-images.config.jsin your project root. -
Add the
sourceImageParserproperty with a function matching the API signature:
// export-images.config.js
/**
* @type {import('next-export-optimize-images').Config}
*/
const config = {
filenameGenerator: ({ path, name, width, extension }) =>
`${path}/${name}_${width}.${extension}`,
sourceImageParser: ({ src, defaultParser }) => {
// Example: Strip CDN domain and query strings
const cleanSrc = src
.replace(/^https?:\/\/cdn\.example\.com\//, '')
.split('?')[0];
const { pathWithoutName, name, extension } = defaultParser(cleanSrc);
// Rewrite path for output organization
const rewrittenPath = `assets/${pathWithoutName}`;
return { pathWithoutName: rewrittenPath, name, extension };
},
};
module.exports = config;
-
Delegate to
defaultParserwhen you only need to tweak specific parts of the path, or bypass it entirely for complete custom logic. -
Run your export build. The library automatically evaluates the function via
Function(...)insrc/utils/getConfig.tsand applies it to every image during the optimization phase.
Testing Your Custom Parser
The repository includes tests in __tests__/utils/buildOutputInfo/index.test.ts that verify the parser hook works correctly. You can validate your implementation using a similar pattern:
test('Custom sourceImageParser transforms paths correctly', () => {
const customParser = jest.fn(() => ({
pathWithoutName: 'custom/assets',
name: 'hero',
extension: 'webp',
}));
const input = {
src: 'https://cdn.example.com/static/hero.png?v=2',
width: 800,
config: { sourceImageParser: customParser },
};
const output = buildOutputInfo(input);
expect(customParser).toHaveBeenCalledWith({
src: input.src,
defaultParser: expect.any(Function),
});
// Verify the returned values influence output paths
expect(output[0].output).toContain('custom/assets');
});
Running npm test in the repository confirms that your parser receives the correct arguments and that the returned values directly influence filename generation logic in src/utils/buildOutputInfo.ts.
Summary
- sourceImageParser is defined in
export-images.config.jsand evaluated bysrc/utils/getConfig.tsat runtime. - The parser receives
{ src, defaultParser }and must return{ pathWithoutName, name, extension }. - Use it to handle CDN domains, query strings, or custom directory mappings before the optimizer processes images.
- The
defaultParserreference allows you to leverage standard parsing logic while modifying specific components. - Return values directly control output path generation in
src/utils/buildOutputInfo.ts.
Frequently Asked Questions
How do I access the default parser logic inside my custom sourceImageParser?
The sourceImageParser function receives defaultParser as a property in its argument object. Call defaultParser(src) to obtain the standard { pathWithoutName, name, extension } result, then modify whichever fields your project requires. This approach ensures you only override the specific path transformations you need while preserving the core parsing logic.
Can I use sourceImageParser to change file extensions dynamically?
Yes. While the parser typically extracts extensions from the source path, you can override the extension field in your return object. For example, normalize .jpeg to .jpg for compatibility, or force specific extensions based on naming conventions. The optimizer will use your returned extension for format conversion and filename generation.
What happens if my sourceImageParser returns an invalid object?
src/utils/buildOutputInfo.ts expects exactly three string properties: pathWithoutName, name, and extension. If any are missing or non-strings, the filename generation logic may produce broken paths or throw runtime errors during the export phase. Always ensure your parser returns a complete, valid object matching the SourceImageParser type signature.
Where does next-export-optimize-images load my sourceImageParser configuration?
The library loads export-images.config.js via src/utils/getConfig.ts, which evaluates the sourceImageParser property into a real function using Function(...). This resolved function is then passed into src/utils/buildOutputInfo.ts and invoked for every image processed during the static export. Ensure your config file is in the project root or correctly referenced in your build setup.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →