diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 2b1b3bbd47d..57d2237aaab 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'); @@ -298,6 +299,15 @@ module.exports = function (webpackEnv) { }), // This is only used in production mode new CssMinimizerPlugin(), + // This is only used in production mode + new ImageMinimizerPlugin({ + minimizer: { + implementation: ImageMinimizerPlugin.imageminMinify, + options: { + plugins: ['gifsicle', 'jpegtran', 'optipng', 'svgo'], + }, + }, + }), ], }, resolve: { diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 99b82701669..3c512b11e0c 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -50,6 +50,12 @@ "fs-extra": "^10.0.0", "html-webpack-plugin": "^5.5.0", "identity-obj-proxy": "^3.0.0", + "image-minimizer-webpack-plugin": "^3.2.2", + "imagemin": "^8.0.1", + "imagemin-gifsicle": "^7.0.0", + "imagemin-jpegtran": "^7.0.0", + "imagemin-optipng": "^8.0.0", + "imagemin-svgo": "^10.0.1", "jest": "^27.4.3", "jest-resolve": "^27.4.2", "jest-watch-typeahead": "^1.0.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'));