Skip to content

Instantly share code, notes, and snippets.

@dmexs
Last active January 22, 2023 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmexs/a7102ac4842eedd5fbbf452a0f8de4e2 to your computer and use it in GitHub Desktop.
Save dmexs/a7102ac4842eedd5fbbf452a0f8de4e2 to your computer and use it in GitHub Desktop.
NestJS Webpack Multiple Configs
{
"name": "PROJECT",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"start": "webpack --mode=development --env watch=true debug=true",
"build": "webpack --mode=production",
"start:prod": "node dist/server",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"prisma:generate": "prisma generate"
}
}
/** Inspired by: https://gist.github.com/GlCap/2ee3b0eb4a63b06b7fa215d254055c79 */
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { config } = require('process');
const TS_CONFIG_FILE = 'tsconfig.build.json';
const LAZY_IMPORTS = [
'@nestjs/microservices',
'cache-manager',
'class-validator',
'class-transformer',
];
const frontendConfig = {
entry: './src/frontend.ts',
output: { path: path.resolve(__dirname, 'public'), filename: 'frontend.js' },
cache: { type: 'filesystem', cacheDirectory: path.resolve(__dirname, '.build_cache') },
optimization: { nodeEnv: false },
target: 'web',
module: {
rules: [
{
test: /.tsx?$/,
include: [path.resolve(__dirname, 'src')],
use: [
{
loader: 'ts-loader',
options: { transpileOnly: true, configFile: TS_CONFIG_FILE },
},
],
exclude: /node_modules/,
}
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
plugins: [
new TsconfigPathsPlugin({
configFile: TS_CONFIG_FILE,
}),
],
},
}
const serverConfig = {
entry: './src/main.ts',
output: { path: path.resolve(__dirname, 'dist'), filename: 'server.js' },
target: 'node',
mode: 'none',
externals: [nodeExternals()],
externalsPresets: { node: true },
cache: { type: 'filesystem', cacheDirectory: path.resolve(__dirname, '.build_cache') },
optimization: { nodeEnv: false },
module: {
rules: [
{
test: /.tsx?$/,
include: [path.resolve(__dirname, 'src')],
use: [
{
loader: 'ts-loader',
options: { transpileOnly: true, configFile: TS_CONFIG_FILE },
},
],
exclude: /node_modules/,
},
{
test: /\.css$/i,
include: path.resolve(__dirname, 'src'),
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
],
}
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
plugins: [
new TsconfigPathsPlugin({
configFile: TS_CONFIG_FILE,
}),
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "../public/[name].css"
}),
new webpack.ProgressPlugin(),
new webpack.IgnorePlugin({
checkResource(resource) {
if (!LAZY_IMPORTS.includes(resource)) {
return false;
}
try {
require.resolve(resource, {
paths: [process.cwd()],
});
} catch (err) {
return true;
}
return false;
},
}),
new CleanWebpackPlugin(),
new ForkTsCheckerWebpackPlugin({
typescript: {
configFile: TS_CONFIG_FILE,
},
})
],
}
module.exports = (
env = { debug: false, watch: false },
argv = { mode: 'none' },
) => {
serverConfig.mode = argv.mode;
if (argv.mode === 'development') {
serverConfig.watch = env.watch === 'true';
serverConfig.cache.name = env.debug === 'true' ? 'development_debug' : 'development';
serverConfig.devtool = env.debug === 'true' ? 'eval-source-map' : undefined;
frontendConfig.watch = env.watch === 'true';
frontendConfig.cache.name = env.debug === 'true' ? 'development_debug' : 'development';
frontendConfig.devtool = env.debug === 'true' ? 'eval-source-map' : undefined;
// If running in watch mode
if (env.watch === 'true') {
serverConfig.cache.name = env.debug === 'true' ? 'development_debug_hmr' : 'development_hmr';
serverConfig.entry = ['webpack/hot/poll?100', 'webpack/hot/signal', serverConfig.entry]
serverConfig.externals = [
nodeExternals({
allowlist: ['webpack/hot/poll?100', 'webpack/hot/signal'],
}),
];
serverConfig.plugins = [
...serverConfig.plugins,
new webpack.WatchIgnorePlugin({ paths: [/\.js$/, /\.d\.ts$/] }),
new webpack.HotModuleReplacementPlugin(),
new RunScriptWebpackPlugin({
name: 'server.js',
nodeArgs: env.debug === 'true' ? ['--inspect'] : undefined, // Allow debugging
signal: true, // Signal to send for HMR (defaults to `false`, uses 'SIGUSR2' if `true`)
keyboard: true, // Allow typing 'rs' to restart the server. default: only if NODE_ENV is 'development'
autoRestart: false,
// args: ['scriptArgument1', 'scriptArgument2'], // pass args to script
}),
];
}
}
if (argv.mode === 'production') {
serverConfig.devtool = 'source-map';
serverConfig.cache.name = 'production';
serverConfig.optimization.minimize = true;
serverConfig.optimization.minimizer = [
new TerserPlugin({
terserOptions: {
keep_classnames: true,
keep_fnames: true,
},
}),
];
frontendConfig.devtool = 'source-map';
frontendConfig.cache.name = 'production';
frontendConfig.optimization.minimize = true;
frontendConfig.optimization.minimizer = [
new TerserPlugin({
terserOptions: {
keep_classnames: true,
keep_fnames: true,
},
}),
];
}
return [serverConfig, frontendConfig]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment