const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineChunkHtmlPlugin = require('inline-chunk-html-plugin');
const HTMLInlineCSSWebpackPlugin = require('html-inline-css-webpack-plugin').default;
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const workboxPlugin = require('workbox-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { DuplicatesPlugin } = require('inspectpack/plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const path = require('path');
const DEVELOPMENT = 'development';
const SITE_TITLE = 'Comedy Collection';
const environment = process.env.NODE_ENV || DEVELOPMENT;
const target = process.env.TARGET || 'dev';
const resolve = (filename) => path.resolve(__dirname, filename);
/***************************
********* Loaders *********
**************************/
const js = {
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
};
const scss = {
test: /\.scss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
/**
* NOTE: Use following loader to generate css files
*/
// MiniCssExtractPlugin.loader,
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
{
loader: 'sass-loader',
options: {
sassOptions: {
outputStyle: 'compressed'
}
}
}
]
};
const imgs = {
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
};
const css = {
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
};
/***************************
******* Entry config ******
**************************/
const entry = {};
// VENDORS
entry[`react-libs`] = ['react', 'react-dom', 'react-router-dom', 'swr'];
entry[`common-libs`] = ['react-youtube'];
// MAIN SCRIPTS
entry[`app-index`] = resolve('main.js');
// service worker: registeration scripts only
entry[`caching-configs.register`] = resolve('service-workers/caching-configs.register.js');
// CRITICAL STYLES
// TODO: change type to inline
// entry[`styles-home`] = [resolve('assets/scss/home-spinner.scss')];
/*************************************
*** Inject Manifest plugin config ***
** (list of resources to precache) **
************************************/
// service workers mapping here
const injectManifestCachingConfigSW = {
swSrc: resolve(`service-workers/caching-configs.sw.js`),
/**
* NOTE: following sw applies to root of the application.
* adding it under folder `comedians/` would make it be applicable to code under that folder
*/
swDest: `caching-configs.sw.js`,
include: []
};
/***************************
*** HTML plugin config ****
**************************/
const htmlPluginConfig = {
inject: false,
filename: 'index.html',
template: 'index.html'
};
/***************************
******** Plugins **********
**************************/
const commonPlugins = [
new workboxPlugin.InjectManifest(injectManifestCachingConfigSW),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name].css'
}),
new HtmlWebpackPlugin(htmlPluginConfig),
new CopyPlugin({
patterns: [
{
from: './assets/icons/'
}
]
}),
new DuplicatesPlugin({
emitErrors: false,
verbose: true
})
];
const plugins = [];
plugins.push(...commonPlugins);
/*****************************************************************/
////////////////////////// All Config /////////////////////////////
/*****************************************************************/
const BUILD_PATH = resolve(`../build/${target}`);
const clientConfig = {
mode: environment,
target: 'web',
entry,
module: {
rules: [js, scss, imgs]
},
output: {
path: BUILD_PATH,
filename: '[name].[contenthash:8].js',
publicPath: '/',
// fixes issue with window not defined while using webworkers
// https://github.com/webpack/webpack/issues/6642
globalObject: 'this'
},
// create seperate bundle for node_modules packages
optimization: {
splitChunks: {
chunks: 'async'
}
},
plugins
};
if (environment === DEVELOPMENT) {
clientConfig['devtool'] = 'source-map';
clientConfig['devServer'] = {
contentBase: BUILD_PATH
};
} else {
clientConfig['optimization'].minimize = true;
clientConfig['optimization'].minimizer = [new TerserPlugin({ cache: true })];
}
module.exports = [clientConfig];