Files
flood/client/config/webpack.config.prod.js
2021-01-29 20:53:55 +08:00

184 lines
5.1 KiB
JavaScript

const autoprefixer = require('autoprefixer');
const path = require('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,
},
},
],
},
{
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$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
{
include: [/\.svg$/],
issuer: /\.s?css$/,
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// "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$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
],
},
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',
// 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 <script> injected.
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}),
new MiniCssExtractPlugin({
filename: 'static/css/[name].[contenthash].css',
chunkFilename: 'static/css/[id].[contenthash].css',
}),
new webpack.optimize.MinChunkSizePlugin({
minChunkSize: 10000,
}),
new WebpackBar(),
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
output: {
comments: false,
},
},
extractComments: false,
}),
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: {removeAll: true},
},
],
},
}),
],
},
performance: {
// TODO: Add code-splitting and re-enable this when the bundle is smaller
hints: false,
},
};