Created
September 30, 2023 18:41
-
-
Save petrosmm/9573d59dd5699bc9adefc14eab37b352 to your computer and use it in GitHub Desktop.
working but slightly messy next.config.js with bundle splitting for webpack5 / nextjs 13
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
/** | |
* @typedef {import("next").NextConfig} NextConfig | |
* @typedef {import("webpack").Configuration} WebpackConfig | |
* @typedef {import("next/dist/server/config-shared").WebpackConfigContext} WebpackConfigContext | |
* @typedef {(config: WebpackConfig, context: WebpackConfigContext) => any} NextWebpackConfig | |
* @typedef {import("webpack").optimize.SplitChunksPlugin} SplitChunksPlugin | |
* @typedef {import("@next/bundle-analyzer")} BundleAnalyzerPlugin | |
* @typedef {import("copy-webpack-plugin")} CopyPlugin | |
* https://nextjs.org/docs/api-reference/next.config.js/custom-webpack-config | |
* https://adamjberkowitz.com/blog/post/managing-webpack-vendor-chunks-and-wordpress | |
* https://github.com/vercel/next.js/discussions/35969#discussioncomment-2523019 | |
* https://medium.com/faceyspacey/how-to-use-webpacks-new-magic-comment-feature-with-react-universal-component-ssr-a38fd3e296a | |
*/ | |
// const path = require("path") | |
// const buildPath = process.env !== "production" ? path.resolve(__dirname, "dev-build") : path.resolve(__dirname, "build"); | |
// const TerserPlugin = require("terser-webpack-plugin"); | |
const plugins = []; | |
const isAnalyze = process.env.ANALYZE === "true"; | |
const webpack = require("webpack"); | |
const pageExtensions = ["page.tsx", "page.ts", "page.jsx", "page.js", "api.ts", "api.js", /* just incase */ "api.tsx"]; | |
const CopyPlugin = require("copy-webpack-plugin"); | |
/** @type CopyPlugin */ | |
const copyPlugin = new CopyPlugin({ | |
patterns: [ | |
{ | |
from: './server-resources', | |
to: './server-resources', | |
}, | |
{ | |
from: './server-resources', | |
to: './server-resources', | |
}, | |
], | |
}); | |
// bundle analyzer here | |
if (isAnalyze) { | |
// only load dependency if env `ANALYZE` was set | |
/** @type BundleAnalyzerPlugin */ | |
const withBundleAnalyzer = require("@next/bundle-analyzer")({ | |
enabled: true, | |
}); | |
plugins.push(withBundleAnalyzer) | |
} | |
/** @type {Omit<NextConfig, 'webpack'>} nextConfig */ | |
const nextConfig = { | |
// https://nextjs.org/docs/pages/api-reference/next-config-js/output | |
distDir: "out", | |
reactStrictMode: true, | |
// keep this compression off it's gzip based: https://nextjs.org/docs/pages/api-reference/next-config-js/compress | |
compress: false, | |
pageExtensions: pageExtensions, | |
poweredByHeader: false, | |
swcMinify: true, | |
/** @type {NextWebpackConfig} */ | |
webpack(config, context) { | |
let isDev = context.dev; | |
let isServer = context.isServer; | |
// https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application | |
if (false) if (!isServer && true) { config.resolve.fallback = { fs: false }; } | |
if (false) | |
config.resolve.fallback = { | |
"fs": false, | |
"path": false, | |
"os": false, | |
}; | |
// NOTE: jQuery added via | |
// https://dev.to/anuraggharat/adding-bootstrap-to-nextjs-39b2 | |
if (!isDev) { | |
// https://medium.com/@abhayshiravanthe/modules-and-code-splitting-in-webpack-5-6ce0a58d7f36 | |
config.optimization.splitChunks = {}; | |
config.optimization.splitChunks.automaticNameDelimiter = "_"; | |
config.optimization.splitChunks.minSize = 17000; | |
config.optimization.splitChunks.minRemainingSize = 0; | |
config.optimization.splitChunks.minChunks = 1; | |
config.optimization.splitChunks.maxAsyncRequests = 30; | |
config.optimization.splitChunks.maxInitialRequests = 30; | |
config.optimization.splitChunks.automaticNameDelimiter = "_"; | |
config.optimization.splitChunks.enforceSizeThreshold = 30000; | |
config.optimization.splitChunks.cacheGroups = { | |
common: { | |
test: /[\\/]node_modules[\\/]/, | |
priority: -5, | |
reuseExistingChunk: true, | |
chunks: "initial", | |
name: "common_app", | |
minSize: 0, | |
}, | |
default: { | |
minChunks: 2, | |
priority: -20, | |
reuseExistingChunk: true, | |
}, | |
// we are opting out of defaultVendors, so rest of the node modules will be part of default cacheGroup | |
defaultVendors: false, | |
bootstrap: { | |
test: /[\\/]node_modules[\\/](bootstrap)[\\/]/, | |
name: 'vendor_bootstrap', | |
chunks: "all", | |
priority: 9, | |
}, | |
reactPackage: { | |
test: /[\\/]node_modules[\\/](react|react-dom|react-router|react-router-dom|react-usestateref|react-query)[\\/]/, | |
name: 'vendor_react', | |
chunks: "all", | |
priority: 10, | |
}, | |
// not sure which popper picks up | |
jqueryAndPopper: { | |
test: /[\\/]node_modules[\\/](jquery|popper|@popperjs|popperjs|popper.js)[\\/]/, | |
name: 'vendor_jqueryandpopper', | |
chunks: "all", | |
priority: 11, | |
}, | |
moment: { | |
test: /[\\/]node_modules[\\/](moment)[\\/]/, | |
name: 'vendor_moment', | |
chunks: "all", | |
priority: 12, | |
}, | |
linq: { | |
test: /[\\/]node_modules[\\/](linq)[\\/]/, | |
name: 'vendor_linq', | |
chunks: "all", | |
priority: 13, | |
}, | |
mui_material: { | |
test: /[\\/]node_modules[\\/](@mui)[\\/](material|icons-material|base|system)[\\/]/, | |
name: 'vendor_muimaterial', | |
chunks: "all", | |
priority: 14, | |
}, | |
mui_material_date: { | |
test: /[\\/]node_modules[\\/](@mui)[\\/](x-date-pickers)[\\/]/, | |
name: 'vendor_muimaterial_date', | |
chunks: "all", | |
priority: 15, | |
}, | |
misc: { | |
test: /[\\/]node_modules[\\/](html-minifier|html-react-parser|react-obfuscate-email|string-strip-html|mime-types)[\\/]/, | |
name: 'vendor_misc', | |
chunks: "all", | |
priority: 16, | |
}, | |
// serverside chunk only | |
directus: { | |
test: /[\\/]node_modules[\\/](@directus)[\\/](sdk)[\\/]/, | |
name: 'vendor_directus', | |
chunks: "all", | |
priority: 17, | |
}, | |
chrono_node: { | |
test: /[\\/]node_modules[\\/](chrono-node)[\\/]/, | |
name: 'vendor_chrono-node', | |
chunks: "all", | |
priority: 18, | |
}, | |
emotion: { | |
test: /[\\/]node_modules[\\/](@emotion)[\\/](styled|react)[\\/]/, | |
name: 'vendor_emotion', | |
chunks: "all", | |
priority: 19, | |
}, | |
// TODO does not do anything remove me later, please | |
deprecated: { | |
test: /[\\/]node_modules[\\/](graphql-tag|material-ui-popup-state)[\\/]/, | |
name: 'vendor_deprecated', | |
chunks: "all", | |
priority: 20, | |
}, | |
}; | |
} | |
config.plugins.push(copyPlugin); | |
if (false) | |
console.log(`config.plugins`, config.plugins); | |
config.optimization.minimize = !isDev; | |
config.optimization.chunkIds = "deterministic"; | |
config.optimization.moduleIds = "deterministic"; | |
if (false) { | |
this.rewrites = async () => { | |
// let z = await fetch("https://reqres.in/api/users?page=2"); | |
// let zz = await z.json(); | |
if (false) { | |
// console.log(zz); | |
console.log("hello from rewrites"); | |
} | |
return { | |
// After checking all Next.js pages (including dynamic routes) | |
// and static files we proxy any other requests | |
fallback: [ | |
{ | |
source: "/:path*", | |
destination: `https://www.website.org/:path*`, | |
}, | |
], | |
} | |
}; | |
} | |
return config; | |
}, | |
staticPageGenerationTimeout: 2400, | |
experimental: { | |
// largePageDataBytes: 128 * 100000, | |
isrMemoryCacheSize: 150, | |
}, | |
// https://nextjs.org/docs/pages/api-reference/next-config-js/rewrites | |
rewrites: undefined, | |
} | |
module.exports = () => plugins.reduce((acc, next) => next(acc), nextConfig); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment