Jenkins Warnings: Bundle Size Investigation & Support
π¨ Jenkins Warnings: Bundle Size Investigation & Support
π Context
For several weeks, our Jenkins CI/CD pipeline has been consistently reporting warnings related to the JavaScript bundle size generated during production builds. These warnings clutter the Jenkins logs and create confusion regarding the quality of the delivered code. We've identified that this issue doesn't stem from our application code but from the external libraries and dependencies we use, in accordance with the company's development standards.
β οΈ Observed Symptoms
Jenkins Warning
Each production build triggers the following warning:
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
9999.awt_cpv_builder.js (1.95 MiB)
1550.awt_cpv_builder.js (277 KiB)
2000.awt_cpv_builder.js (320 KiB)
Technical Details
- Problematic Bundle:
9999.awt_cpv_builder.js - Uncompressed Size: 1.95 MB
- Estimated Gzipped Size: ~577 KB
- Recommended Limit: 244 KB (360 KB gzipped)
- Exceedance: +217 KB gzipped (or +60% over the limit)
Impact
- β Systematic warnings in Jenkins for several weeks
- β Confusion among development and code review teams
- β Difficulty identifying actual issues in CI/CD logs
- β No user impact - The bundle functions correctly in production
π Investigation by the Development Team
1οΈβ£ Applied Optimizations
β Babel Configuration - Smart Polyfills
Modified file: modules/front-js/babel.config.js
// Configuration added to import only the necessary polyfills
{
modules: false,
useBuiltIns: 'usage', // β Optimization
corejs: 3, // β Optimization
targets: { browsers: [...] }
}
Result: Reduced size by ~50 KB by avoiding the complete import of core-js.
β Removal of Redundant Manual Imports
Modified file: modules/front-js/ts/App.tsx
Removed 8 lines of manual imports for core-js and regenerator-runtime, now managed automatically by Babel.
Result: Cleaner code and reduced size.
β Lazy Loading with webpackChunkName
Modified file: modules/front-js/ts/navigation/LazyRoutes.ts
Added webpackChunkName to 17 lazy-loaded components to optimize code splitting:
// Before
lazy(() => import('../features/octavia/pages/OctaviaRecherchePage'))
// After
lazy(() => import(
/* webpackChunkName: "page-recherche" */
'../features/octavia/pages/OctaviaRecherchePage'
))
Optimized Pages: page-recherche, page-dossiers, page-financement, page-analyse, page-decision, page-engagement, page-roe, page-garantie, page-intervenant, page-detail-intervenant, page-gestion, page-exemple-home, page-exemple-version, page-accessibilite, page-utilisateur-non-autorise, page-alert, wrapped-routes.
Result: Improved chunk identification and preparation for future optimizations.
β Tree Shaking and Minification
- Configuration
usedExports: trueactivated - TerserPlugin for JavaScript minification
- Specific imports from submodules (
@avenir/components/sg-card) - Context replacement for moment.js (French locale only)
2οΈβ£ Webpack Configuration Attempts
We tested 6 different splitChunks configurations to try and reduce the size of bundle 9999:
- β splitChunks configuration with
maxSize: 350000 - β Separating vendors into distinct cacheGroups (React, Redux, Avenir, AWT)
- β Configuration
enforce: trueon cacheGroups - β Complete deactivation of splitChunks (
splitChunks: false) - β Complete replacement of
prodConfig.optimization - β Webpack configuration without inheriting from
prodConfig
Result: None of these configurations changed the size of bundle 9999.
3οΈβ£ Bundle Composition Analysis
We thoroughly analyzed the composition of bundle 9999.awt_cpv_builder.js:
Composition of bundle 9999 (1.95 MB unzipped, ~577 KB gzipped)
ββ @avenir/components : ~200 KB gzipped (34.6%)
ββ @avenir/core : ~50 KB gzipped (8.7%)
ββ react + react-dom : ~130 KB gzipped (22.5%)
ββ redux + redux-saga : ~20 KB gzipped (3.5%)
ββ react-router : ~50 KB gzipped (8.7%)
ββ awt-* libraries : ~50 KB gzipped (8.7%)
β ββ awt-bootstraper
β ββ awt-gda-loader
β ββ awt-natif
β ββ awt-react-extras
β ββ awt-common-log
ββ Utilities : ~77 KB gzipped (13.3%)
ββ axios
ββ formik
ββ yup
ββ date-fns
Total : ~577 KB gzipped
π― Diagnosis: Root Cause Identified
Bundle 9999 is a Shared Vendors Chunk
Bundle 9999.awt_cpv_builder.js is not a bug, but the expected result of webpack's code splitting strategy:
- Automatic Detection: Webpack detects that React, Redux, Avenir Components, etc., are used by all 17 lazy-loaded pages.
- Extraction into a Common Chunk: To optimize browser caching and avoid duplication, webpack extracts these vendors into a single chunk (bundle 9999).
- Performance Trade-off: This optimizes caching but creates a large initial file.
Why the Optimizations Didn't Work
The optimizations we applied (polyfills, tree shaking, lazy loading) reduce application code but not the external vendors, which represent 87% of the bundle.
Bundle 9999 is composed of:
- 87% external libraries: @avenir, React, Redux, AWT, etc.
- 13% application code: Already optimized
π οΈ What We CANNOT Solve on the Development Side
1. Size of Avenir Libraries
Components from @avenir/components (200 KB gzipped) and @avenir/core (50 KB gzipped) represent 43% of the bundle.
Why this is problematic:
- We only use the necessary components via specific imports.
- Tree shaking is active but limited by the library's architecture.
- We cannot modify the source code of
@avenir.
Possible actions only by Avenir maintainers:
- More granular module splitting.
- Bundle size optimization of each component.
- Better tree shaking support.
- Documentation of the heaviest components.
2. Imposed AWT Webpack Configuration
We use the webpack configuration provided by awt-webpack-config@5.3.2, which imposes:
const prodConfig = require('awt-webpack-config/lib/webpack.prod.config.js');
Why this is problematic:
- The
prodConfigconfiguration automatically generates the 9999 vendors bundle. - We cannot modify this logic without stepping outside the AWT framework.
- Attempts to override the configuration had no effect.
Possible actions only by AWT maintainers:
- Provide an option to customize
splitChunks. - Document the expected size limits.
- Provide optimized alternative configurations.
3. Required Framework Dependencies
The XBlocks AWT v7 architecture requires the use of:
- React 18.3.1 (~130 KB gzipped)
- Redux + Redux-Saga (~20 KB gzipped)
- React Router 6.29.0 (~50 KB gzipped)
- AWT libraries (~50 KB gzipped)
Total required dependencies: ~250 KB gzipped (or 43% of the bundle)
These dependencies are necessary to comply with the framework and cannot be replaced or reduced without going outside the imposed development framework.
π Concrete Evidence
Webpack Bundle Analyzer Analysis
We generated a visual report with webpack-bundle-analyzer:
cd modules/front-js
pnpm analyze
Results:
- Bundle 9999 contains 1252 modules from
node_modules. - The 5 heaviest libraries represent 70% of the bundle:
- @avenir/components: 34.6%
- react + react-dom: 22.5%
- Other utilities: 13.3%
- react-router: 8.7%
- @avenir/core: 8.7%
Complete Webpack Logs
orphan modules 7.18 MiB [orphan] 3109 modules
runtime modules 7.71 KiB 13 modules
cacheable modules 8.52 MiB (javascript) 2.7 MiB (asset)
modules by path ./node_modules/.pnpm/ 6.92 MiB (javascript) 2.7 MiB (asset)
javascript modules 6.92 MiB 914 modules
modules by path ./ts/ 1.6 MiB 101 modules
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
Assets:
9999.awt_cpv_builder.js (1.95 MiB)
Observation: The application code (./ts/) represents only 18.7% of the total, while node_modules represents 81.3%.
π Request for Support from Maintainers
To the Avenir Team (@avenir/components, @avenir/core)
Problem: Avenir components represent 43% of our vendors bundle (250 KB gzipped).
Questions:
- Is there a roadmap to reduce the size of the components?
- Are there any components we use that are particularly heavy?
- Is it possible to improve tree shaking to reduce unused imports?
Documentation used:
- Specific imports:
from '@avenir/components/sg-card'β - No global import:
from '@avenir/components'β
Request:
- Audit the size of Avenir components in our project.
- Recommendations to reduce the bundle size.
To the AWT Team (awt-webpack-config, awt-bootstraper)
Problem: The imposed webpack configuration generates a vendors bundle of 577 KB gzipped with a limit of 360 KB.
Questions:
- What is the recommended bundle size limit for an AWT v7 application?
- Is it possible to customize the
splitChunksconfiguration without breaking AWT compatibility? - Are there AWT applications that respect the 360 KB limit for vendors?
Current Configuration:
const prodConfig = require('awt-webpack-config/lib/webpack.prod.config.js');
Request:
- Documentation of best practices to reduce AWT bundle sizes.
- Configuration option to divide the vendors bundle into multiple chunks.
- Clarification on acceptable size limits.
To the XBlocks Framework Team
Problem: The required framework dependencies (React, Redux, Router, AWT libs) represent 250 KB gzipped (43% of the bundle).
Questions:
- Is there a roadmap to reduce the required dependencies?
- Is it possible to externalize some libraries (React, Redux) via CDN?
- What are the recommendations for applications with many lazy-loaded pages?
Request:
- Audit of our architecture to validate that we are following best practices.
- Specific recommendations to reduce the vendors bundle size.
π Impact and Urgency
Current Impact
- β οΈ Medium: Systematic warnings in Jenkins for several weeks
- β οΈ Medium: Confusion within the development teams
- β No user impact: The application functions correctly in production
Urgency
- π΄ Medium: The problem affects the readability of CI/CD pipelines
- π Short term: We need to clarify if this is a real problem or a false positive
- π’ Long term: Improve the architecture to meet the limits
π‘ Proposed Solutions
Option 1: Accept the Trade-off (Recommended in the short term)
Proposition: Accept that the 577 KB gzipped vendors bundle is an acceptable compromise for our architecture.
Justification:
- The bundle contains all vendors for the entire application.
- It is loaded only once and cached.
- Individual pages are small (< 100 KB).
- Overall performance is better than with duplication.
Action:
- Document this exception in the Jenkins configuration.
- Disable the warning specifically for the 9999 bundle.
- Monitor the size evolution.
Option 2: Architecture Refactoring (Long term)
Proposition: Refactor the architecture to create multiple entry points instead of a single vendors bundle.
Approach:
- "Core" bundle with React/Redux/Router (~200 KB)
- "avenir-ui" bundle with Avenir components (~200 KB)
- "features" bundle per business domain (~100 KB each)
Option 3: Collaboration with Maintainers (Preferred)
Proposition: Work with the Avenir and AWT teams to identify optimizations in the source libraries.
Benefit:
- Improvement for all projects using these libraries.
- No modification of our architecture.
- Sustainable solution.
Steps:
- Joint audit of the bundle composition.
- Identification of optimizable components/libraries.
- Implementation of optimizations in the source libraries.
- Update of our dependencies.