@codefast/image-loader
Version:
Flexible image loader for Next.js supporting multiple CDN providers
148 lines (147 loc) • 5.29 kB
JavaScript
"use strict";
var __webpack_require__ = {};
(()=>{
__webpack_require__.d = (exports1, definition)=>{
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
enumerable: true,
get: definition[key]
});
};
})();
(()=>{
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
__webpack_require__.r = (exports1)=>{
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
value: 'Module'
});
Object.defineProperty(exports1, '__esModule', {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
ImageLoaderFactory: ()=>ImageLoaderFactory,
defaultImageLoaderFactory: ()=>defaultImageLoaderFactory
});
class ImageLoaderFactory {
loaders = [];
config;
loaderCache = {};
transformCache = {};
maxCacheSize = 1000;
constructor(config = {}){
this.config = {
defaultQuality: 75,
...config
};
}
registerLoader(loader) {
if (this.loaders.some((l)=>l.getName() === loader.getName())) throw new Error(`Loader with name "${loader.getName()}" is already registered`);
this.loaders.push(loader);
this.clearLoaderCache();
}
registerLoaders(loaders) {
for (const loader of loaders)this.registerLoader(loader);
}
unregisterLoader(name) {
const index = this.loaders.findIndex((loader)=>loader.getName() === name);
if (-1 !== index) {
this.loaders.splice(index, 1);
this.clearLoaderCache();
return true;
}
return false;
}
getLoaders() {
return [
...this.loaders
];
}
findLoader(source) {
const domain = this.extractDomain(source);
if (domain in this.loaderCache) return this.loaderCache[domain];
let selectedLoader = null;
if (this.config.domainMappings?.[domain]) {
const mappedLoaderName = this.config.domainMappings[domain];
selectedLoader = this.loaders.find((loader)=>loader.getName() === mappedLoaderName) ?? null;
}
selectedLoader ??= this.loaders.find((loader)=>loader.canHandle(source)) ?? null;
this.cacheLoader(domain, selectedLoader);
return selectedLoader;
}
load(config) {
const cacheKey = this.createTransformCacheKey(config);
if (this.transformCache[cacheKey]) return this.transformCache[cacheKey];
const loader = this.findLoader(config.src);
if (!loader) {
console.warn(`No loader found for URL: ${config.src}. Returning original URL.`);
return config.src;
}
const normalizedConfig = {
...config,
quality: config.quality ?? this.config.defaultQuality
};
const transformedUrl = loader.load(normalizedConfig);
this.cacheTransform(cacheKey, transformedUrl);
return transformedUrl;
}
createNextImageLoader() {
return (params)=>this.load({
quality: params.quality,
src: params.src,
width: params.width
});
}
getStats() {
return {
domainMappings: this.config.domainMappings ?? {},
loaderNames: this.loaders.map((loader)=>loader.getName()),
totalLoaders: this.loaders.length
};
}
clear() {
this.loaders.length = 0;
this.clearLoaderCache();
this.clearTransformCache();
}
extractDomain(url) {
try {
const urlObject = new URL(url);
return urlObject.hostname.toLowerCase();
} catch {
return "";
}
}
cacheLoader(domain, loader) {
if (Object.keys(this.loaderCache).length >= this.maxCacheSize) this.clearLoaderCache();
this.loaderCache[domain] = loader;
}
clearLoaderCache() {
for (const key of Object.keys(this.loaderCache))delete this.loaderCache[key];
}
createTransformCacheKey(config) {
const quality = config.quality ?? this.config.defaultQuality ?? 75;
return `${config.src}|${config.width.toString()}|${quality.toString()}`;
}
cacheTransform(key, transformedUrl) {
if (Object.keys(this.transformCache).length >= this.maxCacheSize) this.clearTransformCache();
this.transformCache[key] = transformedUrl;
}
clearTransformCache() {
for (const key of Object.keys(this.transformCache))delete this.transformCache[key];
}
}
const defaultImageLoaderFactory = new ImageLoaderFactory();
exports.ImageLoaderFactory = __webpack_exports__.ImageLoaderFactory;
exports.defaultImageLoaderFactory = __webpack_exports__.defaultImageLoaderFactory;
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"ImageLoaderFactory",
"defaultImageLoaderFactory"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});