Skip to content

Instantly share code, notes, and snippets.

@sidsbrmnn
Last active August 13, 2023 18:11
Show Gist options
  • Save sidsbrmnn/96103c60601f06d90dc11f7d58aabaca to your computer and use it in GitHub Desktop.
Save sidsbrmnn/96103c60601f06d90dc11f7d58aabaca to your computer and use it in GitHub Desktop.
Production-ready webpack configuration for React applications in Typescript
{
"presets": ["@babel/env", "@babel/react", "@babel/typescript"],
"plugins": [
"@babel/proposal-object-rest-spread",
["@babel/plugin-transform-runtime", { "regenerator": true }]
]
}
{
"dependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.11.5",
"@babel/preset-react": "^7.10.4",
"@babel/preset-typescript": "^7.10.4",
"@babel/runtime": "^7.11.2",
"@types/node": "^14.11.1",
"@types/react": "^16.9.49",
"@types/react-dom": "^16.9.8",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"autoprefixer": "^10.0.0",
"babel-loader": "^8.1.0",
"clean-webpack-plugin": "^3.0.0",
"compression-webpack-plugin": "^6.0.2",
"cross-env": "^7.0.2",
"css-loader": "^4.3.0",
"cssnano": "^4.1.10",
"eslint": "^7.9.0",
"eslint-config-prettier": "^6.11.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.2",
"file-loader": "^6.1.0",
"html-loader": "^1.3.0",
"html-webpack-plugin": "^4.4.1",
"mini-css-extract-plugin": "^0.11.2",
"postcss": "^8.0.6",
"postcss-loader": "^4.0.2",
"prettier": "^2.1.2",
"style-loader": "^1.2.1",
"tailwindcss": "^1.8.10",
"terser-webpack-plugin": "^4.2.2",
"typescript": "^4.0.3",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
},
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server",
"build": "cross-env NODE_ENV=production webpack"
}
}
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
...(process.env.NODE_ENV === 'production' ? [require('cssnano')] : []),
],
};
{
"compilerOptions": {
"allowJs": false,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"module": "CommonJS",
"noEmit": true,
"noImplicitAny": true,
"outDir": "dist",
"strict": true,
"target": "ESNext"
},
"include": ["src/**/*.ts", "src/**/*.tsx"]
}
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const {
EnvironmentPlugin,
HotModuleReplacementPlugin,
HashedModuleIdsPlugin,
} = require('webpack');
const isDev = process.env.NODE_ENV !== 'production';
module.exports = {
mode: isDev ? 'development' : 'production',
entry: path.resolve(__dirname, 'src', 'index.tsx'),
output: {
chunkFilename: isDev
? '[name].chunk.js'
: '[name].[chunkhash].chunk.js',
filename: isDev ? '[name].js' : '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
target: 'web',
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
},
module: {
rules: [
{
enforce: 'pre',
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'eslint-loader',
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.html$/,
use: 'html-loader',
},
{
test: /\.css$/,
use: [
isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
],
},
{
test: /\.(png|jpe?g|gif)$/i,
use: 'file-loader',
},
],
},
optimization: isDev
? {
splitChunks: {
chunks: 'all',
},
}
: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
sourceMap: true,
terserOptions: {
compress: {
comparisons: false,
},
mangle: true,
output: {
ascii_only: true,
comments: false,
},
parse: {},
warnings: false,
},
}),
],
nodeEnv: 'production',
sideEffects: true,
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: function (module) {
const packageName = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
)[1];
return `npm.${packageName.replace('@', '')}`;
},
},
},
chunks: 'all',
maxInitialRequests: 10,
minSize: 0,
},
},
plugins: [
new CleanWebpackPlugin(),
new EnvironmentPlugin({
NODE_ENV: 'development',
}),
...(isDev ? [new HotModuleReplacementPlugin()] : []),
new MiniCssExtractPlugin({
filename: isDev ? '[name].css' : '[name].[hash].css',
}),
new HtmlWebpackPlugin({
inject: true,
minify: !isDev,
template: path.resolve(__dirname, 'src', 'index.html'),
}),
...(isDev
? []
: [
new CompressionPlugin({
algorithm: 'gzip',
minRatio: 0.8,
threshold: 10240,
test: /\.js$|\.css$|\.html$/,
}),
new HashedModuleIdsPlugin({
hashDigest: 'hex',
hashDigestLength: 20,
hashFunction: 'sha256',
}),
]),
],
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
disableDotRule: true,
},
hot: true,
inline: true,
stats: 'minimal',
},
devtool: isDev ? 'cheap-module-eval-source-map' : 'hidden-source-map',
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment