-
Notifications
You must be signed in to change notification settings - Fork 12k
Regression in main bundle size. #20149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This bootstrapping code was actually never supported. In fact, pre version 11.1, when using The former is used to bootstrap JIT applications. Before /*!*********************!*\
!*** ./src/main.ts ***!
\*********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
(() => __awaiter(void 0, void 0, void 0, function* () {
const { enableProdMode } = yield __webpack_require__.e(/*! import() | angular-core */ "default~angular-core~angular-platform-browser-dynamic~app-app-module").then(__webpack_require__.bind(null, /*! @angular/core */ "fXoL"));
const { platformBrowserDynamic } = yield Promise.all(/*! import() | angular-platform-browser-dynamic */[__webpack_require__.e("default~angular-core~angular-platform-browser-dynamic~app-app-module"), __webpack_require__.e("default~angular-platform-browser-dynamic~app-app-module"), __webpack_require__.e("angular-platform-browser-dynamic")]).then(__webpack_require__.bind(null, /*! @angular/platform-browser-dynamic */ "a3Wg"));
const { AppModule } = yield Promise.all(/*! import() | app-app-module */[__webpack_require__.e("default~angular-core~angular-platform-browser-dynamic~app-app-module"), __webpack_require__.e("default~angular-platform-browser-dynamic~app-app-module"), __webpack_require__.e("app-app-module")]).then(__webpack_require__.bind(null, /*! ./app/app.module */ "ZAI4"));
const { environment } = yield __webpack_require__.e(/*! import() | environments-environment */ "environments-environment").then(__webpack_require__.bind(null, /*! ./environments/environment */ "AytR"));
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}))();
/***/ }) In 11,.1, with the new Ivy plugin system, a non dynamic import is added and the bootstrapping code is change to use After /*!*********************!*\
!*** ./src/main.ts ***!
\*********************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/platform-browser */ "jhN1");
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
(() => __awaiter(void 0, void 0, void 0, function* () {
const { enableProdMode } = yield Promise.resolve(/*! import() */).then(__webpack_require__.bind(null, /*! @angular/core */ "fXoL"));
const { platformBrowserDynamic } = yield __webpack_require__.e(/*! import() | angular-platform-browser-dynamic */ "angular-platform-browser-dynamic").then(__webpack_require__.bind(null, /*! @angular/platform-browser-dynamic */ "a3Wg"));
const { AppModule } = yield __webpack_require__.e(/*! import() | app-app-module */ "app-app-module").then(__webpack_require__.bind(null, /*! ./app/app.module */ "ZAI4"));
const { environment } = yield __webpack_require__.e(/*! import() | environments-environment */ "environments-environment").then(__webpack_require__.bind(null, /*! ./environments/environment */ "AytR"));
if (environment.production) {
enableProdMode();
}
_angular_platform_browser__WEBPACK_IMPORTED_MODULE_0__["platformBrowser"]()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}))(); Assuming you are not going to use JIT, to disable the above behaviour you can replace the (async () => {
const { enableProdMode } = await import('@angular/core');
- const { platformBrowserDynamic } = await import('@angular/platform-browser-dynamic');
+ const { platformBrowser } = await import('@angular/platform-browser');
const { AppModule } = await import('./app/app.module');
const { environment } = await import('./environments/environment');
if (environment.production) {
enableProdMode();
}
- platformBrowserDynamic()
+ platformBrowser()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
})(); Using dynamic imports, can cause optimization bailouts which will result in larger bundle sizes. in general I don't think that the above is a common good practice to support as users might user the above pattern without fully understanding the consequences. Seeing that the above pattern is not recommended and there is a workaround for your problem I think it's best not to take action. To support the above pattern, the transformer code will need to be extended to handle this use-case, which few people would benefit from. |
@alan-agius4 The provided code is an example of what happens. It's not coding that is used as-is in production code.
I think those do outweigh the current optimization bailout. Also, optimization bailout is a tooling artifact, and while important, it should not be leading in how to architect an application. When tooling matures, it will start picking up on those patterns. Thanks for explaining the platform vs platformDynamic, the workaround works, and I don't need JIT in most of my apps anyway. |
Following our offline convo. This is also related to why we use FESM's instead of ESM. #13635 (When not using FESM there would be a size increase of While I do see that the benefit for SSG, there are some cavets, the underlying tooling struggles to optimize when having a lot of files (Webpack and Terser). In the above case the initial size of the application more than doubles in size with an increase of about Keep tooling in mind when architecting your application is also important IMHO similarly to when you intend to HMR or SSR, if you do want to successfully use such features you need to keep these in mind when architecting your application. Eventually when tooling does support your desired architecture you can update it. Currently, I don't see as there is anything actionable from our end since this is a limitation of how underlying tools work and expects the JavaScript input. If you do find that such optimization bailout are acceptable for you, there is nothing which is stopping you from using the above bootstrapping code. I do however suggest the above to be used with caution a period analysing of your bundle as overtime you might end up retaining a lot of unused code in your chunks. Cross chunk optimization is something high on our wishlist as well. Feel free to reach out on Slack to discuss this more. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
🐞 Bug report
Command (mark with an
x
)Is this a regression?
Yes, the previous version in which this bug was not present was: ....Description
When I build my app with version
11.0.7
, this is the initial bundle:When I upgrade to
11.2.2
, this is the initial bundle:That is a 359Kb size increase of
main.js
🔬 Minimal Reproduction
In the new app, update main to:
then build and notice the main bundle size
after that,
ng update @angular/cli @angular/core
Build and notice the increased bundle size.
The text was updated successfully, but these errors were encountered: