Skip to content
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

[es-build] Browser directory created in outputPath #26304

Closed
1 task
ssougnez opened this issue Nov 9, 2023 · 58 comments
Closed
1 task

[es-build] Browser directory created in outputPath #26304

ssougnez opened this issue Nov 9, 2023 · 58 comments

Comments

@ssougnez
Copy link

ssougnez commented Nov 9, 2023

Command

build

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

I have an Angular application configure as below:

"outputPath": "../MyNetApplication/wwwroot",

When using webpack build, the compiled files of the Angular application went directly in wwwroot so I could publish my .NET application and it worked directly.

I tried to switch to es-build, however, after the build, the compiled files of the Angular application end up into "../MyNetApplication/wwwroot/browser" which prevents me from publishing the .NET application as this would not work.

It seems weird to me that the outputPath settings of angular.json is only partially honored.
According to me, this settings should be used and not altered during the compilation.

Minimal Reproduction

Just create a new Angular application using angular/cli 17 and run ng build.
The files will be located under dist/ng17/browser.

Exception or Error

No response

Your Environment

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1700.0
@angular-devkit/build-angular   17.0.0
@angular-devkit/core            17.0.0
@angular-devkit/schematics      17.0.0
@angular/cli                    17.0.0
@schematics/angular             17.0.0
rxjs                            7.8.1
typescript                      5.2.2
zone.js                         0.14.2

Anything else relevant?

No response

@alan-agius4
Copy link
Collaborator

alan-agius4 commented Nov 9, 2023

This is by design.

The application builder will output publicly accessible files in the browser directory, ssr files in the server directory and other files such as statistics and licenses information in the root outputPath.

In .NET Core you can configure and change the wwwroot by using .UseWebRoot.

Edit: If this change in outputPath semantics is a major obstacle, consider using browser-esbuild which leverages esbuild/Vite to provide the same build-time improvements as application builder but with identical options to the existing browser builder, meaning outputPath is unchanged.

@ssougnez
Copy link
Author

ssougnez commented Nov 9, 2023

Thanks for the tip.

However, I still find it a bit weird (but maybe I'm alone). If I configure an output path, I expect angular to scrupulously respect it. Especially if I don't use SSR.

What would make more sense to me would be to have a SSR section in the angular.json where I could override the default output path.

This way, people could use the regular outputPath setting to have the same behaviour than with webpack and use a combination of the two if they want to use SSR.

With this approach, everyone would be able to configure his application the way he wants.

Just a suggestion...

@alan-agius4
Copy link
Collaborator

The main reasons behind this change of having a standardise output are;

  • By having always /browser and /server users don’t need to modify their setup when they opt-in or out of SSR.
  • Simplifies integration for hosting and cloud providers as it’s easier to determine which files are/should be accessible in the browser and those that are server only/private.
  • Simpler to explain, as there the outputs are consistent, irrespective of the type of rendering the chosen (CSR, SSG, SSG or hybrid).

Whilst this change does remove some flexibility, we believe that the pros outweigh the cons in the long run.

@olostan
Copy link

olostan commented Nov 9, 2023

I run in same issue. I am using Firebase for hosting and after moving to application builder when I deploy to hosting, I see that both browser and server folders are deployed, so when I navigate to hosted website I have "not found" as index.html is in browser/index.html

I prefer to use SSR.

It is application builder issue or angularfire? Should I reconfigure Angularfire to deploy only browser folder or server folder or application builder can build into single folder that could be deployed to firebase hosting?

Thnx

@alan-agius4
Copy link
Collaborator

alan-agius4 commented Nov 9, 2023

@olostan, if you are using AngulsrFire ng deploy functionality it should determine the right thing out of the box.

Although it does look like they are still working on supporting the new builder firebase/firebase-tools#6480

@olostan
Copy link

olostan commented Nov 9, 2023

@alan-agius4 Thnx! Looks like it is exactly what I am missing.

@alan-agius4 alan-agius4 closed this as not planned Won't fix, can't repro, duplicate, stale Nov 10, 2023
@blogcraft
Copy link

Trying to use esbuild has being absolute hell. I don't use ssr (can't even install node in server) but having this browser directory has introduced so many unnecessary problems.

