const path = require("path");
const webpack = require("webpack");
const HTMLwebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetPlugin = require("optimize-css-assets-webpack-plugin");
const TerserWebpackPlugin = require("terser-webpack-plugin");
const ErrorOverlayPlugin = require("error-overlay-webpack-plugin");
const isDev = process.env.NODE_ENV === "development";
const isProd = !isDev;
const cssLoader = (extra) => {
const loaders = [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: isDev,
reloadAll: true,
publicPath: "../",
},
},
{
loader: "css-loader",
options: {
url: true,
},
},
];
if (extra) {
loaders.push(extra);
}
return loaders;
};
module.exports = {
context: path.resolve(__dirname, "src"),
mode: "development",
entry: {
index: "./index.js",
},
output: {
filename: isDev ? `js/[name].js` : `js/[name].[contenthash:8].chunk.js`,
path: path.resolve(__dirname, "build"),
},
devServer: {
port: 4200,
hot: isDev,
},
optimization: {
moduleIds: "hashed",
splitChunks: {
chunks: "all",
name: false,
},
minimizer: [].concat(
isProd
? [
new OptimizeCssAssetPlugin(),
new TerserWebpackPlugin(),
]
: []
),
},
resolve: {
extensions: [".js", ".json"],
},
plugins: [
new HTMLwebpackPlugin({
template: "./index.html",
minify: {
collapseWhitespace: isProd,
},
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new CleanWebpackPlugin(),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, "src/favicon.ico"),
to: path.resolve(__dirname, "build"),
},
]),
new MiniCssExtractPlugin({
filename: isDev ? `[name].css` : "css/[name].[hash:8].css",
}),
new ErrorOverlayPlugin(),
],
devtool: isDev ? "cheap-module-source-map" : "",
module: {
rules: [
{
test: /\.css$/,
use: cssLoader(),
},
{
test: /\.(png|jpg|svg|gif)$/,
loader: "file-loader",
options: {
outputPath: "img",
},
},
{
test: /\.(ttf|woff|woff2|eot)$/,
use: ["file-loader"],
},
{
test: /\.s[ac]ss$/,
use: cssLoader("sass-loader"),
},
{
test: /\.ts$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-typescript"],
plugins: ["@babel/plugin-proposal-class-properties"],
},
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: ["@babel/plugin-proposal-class-properties"],
},
},
"eslint-loader",
],
},
],
},
};