Skip to content

Instantly share code, notes, and snippets.

@wesleygrimes
Created November 6, 2024 14:26
Show Gist options
  • Save wesleygrimes/215b8914dd9459d89e8a8a968db79035 to your computer and use it in GitHub Desktop.
Save wesleygrimes/215b8914dd9459d89e8a8a968db79035 to your computer and use it in GitHub Desktop.
ejected webpack config from monolith
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
import { readFileSync } from 'fs';
import GenerateJsonPlugin from 'generate-json-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import { createProxyMiddleware } from 'http-proxy-middleware';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import * as path from 'path';
import RobotstxtPlugin from 'robotstxt-webpack-plugin';
import TerserPlugin from 'terser-webpack-plugin';
import ThreadLoader from 'thread-loader';
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
import { fileURLToPath } from 'url';
import webpack from 'webpack';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
const currentFile = fileURLToPath(import.meta.url);
const currentPath = path.dirname(currentFile);
const rootDir = path.resolve('../../../');
console.log('NODE_ENV', process.env.NODE_ENV);
const deployPublicPath = process.env.NX_DEPLOY_PUBLIC_PATH || '/';
const threadLoaderPool = ThreadLoader.warmup(
{
workers: 10, // Adjust the number of workers based on your CPU cores
workerParallelJobs: 50, // Adjust as needed
},
['ts-loader'] // Loaders to run in the thread pool
);
/** @type {import('webpack').Configuration} */
const config = {
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
target: 'web',
context: path.join(rootDir, 'apps/monolith/marketplace'),
devtool:
process.env.NODE_ENV === 'development'
? 'eval-cheap-module-source-map'
: 'source-map',
/** @type {import('webpack-dev-server').Configuration} */
devServer: {
allowedHosts: 'all',
hot: true,
port: process.env.PORT,
host: process.env.HOST || process.env.NX_HOST_NAME,
historyApiFallback: true,
compress: true,
static: path.join(rootDir, 'apps', 'monolith', 'marketplace', 'dist'),
devMiddleware: {
writeToDisk: true,
stats: 'summary',
},
setupMiddlewares: (middlewares, devServer) => {
if (!devServer) {
throw new Error('webpack-dev-server is not defined');
}
const proxyConfig = JSON.parse(
readFileSync(
path.join(rootDir, 'shared/config/proxy.conf.json'),
'utf-8'
)
);
if (proxyConfig) {
console.log('Using proxy middleware', proxyConfig);
devServer.app.use(
Object.keys(proxyConfig).map((path) => {
const config = proxyConfig[path];
return createProxyMiddleware(path, {
...config,
timeout: 1000 * 5,
});
})
);
}
return middlewares;
},
},
entry: './src/index.tsx',
output: {
path: path.join(rootDir, 'dist', 'apps', 'monolith', 'marketplace'),
filename: 'assets/[name].[contenthash].js',
clean: true,
chunkFilename: 'assets/[name].[chunkhash:20].js',
hashFunction: 'xxhash64',
pathinfo: false,
scriptType: `text/javascript`,
publicPath: '/',
crossOriginLoading: false,
assetModuleFilename: `assets/[hash][ext][query]`,
},
resolve: {
alias: {
'@jane/shared/reefer': path.resolve(rootDir, 'dist/libs/shared/reefer/'),
},
extensions: ['.tsx', '.ts', '.jsx', '.js', '.mjs'],
plugins: [
new TsconfigPathsPlugin({
extensions: ['.tsx', '.ts', '.jsx', '.js', '.mjs'],
mainFields: ['module', 'main'],
}),
],
symlinks: true,
mainFields: ['browser', 'module', 'main'],
},
externals: {
'@jane/shared/reefer': '@jane/shared/reefer', // This will treat it as an external module
},
module: {
parser: {
javascript: {
strictExportPresence: true,
},
},
rules: [
{
test: /\.(bmp|png|jpe?g|gif|webp|avif)$/,
type: 'asset',
parser: { dataUrlCondition: { maxSize: 10000 } },
},
{
test: /\.(j|t)sx?$/,
use: [
{
loader: 'thread-loader',
options: {
workerParallelJobs: 50, // Adjust as needed
pool: threadLoaderPool, // Use the created thread pool
},
},
{
loader: 'ts-loader',
options: {
// ... your ts-loader options
happyPackMode: true, // Important for thread-loader
transpileOnly: true,
},
},
],
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: [
process.env.NODE_ENV === 'production'
? {
loader: MiniCssExtractPlugin.loader,
options: {
esModule: true,
},
}
: 'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
// Enable CSS Modules if needed
modules: {
auto: /\.module\.\w+$/,
localIdentName:
process.env.NODE_ENV === 'development'
? '[path][name]__[local]'
: '[hash:base64]',
},
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
config: path.join(currentPath, 'postcss.config.cjs'),
},
},
},
],
},
{
test: /\.svg$/,
use: [
{
loader: '@svgr/webpack',
options: {
exportType: 'named',
},
},
'url-loader',
],
},
{
test: /\.(woff|woff2|eot|ttf|otf|mp3)$/,
type: 'asset/resource',
},
{
test: /monolith\/shared\//,
sideEffects: false,
},
],
},
plugins: [
new HtmlWebpackPlugin({
chunks: 'all',
chunkSortMode: 'none',
googleClientId: process.env.NX_GOOGLE_CLIENT_ID,
inject: 'body',
appCuesEnabled: process.env.NODE_ENV !== 'test',
template: 'src/index.html',
filename: 'index.html',
gaTrackingId: process.env.NX_GOOGLE_ANALYTICS_CUSTOMER_TRACKING_ID,
mixpanelEnabled: true,
showBrowserUpdate: true,
}),
new webpack.ProgressPlugin({}),
new webpack.DefinePlugin({
'process.env': JSON.stringify(
// we only want to pass NX_ env vars to our application code
Object.entries(process.env)
.filter(([key]) => key.startsWith('NX_'))
.reduce((acc, [key, value]) => {
acc[key] = value;
return acc;
}, {})
),
}),
new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^no-locales$/),
new GenerateJsonPlugin('version.json', {
buildVersion: process.env.NX_BUILD_VERSION,
}),
new RobotstxtPlugin(
process.env.NODE_ENV === 'production'
? {
policy: [
{
userAgent: 'AhrefsBot',
disallow: ['/'],
},
{
userAgent: 'SemrushBot',
disallow: ['/'],
},
{
userAgent: '*',
disallow: [
'/cart/',
'/profile/',
'/v1/client/frameless_embeds/',
],
},
],
sitemap:
deployPublicPath !== '/'
? `${deployPublicPath}sitemap.xml.gz`
: undefined,
}
: {
policy: [
{
userAgent: '*',
disallow: '/',
},
],
}
),
process.env.NODE_ENV === 'development' &&
process.env.WEBPACK_SERVE &&
new ReactRefreshWebpackPlugin(),
Boolean(process.env.STATS) && new BundleAnalyzerPlugin(),
process.env.NODE_ENV === 'production' &&
new MiniCssExtractPlugin({
chunkFilename: 'assets/[name].[contenthash:20].css',
filename: 'assets/[name].[contenthash:20].css',
ignoreOrder: false,
experimentalUseImportModule: false,
runtime: true,
linkType: 'text/css',
}),
],
node: {
__dirname: true,
__filename: true,
global: true,
},
stats: {
reasons: true, // Show reasons why modules are included
chunks: true, // Show chunk details
orphanModules: true, // List orphan modules
},
};
// cache assets on the filesystem in development
// this helps speed up subsequent builds
if (process.env.NODE_ENV === 'development' && !process.env.SKIP_CACHE) {
config.cache = {
type: 'filesystem',
cacheDirectory: path.join(rootDir, 'node_modules/.cache/webpack'),
name: 'monolith-marketplace',
buildDependencies: {
config: [currentFile],
},
};
}
// enable optimizations for production builds
if (process.env.NODE_ENV === 'production') {
config.optimization = {
minimize: true,
minimizer: [
new TerserPlugin({
// CLIENT_MAX_PROCESSES is typically set in CircleCI
// otherwise we fall back to true which is os.cpus().length - 1
// more info here: https://webpack.js.org/plugins/terser-webpack-plugin/#parallel
parallel: Number(process.env.CLIENT_MAX_PROCESSES) || true,
extractComments: false,
minify: TerserPlugin.terserMinify,
terserOptions: {
sourceMap: true,
ecma: 2016,
safari10: true,
output: {
ascii_only: true,
comments: false,
webkit: true,
},
},
}),
new webpack.ids.HashedModuleIdsPlugin({
context: currentPath,
hashFunction: 'sha256',
hashDigest: 'hex',
hashDigestLength: 20,
}),
new CssMinimizerPlugin(),
],
emitOnErrors: false,
runtimeChunk: 'single',
concatenateModules: false,
moduleIds: 'deterministic',
splitChunks: {
chunks: 'all',
maxAsyncRequests: Infinity,
cacheGroups: {
janeSharedReefer: {
test: /[\\/]@jane[\\/]shared[\\/]reefer[\\/]/,
name: 'jane-shared-reefer',
chunks: 'all',
},
default: {
chunks: 'async',
minChunks: 2,
priority: 10,
},
common: {
name: 'common',
chunks: 'async',
minChunks: 2,
enforce: true,
priority: 5,
},
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
reuseExistingChunk: true,
enforce: true,
},
},
},
};
}
export default config;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment