const path = require("path");
const webpack = require("webpack");
const fs = require("fs");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const DuplicatePackageCheckerPlugin = require("duplicate-package-checker-webpack-plugin");
const TerserJSPlugin = require("terser-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const paths = {
src: path.resolve(__dirname, "src"),
build: path.resolve(__dirname, "build"),
};
const smp = new SpeedMeasurePlugin();
module.exports = (env, argv) => {
return smp.wrap({
entry: {
index: "./src/index.js",
},
output: {
path: paths.build,
filename: "[name].[hash].js",
},
optimization: {
minimize: argv.mode !== "development",
minimizer: [
new TerserJSPlugin({
cache: true,
parallel: true,
}),
],
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/].*\.js$/,
filename: "vendor.[hash].js",
chunks: "all",
},
},
},
},
resolve: {
alias: {
"@": paths.src,
},
},
module: {
rules: [
{
test: require.resolve("jquery"),
use: [
{
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
},
],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "cache-loader",
},
{
loader: "thread-loader",
},
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
],
},
{
test: /\.pug$/,
use: [
{
loader: "pug-loader",
options: {
pretty: argv.mode !== "development",
},
},
],
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
argv.mode === "development"
? {
loader: "style-loader",
}
: {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../",
},
},
"css-loader",
"postcss-loader",
"fast-sass-loader",
],
},
{
test: /\.svg$/,
include: /icons/,
use: [
{
loader: "svg-sprite-loader",
options: {
runtimeCompat: true,
},
},
"svg-transform-loader",
"svgo-loader",
],
},
{
test: /\.(gif|png|jpe?g)$/i,
include: /ill/,
use: [
{
loader: "responsive-loader",
options: {
name: "[name]-[width].[ext]",
outputPath: "images",
},
},
{
loader: "image-webpack-loader",
options: {
mozjpeg: {
progressive: true,
quality: 65,
},
optipng: {
enabled: false,
},
pngquant: {
quality: [0.8, 1],
},
gifsicle: {
interlaced: false,
},
},
},
],
},
{
test: /\.(svg)$/i,
include: /ill/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "images",
},
},
],
},
{
test: /\.(eot|ttf|woff|woff2)$/,
use: [
{
loader: "file-loader",
options: {
name: "fonts/[name].[ext]",
},
},
],
},
{
test: /\.(mp4)$/,
use: [
{
loader: "file-loader",
options: {
name: "video/[name].[ext]",
},
},
],
},
],
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
}),
new MiniCssExtractPlugin({
filename: "./css/[name].[hash].css",
chunkFilename: "[name].[hash].css",
}),
new SpriteLoaderPlugin({
plainSprite: true,
}),
new CopyWebpackPlugin({
patterns: [
{
from: "static",
to: "static",
},
],
}),
new CleanWebpackPlugin({
dry: true,
cleanOnceBeforeBuildPatterns: ["build/*"],
}),
new DuplicatePackageCheckerPlugin(),
...fs
.readdirSync(path.resolve(__dirname, "src/template/pages"))
.filter((fileName) =>
fileName.endsWith(".pug") && env !== undefined && env.pages.length
? env.pages.split(",").includes(fileName)
: true
)
.map(
(page) =>
new HtmlWebpackPlugin({
minify: false,
template: `${paths.src}/template/pages/${page}`,
filename: `./${page.replace(/\.pug/, ".html")}`,
})
),
],
devServer: {
watchOptions: {
ignored: /node_modules/,
},
hot: true,
port: process.env.PORT,
overlay: {
errors: false,
warnings: false,
},
},
});
};