Last active
January 22, 2023 19:59
-
-
Save dmexs/a7102ac4842eedd5fbbf452a0f8de4e2 to your computer and use it in GitHub Desktop.
NestJS Webpack Multiple Configs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** 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