UNPKG

@vitbokisch/next-optimized-images

Version:

Automatically optimize images used in next.js projects (jpeg, png, gif, svg).

161 lines (141 loc) 4.14 kB
import { createRequire } from 'module' import { getResourceQueries } from '../resource-queries.js' import { getWebpResourceQuery } from './webp-loader.js' import { getUrlLoaderOptions } from './url-loader.js' import { getSvgSpriteLoaderResourceQuery } from './svg-sprite-loader/index.js' const require = createRequire(import.meta.url) /** * Requires an imagemin plugin and configures it * * @param {string} plugin - plugin name * @param {*} nextConfig - next.js configuration * @return {function} */ const requireImageminPlugin = (plugin, nextConfig) => { let moduleName = plugin if (nextConfig.overwriteImageLoaderPaths) { moduleName = require.resolve(plugin, { paths: [nextConfig.overwriteImageLoaderPaths], }) } console.log(moduleName) /* eslint global-require: "off", import/no-dynamic-require: "off" */ return require(moduleName)(nextConfig[plugin.replace('imagemin-', '')] || {}) } /** * Build options for the img loader * * @param {object} nextConfig - next.js configuration * @param {object} detectedLoaders - detected loaders * @param {boolean} optimize - if images should get optimized * @return {object} */ const getImgLoaderOptions = (nextConfig, detectedLoaders, optimize) => { if (!optimize) { return { plugins: [], } } return { plugins: [ detectedLoaders.jpeg ? requireImageminPlugin(detectedLoaders.jpeg, nextConfig) : undefined, detectedLoaders.png ? requireImageminPlugin(detectedLoaders.png, nextConfig) : undefined, detectedLoaders.svg ? requireImageminPlugin(detectedLoaders.svg, nextConfig) : undefined, detectedLoaders.gif ? requireImageminPlugin(detectedLoaders.gif, nextConfig) : undefined, ].filter(Boolean), } } /** * Build the regex for all handled image types * * @param {object} handledImageTypes - handled image types * @return {RegExp} */ const getHandledFilesRegex = (handledImageTypes) => { const handledFiles = [ handledImageTypes.jpeg ? 'jpe?g' : null, handledImageTypes.png ? 'png' : null, handledImageTypes.svg ? 'svg' : null, handledImageTypes.gif ? 'gif' : null, ] return new RegExp(`\\.(${handledFiles.filter(Boolean).join('|')})$`, 'i') } /** * Apply the img loader to the webpack configuration * * @param {object} webpackConfig - webpack configuration * @param {object} nextConfig - next.js configuration * @param {boolean} optimize - if images should get optimized * @param {boolean} isServer - if the build is for the server * @param {object} detectedLoaders - detected loaders * @param {object} handledImageTypes - detected image types * @returns {object} */ const applyImgLoader = ( webpackConfig, nextConfig, optimize, isServer, detectedLoaders, handledImageTypes ) => { const imgLoaderOptions = getImgLoaderOptions( nextConfig, detectedLoaders, optimize ) webpackConfig.module.rules.push({ test: getHandledFilesRegex(handledImageTypes), oneOf: [ // add all resource queries ...getResourceQueries( nextConfig, isServer, optimize ? 'img-loader' : null, imgLoaderOptions, detectedLoaders ), // ?webp: convert an image to webp handledImageTypes.webp ? getWebpResourceQuery(nextConfig, isServer) : undefined, // ?sprite: add icon to sprite detectedLoaders.svgSprite ? getSvgSpriteLoaderResourceQuery( nextConfig, detectedLoaders, imgLoaderOptions, optimize ) : undefined, // default behavior: inline if below the definied limit, external file if above { use: [ { loader: 'url-loader', options: getUrlLoaderOptions(nextConfig, isServer), }, { loader: 'img-loader', options: imgLoaderOptions, }, ], }, ].filter(Boolean), }) return webpackConfig } export { requireImageminPlugin, getImgLoaderOptions, getHandledFilesRegex, applyImgLoader, }