@sangphu
Copy link

sangphu commented Nov 11, 2023

I am having problem with the browser folder too. I build and output to ../webapp folder in spring boot application. The 'browser' inside ../webapp ruin everything. Developers use Angular to build for many types of applications, not necessarily must use /browser or /server. 'browser' should not be here or at least should have the option not to have it.

@pavelpie
Copy link

Big problem for me too. :( Please consider adding an option as a parameter in angular.json. If the parameter is set to an empty string, the output should be directed to just /dist. If the parameter is set to 'browser', then the output should go to the /dist/browser subfolder.

@emeryao
Copy link

emeryao commented Nov 14, 2023

+1

maybe it's more friendly and a better experience for the developers to make it configurable in addition to the default behavior

@Crefelder
Copy link

Crefelder commented Nov 14, 2023

As a current hack I currently use this. It is strange but works:

Change angular.json:
"options": { "outputPath": "dist",
Add in angular.json:
"architect": { "build": { "configurations": { "production": { "deleteOutputPath": true,

Add in package.json - scripts
"postbuild": "node .\\post-build.js",

Add post-build.js file in root:
const fs = require('fs-extra');
fs.move('dist/browser', 'dist', (err) => { if(err) { return console.error(err); } });

@ChrisCopelandSF
Copy link

+1

Problem here too, I also deploy Angular with a Spring Boot application and all of our pipelines are setup so that Angular builds as part of CI/CD and the output path is set to ../application/src/main/resources/public so that Spring may automatically resolve the view. This change has broken that so we cannot upgrade to Angular 17 without recalibrating all our CI/CD pipelines.

I don't think I even saw this change mentioned in any of the notes, but I may have missed it. If the behaviour isn't going to be looked at/changed/made configurable then maybe it's worth mentioning this more clearly so people upgrading don't blindly cause headaches for themselves.

I agree that there should perhaps be an option for client-side rendering to output in the previous directory structure.

@iqmeta
Copy link

iqmeta commented Nov 14, 2023

I am having problem with the browser folder too. I build and output to ../webapp folder in spring boot application. The 'browser' inside ../webapp ruin everything. Developers use Angular to build for many types of applications, not necessarily must use /browser or /server. 'browser' should not be here or at least should have the option not to have it.

Same here, everything in pipeline is breaking because of forced "BROWSER" folder which does kill of all middleware proxy and base-href stuff set up (eg. relative to ./api json fetch logic) . Please give an option like before to be able to customize the real dist outputPath without forcing devs.
Fine with me to have "browser" as default, but give some extra parameter for real outPath of the browser dist... now we need to hack around like @Crefelder

why not in angular.json:

 "outputPath": {
     browser: "../backend/wwwroot/admin",
     ssr: "../backend/not-public-server-side-rendering",
     whatever: "\\server\share\whatever"
}

it's not so easy if you pipe in 5 SPA apps/uis into one wwwroot with the .UseWebRoot .NET change - which also
kills of default in C# backend mapping.

@dgp1130
Copy link
Collaborator

dgp1130 commented Nov 14, 2023

If the change in output path is a major obstacle for adopting esbuild/Vite, we recommend using the browser-esbuild builder. This leverages esbuild and Vite for improved build times but keeps the same options as the existing browser builder, meaning outputPath is used directly and no browser sub-directory is created. You can read more on our docs.

To be clear, the motivation behind this change for application builder was to align client and server rendering output which makes it much more intuitive when adding SSR to an existing application in particular. This alignment should make deployments easier and more consistent going forward given the stable paths between CSR and SSR builds. That said, we do recognize the churn to get there, which is why we have browser-esbuild as a compatibility layer to solve this problem so everyone can still see the build performance benefits without having to touch your deployment pipeline.

@benbro
Copy link

benbro commented Nov 15, 2023

Building with browser-esbuild show a warning:

The 'browser-esbuild' builder is a compatibility builder which will be removed in a future major version in favor of the 'application' builder.

Will it get removed in the future?

@dgp1130
Copy link
Collaborator

dgp1130 commented Nov 15, 2023

browser-esbuild is stable in v17 and subject to our standard deprecation policy.

@clydin, I wonder we should remove/rephrase that warning? We should definitely prefer application builder, but I'm not sure a warning in a stable builder is the best way of communicating that preference. We could maybe drop "will be removed in a future major version" at minimum just to make it less scary?

@blogcraft
Copy link

blogcraft commented Nov 15, 2023

browser-esbuild keeps throwing errors in Angular 17, it used to work in 16.

10:50:42 [vite] Internal server error: Failed to resolve import "src/environments/environment" from ".angular\vite-root\YourApp\chunk-SHHAMBP3.js". Does the file exist? it just won't work with tsconfig.json "baseUrl": "./",

@Lijo123
Copy link

Lijo123 commented Nov 15, 2023

Upgrading to Angular 17 is now breaking all the spring boot apps. Forcing devs to accommodate a change like this(using the browser folder) rather than making it as an option provides more headaches than solutions. As @Crefelder suggested, now we have to 'hack' our way for a work around. This isn't an ideal solution. Please find a fix to this problem, or at the very least, provide it as an option so it can be configured.

@liliyadub
Copy link

I am running into the same issue when upgrading to Angular 17. This forced “BROWSER” directory has introduced a lot of unnecessary problems. Please consider giving an option to be able to customize/configure the dist outputPath.

@miakimovich
Copy link

+1

As a temporary solution I have to modify node_modules\@angular-devkit\build-angular\src\tools\esbuild\utils.js file, since it's the only way to output files directly to outputPath specified in angular.json.

Please consider adding an option in angular.json.

@dgp1130
Copy link
Collaborator

dgp1130 commented Nov 17, 2023

I'm seeing a lot of feedback in this thread asking Angular CLI to support an option to drop browser/ from the output path and I want to be very clear: This option already exists!

The browser-esbuild builder is that option. It is designed to be fully backwards-compatible with the existing browser builder and does not create a browser/ subdirectory. It includes all the esbuild/Vite performance benefits of application builder. The only thing browser-esbuild can't do is server-side rendering, however I believe SSR builds have always had the browser/ directory, so if you're having trouble with deployments here, you're probably not using SSR.

If your deployment pipeline is giving you trouble with application builder due to the browser/ directory, then please try browser-esbuild instead. See our docs for more info.

@e-oz
Copy link

e-oz commented Nov 19, 2023

The browser-esbuild builder is that option

It is deprecated, it's just a temporary solution, not an "option".

ng build says:

The 'browser-esbuild' builder is a compatibility builder which will be removed in a future major version in favor of the 'application' builder.

@dgp1130
Copy link
Collaborator

dgp1130 commented Nov 20, 2023

That log statement was an artifact of prerelease builds. It's already been removed in #26402 and should be published today in 17.0.2.

Angular docs state this the best I think:

For existing projects, you can opt-in to use the new builder on a per-application basis with two different options. Both options are considered stable and fully supported by the Angular team. The choice of which option to use is a factor of how many changes you will need to make to migrate and what new features you would like to use in the project.

The application builder is generally preferred as it improves server-side rendered (SSR) builds, and makes it easier for client-side rendered projects to adopt SSR in the future. However it requires a little more migration effort, particularly for existing SSR applications. If the application builder is difficult for your project to adopt, browser-esbuild can be an easier solution which gives most of the build performance benefits with fewer breaking changes.

outputPath is one potential place where application builder can be a little tricky for existing apps, and browser-esbuild is the recommended solution for that right now.

@e-oz
Copy link

e-oz commented Nov 20, 2023

thank you for the clarification, @dgp1130 !

@HCenggel
Copy link

I also encountered the same situation as you, which forced me to make some changes to my project

@HCenggel
Copy link

+1

As a temporary solution I have to modify node_modules\@angular-devkit\build-angular\src\tools\esbuild\utils.js file, since it's the only way to output files directly to outputPath specified in angular.json.

Please consider adding an option in angular.json.

helpful to me

@markhiserodt
Copy link

markhiserodt commented Nov 30, 2023

For anyone using Asp.Net 8.0 where you have .client and .server subdirectories in your Solution - go to the {solution}.client.esproj file and add add \browser to the like so:

<PublishAssetsDirectory>$(MSBuildProjectDirectory)\dist\{project}\browser</PublishAssetsDirectory>

Then re-deploy and it should fix it

@e-oz
Copy link

e-oz commented Dec 10, 2023

@changhuixu

This workaround will eventually be forgotten and not supported.

No, see this comment.

@changhuixu
Copy link

@changhuixu

This workaround will eventually be forgotten and not supported.

No, see this comment.

I don't understand your position here. Are you going to support this workaround? In my opinion, the best way to maintain it is to add a flag in Angular CLI or make Angular CLI smarter.
I believe that you are super smart and able to edit angular.json. But I don't trust myself that I could remember it next year after updating Angular to a newer version.

@e-oz , you won't lose anything if Angular CLI becomes better and be able to honor the --output-path value.

@e-oz
Copy link

e-oz commented Dec 10, 2023

@changhuixu right now there is no such option as --output-path in ng new. outputPath, mentioned by the author of this issue, is part of the angular.json file.

There is one issue with ng new, though. Right now it creates angular.json with @angular-devkit/build-angular:application in the builder field, even if SSR was not selected (or --ssr=false was applied). It is, indeed, a wrong behavior. It should set @angular-devkit/build-angular:browser-esbuild there and generate fields, related to this builder (right now it creates field browser).

Because this issue is already closed, I've created another issue to report this problem.

@e-oz
Copy link

e-oz commented Dec 12, 2023

I've created a feature request, you might want to track it:
#26632

@e-oz
Copy link

e-oz commented Dec 15, 2023

And it's implemented: #26675
🎉
Thank you, @alan-agius4 !

@benbro
Copy link

benbro commented Dec 30, 2023

There are already differences between browser-esbuild and application. For example the new "loader" builder option was added to the application builder but not to the browser-esbuild builder.
#26371

@sangphu
Copy link

sangphu commented Dec 31, 2023

You can add the following to your application.yml file in a Spring Boot application to accommodate the new output path:

spring:
  web:
    resources:
      static-locations: classpath:/static/browser

Depending on your IDE, this can be an issue. For example, Eclipse will not pick up changes from VSCode, so you will have to manually refresh the Java project to update the web app every time you build or watch your Angular projects. However, if you build to the "webapp" folder, Eclipse will detect the changes automatically.

@jsuryakt
Copy link

jsuryakt commented Jan 25, 2024

Fixed in angular >=17.1.x

"architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            ...}}}

Keep the "browser" : "" value empty if you don't need the default folder browser being added.

https://angular.io/guide/workspace-config#output-path-configuration

@joelfcoelho
Copy link

Fixed in angular >=17.1.x

"architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            ...}}}

Keep the "browser" : "" value empty if you don't need the default folder name browser being added.

https://angular.io/guide/workspace-config#output-path-configuration

This doesn't seem to work for me on 17.1.1.
'browser' is still flagged as required when building

Error: Schema validation failed with the following errors:
Data path "" must have required property 'browser'.

and also can't be an empty string.

An unhandled exception occurred: `browser` option cannot be an empty string.
See "/tmp/ng-PUeaq4/angular-errors.log" for further details.

@jsuryakt
Copy link

Fixed in angular >=17.1.x

"architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            ...}}}

Keep the "browser" : "" value empty if you don't need the default folder name browser being added.
https://angular.io/guide/workspace-config#output-path-configuration

This doesn't seem to work for me on 17.1.1. 'browser' is still flagged as required when building

Error: Schema validation failed with the following errors:
Data path "" must have required property 'browser'.

and also can't be an empty string.

An unhandled exception occurred: `browser` option cannot be an empty string.
See "/tmp/ng-PUeaq4/angular-errors.log" for further details.

Can you share the angular.json or configuration

@joelfcoelho
Copy link

Fixed in angular >=17.1.x

"architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            ...}}}

Keep the "browser" : "" value empty if you don't need the default folder name browser being added.
https://angular.io/guide/workspace-config#output-path-configuration

This doesn't seem to work for me on 17.1.1. 'browser' is still flagged as required when building

Error: Schema validation failed with the following errors:
Data path "" must have required property 'browser'.

and also can't be an empty string.

An unhandled exception occurred: `browser` option cannot be an empty string.
See "/tmp/ng-PUeaq4/angular-errors.log" for further details.

Can you share the angular.json or configuration

Using @angular-devkit/build-angular:browser-esbuild fixes the issue so I hope this isn't in fact a temporary solution.

But for reference I was using exactly the same options for outputPath you provided.

With

"architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            ...}}}

I get

Error: Schema validation failed with the following errors:
Data path "" must have required property 'browser'.

And with

"architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            "browser":"",
            ...}}}

I get

An unhandled exception occurred: `browser` option cannot be an empty string.
See "/tmp/ng-PUeaq4/angular-errors.log" for further details.

@joelfcoelho
Copy link

If I don't provide "browser":"" outside of outputPath I see the first error I mentioned.
Data path "" must have required property 'browser'.

Like I mentioned though @angular-devkit/build-angular:browser-esbuild works fine for me so no issues there. Just overall a strange decision by the angular team to force @angular-devkit/build-angular:application onto new projects.

@jsuryakt
Copy link

jsuryakt commented Jan 30, 2024

If I don't provide "browser":"" outside of outputPath I see the first error I mentioned.
Data path "" must have required property 'browser'.

Like I mentioned though @angular-devkit/build-angular:browser-esbuild works fine for me so no issues there. Just overall a strange decision by the angular team to force @angular-devkit/build-angular:application onto new projects.

Did you change main to browser?

Maybe related

#26260

https://angular.io/guide/esbuild#using-the-application-builder

Once the builder name has been changed, options within the build target will need to be updated. The following table lists all the browser builder options that will need to be adjusted or removed.

main rename option to browser

@joelfcoelho
Copy link

If I don't provide "browser":"" outside of outputPath I see the first error I mentioned.
Data path "" must have required property 'browser'.
Like I mentioned though @angular-devkit/build-angular:browser-esbuild works fine for me so no issues there. Just overall a strange decision by the angular team to force @angular-devkit/build-angular:application onto new projects.

Did you change main to browser?

Maybe related

#26260

https://angular.io/guide/esbuild#using-the-application-builder

Once the builder name has been changed, options within the build target will need to be updated. The following table lists all the browser builder options that will need to be adjusted or removed.

main rename option to browser

I did but then removed it.
It's supposed to look like this then? Since this config seems to be working

            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            "index": "src/index.html",
            "browser": "src/main.ts",

@jsuryakt
Copy link

Yes it's correct,
You can also run the migration
ng update @angular/cli --name use-application-builder

But maybe have to add browser : "" inside outputPath since it's not included in the migration

@amrud
Copy link

amrud commented Feb 15, 2024

If I don't provide "browser":"" outside of outputPath I see the first error I mentioned.
Data path "" must have required property 'browser'.
Like I mentioned though @angular-devkit/build-angular:browser-esbuild works fine for me so no issues there. Just overall a strange decision by the angular team to force @angular-devkit/build-angular:application onto new projects.

Did you change main to browser?
Maybe related
#26260
https://angular.io/guide/esbuild#using-the-application-builder
Once the builder name has been changed, options within the build target will need to be updated. The following table lists all the browser builder options that will need to be adjusted or removed.

main rename option to browser

I did but then removed it. It's supposed to look like this then? Since this config seems to be working

            "outputPath": {
              "base": "dist/project-name",
              "browser": ""
            },
            "index": "src/index.html",
            "browser": "src/main.ts",

this works for me too. thank you

@abdesssalam

This comment was marked as outdated.

@wasit-shafi
Copy link

as quick fix just move the content under browser one level up, remove the browser directory ... should work

that will obviously work, but we have to do it manually all the time, anyways not this issue has been fixed now

@gultyayev
Copy link
Contributor

There is an issue, however. If I pass the --output-path in the CLI – the browser folder is created. And there is no option to specify for it to be not created.

jeffmccune added a commit to holos-run/holos that referenced this issue Apr 13, 2024
This fixes Angular not being served up correctly.

Note, special configuration in Angular is necessary to get the build
output into the ui/ directory.  Refer to: [Output path configuration][1]
and [browser directory created in outputPath][2].

[1]: https://angular.io/guide/workspace-config#output-path-configuration
[2]: angular/angular-cli#26304
@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators May 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests