@hashicorp/next-optimized-images
Version:
Automatically optimize images used in next.js projects (jpeg, png, gif, svg).
104 lines (91 loc) • 3.49 kB
JavaScript
const { getConfig } = require('./config')
const {
detectLoaders,
getNumOptimizationLoadersInstalled,
appendLoaders,
} = require('./loaders')
const { showWarning } = require('./migrater')
// RegExps for all Style Sheet variants
const regexLikeCss = /\.(css|scss|sass)(\.webpack\[javascript\/auto\])?$/
/**
* Configure webpack and next.js to handle and optimize images with this plugin.
*
* @param {object} nextConfig - configuration, see the readme for possible values
* @param {object} nextComposePlugins - additional information when loaded with next-compose-plugins
* @returns {object}
*/
const withOptimizedImages = (nextConfig = {}, nextComposePlugins = {}) => {
const { optimizeImages, optimizeImagesInDev, overwriteImageLoaderPaths } =
getConfig(nextConfig)
return Object.assign({}, nextConfig, {
webpack(config, options) {
if (!options.defaultLoaders) {
throw new Error(
'This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade'
)
}
const { dev, isServer } = options
let enrichedConfig = config
// detect all installed loaders
const detectedLoaders = detectLoaders(overwriteImageLoaderPaths)
// check if it should optimize images in the current step
const optimizeInCurrentStep =
nextComposePlugins && typeof nextComposePlugins.phase === 'string'
? (nextComposePlugins.phase === 'phase-production-build' &&
optimizeImages) ||
(nextComposePlugins.phase === 'phase-export' && optimizeImages) ||
(nextComposePlugins.phase === 'phase-development-server' &&
optimizeImagesInDev)
: (!dev && optimizeImages) || (dev && optimizeImagesInDev)
// show a warning if images should get optimized but no loader is installed
if (
optimizeImages &&
getNumOptimizationLoadersInstalled(detectedLoaders) === 0 &&
isServer
) {
showWarning()
}
// remove (unoptimized) builtin image processing introduced in next.js 9.2
if (enrichedConfig.module.rules) {
enrichedConfig.module.rules.forEach((rule) => {
if (rule.oneOf) {
rule.oneOf.forEach((subRule) => {
if (
subRule.issuer &&
!subRule.test &&
!subRule.include &&
subRule.exclude &&
((subRule.use &&
subRule.use.options &&
subRule.use.options.name) ||
subRule.type === 'asset/resource')
) {
if (
((String(subRule.issuer.test) === String(regexLikeCss) ||
String(subRule.issuer) === String(regexLikeCss)) &&
subRule.use.options.name.startsWith('static/media/')) ||
subRule.type === 'asset/resource'
) {
subRule.exclude.push(/\.(jpg|jpeg|png|svg|webp|gif|ico)$/)
}
}
})
}
})
}
// append loaders
enrichedConfig = appendLoaders(
enrichedConfig,
getConfig(nextConfig),
detectedLoaders,
isServer,
optimizeInCurrentStep
)
if (typeof nextConfig.webpack === 'function') {
return nextConfig.webpack(enrichedConfig, options)
}
return enrichedConfig
},
})
}
module.exports = withOptimizedImages