angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.74k stars 11.98k forks source link

Default to production builds #14471

Closed StephenFluin closed 3 years ago

StephenFluin commented 5 years ago

🚀 Feature request

I know this is tough due to it being a breaking change with the ecosystem, but I think ng build should do a production build by default.

Command (mark with an x)

- [x] build

Description

Most of the time, developers should be building for production, and serving for development. It would save a lot of time overall if ng build defaulted to production mode.

Describe the solution you'd like

During the update process to 9 (or some other version), prompt the user if they want to keep the current behavior or migrate to the new behavior, and then default all new projects with ng new to production by default.

Describe alternatives you've considered

None

filipesilva commented 5 years ago

We actually followed this exact reasoning in 1.6, and some users were caught by surprise in a nasty way (https://github.com/angular/angular-cli/issues/10191), prompting us to revert it (https://github.com/angular/devkit/commit/b9704dc16efcbdfa3ccad59056709331bb2c4f50).

I can't imagine doing this change now would go any better since users have been used to npm run build not doing prod builds for much longer now.

@alexeagle WDYT?

mgechev commented 5 years ago

Based on our discussion today, the feature makes a lot of sense. We should be very explicit in the way we communicate that we're using --prod.

StephenFluin commented 5 years ago

@mgechev Are you saying the right behavior is to default to non-prod or to production mode?

clydin commented 5 years ago

Build —> production by default Serve —> development by default

When the changeover happens (9.0? Sooner?) the concept would be that in addition to messaging in the release notes, a informational message would be displayed on build execution to provide ample opportunity to inform the user of the change in behavior.

filipesilva commented 5 years ago

Using our current setup, we could make the default options for build in angular.json contain the production settings, and have a separate dev configuration for development settings. Then ng serve would target the dev configuration for its build options.

We'd also have to provide good messages in the CLI about this. Users are used to using the --prod flag.

StephenFluin commented 5 years ago

Awesome! Perhaps we could consider an update schematic that adds a "legacyBuildDefault"= true somewhere to existing applications that update to help folks with the transition.

vikerman commented 5 years ago

This requires documentation changes and communicating to the user.

v9 with Ivy might not be the right time for this.

@StephenFluin - It would be good to have a design doc for this.

vthinkxie commented 4 years ago

Hi @mgechev @filipesilva @StephenFluin

I think we should make ng build --prod as default in angular-cli v9

We maintain an angular component library and we almost could receive dozens of the same question every week, that is

Why the angular build out is so big(3MB or larger)? and why the performance is so poor? we do not want to use it any longer

when they run ng build or npm run build

We have to explain that prod mode is not the default mode, plz use ng build --prod instead.

The ng build --prod has been detailed in the official documentation, but many new users just skip the document and just run npm run build (equals ng build) in the project generated by @angular/cli.

Angular may lose quite a lot of users due to the misunderstanding of ng build. I think it is time to make --prod mode default in command ng build.

dgp1130 commented 4 years ago

Consensus seems to be that this is a good idea which we should do. At this point we pretty much just need to actually implement it.

dgp1130 commented 3 years ago

We had some discussion today about how to actually make this happen as there is a lot more underlying complexity than is immediately obvious. Some general notes:

Currently angular.json has options for ng build and various configurations. The default options are generally interpreted as "development" while --configuration production contains the production options. This is what is set up with ng new, but technically a project can have any number of configurations which can mean whatever they want. Angular is very flexible in this regard, but it also means we can make less assumptions about what changing configurations will actually do to an arbitrary project.

To reference similar projects, vue build defaults to production, while vue serve defaults to development (--mode flag). Although I believe Angular is more configurable about what "production" and "development" actually means, so Vue has a stronger abstraction model here.

There is still more discussion to be had here, but our current thought process is:

  1. Update existing projects' npm run build script to actually execute ng build --configuration production.
    • This should fix services like Heroku which run npm run build and will make them use production builds.
    • For comparison, create-react-app and Vue both make npm run build generate a production build.
  2. Update ng new schematics such that ng build uses production options by default.
    • We'll also make a separate development configuration that just needs to be explicitly passed.
    • ng serve needs to be updated to use --configuration development by default if available.
  3. Create an optional migration for existing projects to make the production configuration default and add a separate development configuration with the current options.
    • Making this migration optional avoids a potentially significant and painful migration of angular.json being forced on users.
    • Users who really want this behavior and are invested in the change are willing to run a migration to get it.
  4. Deprecate ng * --prod in favor of ng * --configuration production.

This does have a few notable caveats:

  1. npm run build will now be different than ng build.
    • This will certainly trip some people up who would expect these two commands to be mostly equivalent.
    • Only a disconnect for existing projects that do not migrate.
  2. ng build semantics vary by project.
    • Since the migration is optional, at least some existing projects will continue to have ng build -> "development", while new projects will have ng build -> "production".
    • A new developer joining an Angular project has no good way of knowing what ng build will do without looking at the project setup (which requires non-trivial knowledge of Angular configurations) or just trying it and seeing what happens.
  3. Existing education content will likely need to be updated.
    • ng new --defaults foo && cd foo && ng build will now be prod and --configuration production would be removed and likely fail validation.
    • (Note to content authors, pin your versions to protect yourself from changes like this! For example, don't write npm install @angular/cli, write npm install @angular/cli@11.0.0.)

The biggest question we don't have a good answer to is what should happen for ng build --watch? It is just an ng build command, so if we did nothing special, this would build for production, which is most likely not what the user wanted. Some possible thoughts:

Definitely still more discussion to be had, so we'll follow up with this next week (or maybe after the holidays).

dgp1130 commented 3 years ago

Discussed this issue a little more today.

Regarding the watch issue, we decided the simplest solution is to just add npm run watch which executes ng build --watch --configuration development. This causes the least changes and introduces minimal confusion to users. NPM scripts are also generally well understood by web developers and the extra transparency means looking up "What does npm run build do for this project?" is a lot easier than "What does ng build --watch do for this project?"

The ng watch solution seemed to be the next most liked solution, however it is a bit heavyweight and we didn't want to fully commit to that just yet. Instead, we decided to move forward with just npm run watch for now with some documentation and release notes pointing users to prefer that. If we still see a lot of confusion in this area, we can reconsider a more comprehensive change around deprecating ng build --watch and migrating users to ng watch. (Personally I feel my suggestion of ng serve --dont did not receive the consideration it should have :laughing:.)

Also a quick correction to the previous comment: ng serve, would not use --configuration development by default, but rather --browserTarget app:build:development. The use of --browserTarget means that we don't default to --configuration development, which would add flag confusion around how to build the default configuration. --browserTarget is often a tripping point for a lot of new users, but that is a separate problem to making ng build build for production by default.

One other thought around --prod since this will likely be a significant breaking change for existing education content. When we initially restructure angular.json to make the default configuration build for production, we should add a no-op production configuration. This would allow --configuration production and --prod to still work, even though they won't actually do anything. At that point we can add a deprecation message to --prod explaining the change and advising users to:

  1. If this is an existing project, apply the optional migration and then drop --prod since it won't do anything.
  2. If this is an existing project and they don't want to migrate, switch their command line to --configuration production.
  3. If this is a new project, don't pass --prod, since it already doesn't do anything.

Hopefully this non-breaking warning should catch a lot of content authors and give them an opportunity to update their material before we fully remove --prod. We can remove the no-op production configuration as a later migration.

So with all that I think the list of changes for new projects (ng new) is:

  1. Update angular.json default configuration for build to use production options.
  2. Add a separate development configuration to angular.json builds.
  3. Update angular.json default serve configuration to use --browserTarget app:build:development.
  4. Add npm run watch which executes ng build --watch --configuration development.

And the list of changes for existing projects is:

  1. Add migration to update npm run build to actually execute ng build --configuration production.
    • This should fix services like Heroku which run npm run build and will make them use production builds.
  2. Add migration to add npm run watch which executes ng build --watch.
  3. Add an optional migration for existing projects to make the existing production configuration the default and add a separate development configuration with the existing default options.
    • Should also update npm run build to just use ng build since that will now be prod by default.
    • Should also update npm run watch to use ng build --watch --configuration development.

Once those are ready we then need to:

  1. Deprecate ng * --prod in favor of ng * --configuration production.
    • Clearly document for education content authors what is changing and how they should update their content.
  2. Release all of the above in a major version.
  3. Remove --prod option.
  4. Wait until subsequent major version to release.
earshinov commented 3 years ago

Related: https://github.com/angular/angular-cli/issues/12351

angular-automatic-lock-bot[bot] commented 3 years ago

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.