const autoprefixer = require('autoprefixer'); const path = require('node:path'); const webpack = require('webpack'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const WebpackBar = require('webpackbar'); const paths = require('../../shared/config/paths'); // Assert this just to be safe. // Development builds of React are slow and not intended for production. if (process.env.NODE_ENV !== 'production') { throw new Error('Production builds must have NODE_ENV=production.'); } module.exports = { mode: 'production', module: { rules: [ { test: /\.(ts|js)x?$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { babelrc: true, }, }, ], }, { test: /\.s?css$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { // filename is static/css/x.css, so root path is ../../ publicPath: '../../', }, }, { loader: 'css-loader', options: { importLoaders: 1, sourceMap: true, modules: { mode: 'global', localIdentName: '[name]_[local]__[hash:base64:5]', }, }, }, { loader: 'postcss-loader', options: { sourceMap: true, postcssOptions: { plugins: () => [autoprefixer()], }, }, }, { loader: 'sass-loader', options: { sourceMap: true, sassOptions: { silenceDeprecations: ['mixed-decls'], }, }, }, ], }, { exclude: [/node_modules/], test: /\.(ts|js)x?$/, use: ['source-map-loader'], enforce: 'pre', }, { test: /\.md$/, loader: 'frontmatter-markdown-loader', options: {mode: ['react-component']}, }, { test: [/\.woff2$/], type: 'asset/resource', }, { include: [/\.svg$/], issuer: /\.s?css$/, type: 'asset/resource', }, // "url" loader works like "file" loader except that it embeds assets // smaller than specified limit in bytes as data URLs to avoid requests. // A missing `test` is equivalent to a match. { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], type: 'asset/resource', }, // https://github.com/lingui/js-lingui/issues/1048 { resourceQuery: /raw-lingui/, type: 'javascript/auto', }, ], }, entry: paths.appIndex, resolve: { extensions: ['.cjs', '.mjs', '.js', '.jsx', '.ts', '.tsx', '.json'], alias: { '@client': path.resolve('./client/src/javascript'), '@shared': path.resolve('./shared'), }, }, output: { // The build folder. path: paths.appBuild, // Generated JS file names (with nested folders). // There will be one main bundle, and one file per asynchronous chunk. // We don't currently advertise code splitting but Webpack supports it. filename: 'static/js/[name].[chunkhash:8].js', chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js', assetModuleFilename: 'static/media/[name].[hash:8][ext]', // Point sourcemap entries to original disk location (format as URL on Windows) devtoolModuleFilenameTemplate: (info) => path.relative(paths.appSrc, info.absoluteResourcePath).replace(/\\/g, '/'), }, plugins: [ // Generates an `index.html` file with the