You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SSR builder and externals dependencies (Angular 9) #16348
In some specific scenarios, I would like to bundle dependencies and minify the code of my Angular application, but at the same time leave my server-side code untouched (no dependencies bundled, no minification/obfuscation). This is important because:
sometimes you may not want to bundle all server dependencies (especially when you're building a full-stack app). For instance, you won’t be able to bundle pg (if you use postgres) as well as internal deps of mongoose (or bcrypt) because they use a native node.js binaries (C++ code)
sometimes you may not want to obfuscate class names, properties names, function names etc because there are important for libraries such as Typeorm (to automatically create columns with proper names in a database) or e.g. NestJS. Having full control over what can be optimized for server-side is quite important here
What is the current behavior?
When I try to set bundleDependencies to none under server configuration in angular.json, the application will stop working:
Both serve:ssr and serve:ssr:dev won't work.
Also, I'm not entirely sure how I can determine the behavior of webpack for the server part now. Previously, we had webpack.server.config in which we could simply use plugins like nodeExternals or set optimization to false (to avoid code minification). This is worth adding to the docs (how to accomplish this now with a new setup).
Disable server dependency bundling which can be done via the angular.json configuration. Under your server target options add "bundleDependencies": "none"
Run NGCC binary prior to building. This can be done by adding a postinstall script in your package.json - "postinstall": "ngcc"
Following the above steps fixed the issue, thanks!
Nonetheless, I still can't find a way to apply a custom webpack configuration to both build:ssr (for prod) and serve:ssr:dev scripts. I want to leverage builders to avoid using three different scripts (as in Angular <= 8), have a live reload built-in and at the same time, have an ability to adjust ts-loader configuration (e.g. apply plugins) and externals dynamically from js file. Is it possible?
Also, since adding postinstall script, manually removing & reinstalling all packages and setting bundleDependencies to none isn't straightforward, I'd suggest adding an option to the ng add UNIVERSAL_ENGINE[?] schematic that would perform all these tasks automatically (e.g. --no-bundle-server?).
This is, in fact, very important for everyone who wants to not only serve SSR Angular app but also create, for instance, a basic REST API that connects to a database. With current setup (without manually performing all changes listed above), the following stack: express/nestjs/koa + Angular SSR + postgres/mongoose won't work properly.
Nonetheless, I still can't find a way to apply a custom webpack configuration to both build:ssr (for prod) and serve:ssr:dev scripts. I want to leverage builders to avoid using three different scripts (as in Angular <= 8), have a live reload built-in and at the same time, have an ability to adjust ts-loader configuration (e.g. apply plugins) and externals dynamically from js file. Is it possible?
To achive this you'd need to replace the @angular-devkit/build-angular:server builder with a 3rd party builder that allows such behaviour.
This is, in fact, very important for everyone who wants to not only serve SSR Angular app but also create, for instance, a basic REST API that connects to a database. With current setup (without manually performing all changes listed above), the following stack: express/nestjs/koa + Angular SSR + postgres/mongoose won't work properly.
Can you elaborate please to why this doesn't work properly? Is this because @nestjs/ng-universal requires a bundle as an external file?
Can you elaborate please to why this doesn't work properly? Is this because @nestjs/ng-universal requires a bundle as an external file?
It's not about @nestjs/ng-universal. Even with a default configuration and the @angular-devkit/build-angular:server builder, NestJS itself will work fine.
The problem starts when you would like to create a real-world full-stack app with Angular SSR, regardless of whether you're going to use either express or NestJS or anything else.
Once you try to "bundle" your app which consists of Angular, Express and MongoDB, you will see the following error:
Error: Cannot find module './drivers/node-mongodb-native/connection'
at webpackEmptyContext
Why? Because mongoose depends on mongodb which depends on kerberos (C++) and node-gyp.
Similarly, if you try to build an application which consists of Angular, Express, and Postgres (with, let's say, TypeORM as ORM), you will see this error:
ERROR in ./node_modules/pg/lib/native/client.js
Module not found: Error: Can't resolve 'pg-native'
Why? Because pg depends on pg-native which depends on node-libpq (low level C++ native bindings to PostgreSQL).
Lots of popular Node.js packages that are "required" to build a typical REST/GraphQL API depend on native bindings. With the current (default) configuration, this builder will be useless for most people who want to do more than perform server-side rendering.
I see what you mean now, maybe we should also users to specify externals in an easier manner. I'll move this to the CLI repo since that is where the server builder resides.
We'll have a chat around this in our next team meeting and we'll decide if we should support this out-of-box or rely on 3rd party builders to allow specifying externals.
Activity
alan-agius4 commentedon Dec 4, 2019
Hi, this is expected unless 'node_modules' are transformed using the standalone Angular compatibility compiler (NGCC).
See: angular/universal#1327 (comment) for more context and how to address this.
kamilmysliwiec commentedon Dec 4, 2019
Following the above steps fixed the issue, thanks!
Nonetheless, I still can't find a way to apply a custom webpack configuration to both
build:ssr(for prod) andserve:ssr:devscripts. I want to leverage builders to avoid using three different scripts (as in Angular <= 8), have a live reload built-in and at the same time, have an ability to adjustts-loaderconfiguration (e.g. apply plugins) andexternalsdynamically from js file. Is it possible?kamilmysliwiec commentedon Dec 4, 2019
Also, since adding
postinstallscript, manually removing & reinstalling all packages and settingbundleDependenciestononeisn't straightforward, I'd suggest adding an option to theng add UNIVERSAL_ENGINE[?]schematic that would perform all these tasks automatically (e.g.--no-bundle-server?).This is, in fact, very important for everyone who wants to not only serve SSR Angular app but also create, for instance, a basic REST API that connects to a database. With current setup (without manually performing all changes listed above), the following stack:
express/nestjs/koa + Angular SSR + postgres/mongoosewon't work properly.alan-agius4 commentedon Dec 4, 2019
To achive this you'd need to replace the
@angular-devkit/build-angular:serverbuilder with a 3rd party builder that allows such behaviour.Can you elaborate please to why this doesn't work properly? Is this because
@nestjs/ng-universalrequires abundleas an external file?kamilmysliwiec commentedon Dec 4, 2019
It's not about
@nestjs/ng-universal. Even with a default configuration and the@angular-devkit/build-angular:serverbuilder, NestJS itself will work fine.The problem starts when you would like to create a real-world full-stack app with Angular SSR, regardless of whether you're going to use either express or NestJS or anything else.
Once you try to "bundle" your app which consists of Angular, Express and MongoDB, you will see the following error:
Why? Because
mongoosedepends onmongodbwhich depends on kerberos (C++) andnode-gyp.Similarly, if you try to build an application which consists of Angular, Express, and Postgres (with, let's say, TypeORM as ORM), you will see this error:
Why? Because
pgdepends onpg-nativewhich depends on node-libpq (low level C++ native bindings to PostgreSQL).Lots of popular Node.js packages that are "required" to build a typical REST/GraphQL API depend on native bindings. With the current (default) configuration, this builder will be useless for most people who want to do more than perform server-side rendering.
alan-agius4 commentedon Dec 4, 2019
I see what you mean now, maybe we should also users to specify
externalsin an easier manner. I'll move this to the CLI repo since that is where the server builder resides.We'll have a chat around this in our next team meeting and we'll decide if we should support this out-of-box or rely on 3rd party builders to allow specifying
externals.fix(@angular-devkit/build-angular): add `externalDependencies` to ser…
angular-automatic-lock-bot commentedon Jan 6, 2020
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.
fix(@angular-devkit/build-angular): add `externalDependencies` to ser…