@@ -15,6 +15,64 @@ function localPolyfill(name) {
1515 return path . resolve ( __dirname , 'polyfills' , ...name . split ( '/' ) , 'index.ts' ) ;
1616}
1717
18+ function normalizeDepName ( name ) {
19+ return name . replaceAll ( '@' , '' ) . replaceAll ( '/' , '__' ) ;
20+ }
21+
22+ function resolveDepEntry ( name ) {
23+ const monorepoPackagesDir = path . resolve ( __dirname , '..' ) ;
24+ const resolvedPath = require . resolve ( name ) ;
25+ if ( resolvedPath . startsWith ( monorepoPackagesDir ) ) {
26+ const packageJson = require ( `${ name } /package.json` ) ;
27+ const packageRoot = path . dirname ( require . resolve ( `${ name } /package.json` ) ) ;
28+ const entrypoint = path . join (
29+ packageRoot ,
30+ packageJson [ 'compass:main' ] ?? packageJson [ 'main' ]
31+ ) ;
32+ return entrypoint ;
33+ }
34+ return require . resolve ( name ) ;
35+ }
36+
37+ /**
38+ * Takes in a webpack configuration for a library package and creates a
39+ * multi-compiler config that splits the library into multiple parts that can be
40+ * properly processed by another webpack compilation.
41+ *
42+ * This is opposed to using a webpack chunk splitting feature that will generate
43+ * the code that uses internal webpack module runtime that will not be handled
44+ * by any other bundler. This custom code splitting is way less advanced, but
45+ * works well for leaf node dependencies of the package.
46+ *
47+ * NB: This naive implementation works well only for leaf dependencies with a
48+ * single export file. It can be updated to support multiple exports packages,
49+ * but we can skip this for now
50+ */
51+ function createSiblingBundleFromLeafDeps (
52+ config ,
53+ deps ,
54+ moduleType = 'commonjs2'
55+ ) {
56+ const siblings = Object . fromEntries (
57+ deps . map ( ( depName ) => {
58+ return [ depName , `${ moduleType } ./${ normalizeDepName ( depName ) } .js` ] ;
59+ } )
60+ ) ;
61+ const baseConfig = merge ( config , { externals : siblings } ) ;
62+ const configs = [ baseConfig ] . concat (
63+ deps . map ( ( depName ) => {
64+ return merge ( baseConfig , {
65+ entry : resolveDepEntry ( depName ) ,
66+ output : {
67+ filename : `${ normalizeDepName ( depName ) } .js` ,
68+ library : { type : moduleType } ,
69+ } ,
70+ } ) ;
71+ } )
72+ ) ;
73+ return configs ;
74+ }
75+
1876/**
1977 * Atlas Cloud uses in-flight compression that doesn't compress anything that is
2078 * bigger than 10MB, we want to make sure that compass-web assets stay under the
@@ -222,7 +280,7 @@ module.exports = (env, args) => {
222280 } ,
223281 } ;
224282
225- return merge ( config , {
283+ const compassWebConfig = merge ( config , {
226284 externals : {
227285 react : 'commonjs2 react' ,
228286 'react-dom' : 'commonjs2 react-dom' ,
@@ -258,4 +316,18 @@ module.exports = (env, args) => {
258316 } ,
259317 ] ,
260318 } ) ;
319+
320+ // Split production bundle into more chunks to make sure it's easier for us to
321+ // stay under the max chunk limit. Be careful when adding new packages here,
322+ // make sure you're only selecting big packages with the smallest amount of
323+ // shared dependencies possible
324+ const bundles = createSiblingBundleFromLeafDeps ( compassWebConfig , [
325+ '@mongodb-js/compass-components' ,
326+ 'bson-transpilers' ,
327+ // bson is not that big, but is a shared dependency of compass-web,
328+ // compass-components and bson-transpilers, so splitting it out
329+ 'bson' ,
330+ ] ) ;
331+
332+ return bundles ;
261333} ;
0 commit comments