diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 6bc8b2cee11..7ebe2cf5ad2 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -18,6 +18,7 @@ const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin'); const TerserPlugin = require('terser-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin'); const { WebpackManifestPlugin } = require('webpack-manifest-plugin'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); @@ -232,7 +233,7 @@ module.exports = function (webpackEnv) { }, optimization: { minimize: isEnvProduction, - minimizer: [ + minimizer: minimizer: [ // This is only used in production mode new TerserPlugin({ terserOptions: { @@ -275,6 +276,17 @@ module.exports = function (webpackEnv) { }), // This is only used in production mode new CssMinimizerPlugin(), + // This is only used in production mode + new ImageMinimizerPlugin({ + minimizerOptions: { + plugins: [ + 'gifsicle', + 'jpegtran', + 'optipng', + 'svgo', + ], + }, + }), ], }, resolve: { diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index bd95dae6a0b..329808d7e70 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -50,6 +50,11 @@ "fs-extra": "^10.0.0", "html-webpack-plugin": "5.3.2", "identity-obj-proxy": "3.0.0", + "image-minimizer-webpack-plugin": "^2.2.0", + "imagemin-gifsicle": "^7.0.0", + "imagemin-jpegtran": "^7.0.0", + "imagemin-optipng": "^8.0.0", + "imagemin-svgo": "^9.0.0", "jest": "26.6.0", "jest-circus": "26.6.0", "jest-resolve": "26.6.0", diff --git a/test/fixtures/webpack-image-optimization/index.test.js b/test/fixtures/webpack-image-optimization/index.test.js new file mode 100644 index 00000000000..4bcb015343a --- /dev/null +++ b/test/fixtures/webpack-image-optimization/index.test.js @@ -0,0 +1,25 @@ +const testSetup = require('../__shared__/test-setup'); + +const fs = require('fs-extra'); +const globby = require('globby'); +const path = require('path'); + +test('optimizes in production', async () => { + const { fulfilled } = await testSetup.scripts.build(); + expect(fulfilled).toBe(true); + + const buildDir = path.join(testSetup.testDirectory, 'build'); + const builtImageFile = path.join( + buildDir, + globby.sync('**/*.png', { cwd: buildDir }).pop() + ); + const recievedBuf = fs.readFileSync(builtImageFile); + + const expectedImageFile = path.join( + testSetup.templateDirectory, + './src/images/webpack-optimized.png' + ); + const expectedBuf = fs.readFileSync(expectedImageFile); + + expect(recievedBuf).toStrictEqual(expectedBuf); +}); diff --git a/test/fixtures/webpack-image-optimization/package.json b/test/fixtures/webpack-image-optimization/package.json new file mode 100644 index 00000000000..26a3813575e --- /dev/null +++ b/test/fixtures/webpack-image-optimization/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "react": "latest", + "react-dom": "latest" + } +} diff --git a/test/fixtures/webpack-image-optimization/src/images/webpack-optimized.png b/test/fixtures/webpack-image-optimization/src/images/webpack-optimized.png new file mode 100644 index 00000000000..62e7ba0ce4f Binary files /dev/null and b/test/fixtures/webpack-image-optimization/src/images/webpack-optimized.png differ diff --git a/test/fixtures/webpack-image-optimization/src/images/webpack-unoptimized.png b/test/fixtures/webpack-image-optimization/src/images/webpack-unoptimized.png new file mode 100644 index 00000000000..665c9a2c348 Binary files /dev/null and b/test/fixtures/webpack-image-optimization/src/images/webpack-unoptimized.png differ diff --git a/test/fixtures/webpack-image-optimization/src/index.css b/test/fixtures/webpack-image-optimization/src/index.css new file mode 100644 index 00000000000..0943c64c564 --- /dev/null +++ b/test/fixtures/webpack-image-optimization/src/index.css @@ -0,0 +1,5 @@ +#root { + width: 300px; + height: 300px; + background: url(./images/webpack-unoptimized.png) center/cover no-repeat; +} diff --git a/test/fixtures/webpack-image-optimization/src/index.js b/test/fixtures/webpack-image-optimization/src/index.js new file mode 100644 index 00000000000..c233f23b66c --- /dev/null +++ b/test/fixtures/webpack-image-optimization/src/index.js @@ -0,0 +1,5 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; + +ReactDOM.render(
, document.getElementById('root'));