Angular-cli: --deploy-url will have no effect on assets paths

Created on 8 Feb 2017  Â·  44Comments  Â·  Source: angular/angular-cli

Please provide us with the following information:

Versions.

Please run ng --version. If there's nothing outputted, please run in a Terminal: node --version and paste the result here:
@angular/cli: 1.0.0-beta.30 node: 7.5.0 os: win32 x64 @angular/common: 2.4.6 @angular/compiler: 2.4.6 @angular/core: 2.4.6 @angular/forms: 2.4.6 @angular/http: 2.4.6 @angular/platform-browser: 2.4.6 @angular/platform-browser-dynamic: 2.4.6 @angular/router: 3.4.6 @angular/cli: 1.0.0-beta.30 @angular/compiler-cli: 2.4.6

Repro steps.

Was this an app that wasn't created using the CLI? What change did you do on your code? etc.

  • create app with the cli
  • use img src="assets/logo.png" in a template
  • ng build -d mysubfolder -bh mysubfolder
    copy the content of the dist to "htdocs/mysubfolder" on any webserver or use
    app.use('/mysubfolder', express.static(path.join(__dirname, angularDist))); on a node server.

The log given by the failure.

Normally this include a stack trace and some more information.

404 on all assets because it will ignore base href or deploy url and just use GET /assets/logo.png

Mention any other details that might be useful.

1 (urgent) bufix

Most helpful comment

@filipesilva can you tell me what the reasoning was to only process asset urls in css, and not in the html templates?

All 44 comments

Hello! I am running into the same issues.

I am deploying an app written by someone else. Components have hard-coded paths like /assets/img/etc (note the leading slash compared to the OP); the main application files (*.bundle.js and sourcemaps) end up in the root of the dist directory. This is okay for frontend development (using ng serve, /index.html can load /index.bundle.js and /assets/img/etc), but for the actual deployment I would ideally have everything under URLs looking like /static/app/ and /static/assets/ for example.

Ideally, we would have set up different paths and directories from the start if we had thought about the server considerations. Trying to minimize changes at this stage, I found the one-line documentation for base-href and deploy-url not very enlightening, but PR #2276 seemed like deploy-url was intended to solve my issue. I am still experimenting in CI to see if that works for the main js files, but this ticket tells me it won’t help with the assets URLs.

I had this problem too. All my resources are served on a subdomain. Using the deployUrl option solved the issue for the scripts/styles being loaded from the subdomain inside the index.html. This guaranteed me to not worry about base href so that my routing will work properly, it remains as default /. Regarding other resources like images, try loading them from your styles using the background-image property. As the styles loads from the subdomain, it loads the necessary resources from the subdomain too, including fonts, etc.
Now I have an issue with the favicon as it is an asset, the compiler does not put the deployUrl in the href attribute and I have to put it manually.

Facing the same issue here, I've got some CSS like this:

label.custom-radio-default-label {
  margin: 0;
  clear: none;
  cursor: pointer;
  background: url(/assets/images/custom-radio-normal.svg) left center no-repeat;
  background-size: 20px;
  font-size: 16px;
  font-weight: normal;
}

and building with ng build --deploy-url https://test.com doesn't seem to have any effect on the output.

Largely fixed by https://github.com/angular/angular-cli/pull/4803.

The ng build --deploy-url https://test.com (with http) scenario isn't catered for currently though.

@filipesilva #5254 Here is a related issue that I've posted 3 days ago. Hope you will fix this soon.

@filipesilva Does #4803 rewrite paths for assets that are images or javascript files, or only CSS files?

@es-lab thank you, I will track the http bug in your issue instead. I'm closing this one then.

@merwok it rewrite paths only for assets in url() inside CSS. Those are the only ones that need path rewriting afaik.

The example in the original message is an image. The source code contains img src="assets/logo.png" (in my case, src="/assets/logo.png") but the files will be served from /static/assets/.

@merwok if you have url('/assets/logo.png') in your CSS, and use --deploy-url=static/, the CLI should build that path to url('/static/assets/logo.png'). Mind you that images under a certain size are just inlined.

Make sure you're using the latest RC though.

Thank you for the reply! I’ll check with my team when we can upgrade and adapt our CI to benefit from the new behaviour.

@filipesilva It affects urls stated in CSS files, but it doesn't those which are directly stated in markup like <img src="assets/logo.png">. So if I build using --deploy-url=static/ it won't be
<img src="/static/assets/logo.png">

@milankr we do not process HTML, so that is expected behaviour.

Ah! If only index.html is changed and not the other HTML files, I’ll have to keep my sed workaround.

Next project, we’ll get the paths right from day one!

@filipesilva can you tell me what the reasoning was to only process asset urls in css, and not in the html templates?

@filipesilva What is the strategy using src paths with a project using --deploy-url? @merwok comment points out this issue:

"The example in the original message is an image. The source code contains img src="assets/logo.png" (in my case, src="/assets/logo.png") but the files will be served from /static/assets/."

The request for the image resource will 404.

Is there any workaround to make this work for <img src="[...]" />?
(Or any other path in the html files)

@bergben the only workaround that now reading the thread is to use Javascript binding so you configure the base path in your environment config files 👎

@filipesilva any updates on this? I need HTML processing as well

FWIW, I lived with renaming assets to static/assets and doing a mass search-and-replace. Source paths now match deployed paths.

I need to put Index.html in root directory i.e. /dist folder and all script files in dist/scripts directory, can anyone please guide how do I achieve this? So that when I deploy it on server my index file resides in root of my domain (mydomain/index.html) and all scripts in scripts directory (e.g. mydomain/scripts/**.js)

@tomasklingen it was attempted a couple of times but at the time we couldn't find a safe approach for it, especially since you can compose urls in html using component variables. So any change there was very likely to break some projects, which is a breaking change and thus outside of 1.x.

@filipesilva Can we get some sort of reserved string/variable/token that you can search in HTML and TS to replace all occurences?

@filipesilva ,

For those of us who are not in production yet. Should we think about some workaround or we can expect some fix in next releases(even not in 1.x)?

When you deploy to prod, extract of the index.html, just this!

I think there are two workarounds: either move your source files and do a mass search and replace so that the source paths match the deployed paths (what I mentioned in a previous comment), or use the ng eject command to get access to the raw webpack config and get out of ng cli.

I have a work around in the mean time.

I put the deploy path in my environment.ts files.

Then in the components that I want to refer to files in the assets folder, I set href/src to "{{deploypath}}/assets/...". You will have to create a deploypath component variable and assign the environment.deployPath in the constructor of the component.

@zsmorgan21 We do the same thing. When we deploy, we have a script that updates our package version and replace the value in our environment file. It works so far.

I'll reference this StackOverflow post https://stackoverflow.com/questions/47885451

As I've ran into the same issue, deployUrl manages the path in the index.html, but not across the application's assets/ files. The workaround is to have a CI/CD post-build script which pretty much does in-place replace of assets path in the built files using sed.

The proper CDN support for any client-side apps framework is quite important; I'm not deep into Angular/CLI to know all the ins and outs to propose a solution, but it is something we're definitely running into when planning CDN deployments.

Generally, setting the base-href is a cleaner option. It not only handles initial scripts, but also lazy scripts, processed resources, and most importantly the application's assets. The use of Angular's APP_BASE_HREF (documentation) in combination can provide a full solution for CDN use cases such as described here.

@clydin,

base-ref alone wont solve the issue with assets. However, I do think setting and referencing Angular's APP_BASE_HREF is the better option than using angular CLI's environment variables. You can set it like @clydin mentioned above. You can reference it like so...

https://stackoverflow.com/questions/39287444/angular2-how-to-get-app-base-href-programatically

Could you elaborate on why using the --base-href option will not solve the asset issue?

All relative fetches made by the browser will be prefixed by the provided base href. This would include all relative asset URLs within the application. This is also why it is generally a cleaner solution as opposed to the --deploy-url option which requires the supplied URL to be embedded throughout the application to function. The APP_BASE_HREF token (which is used as the Angular router base path) would generally be set / in this scenario; as the default value is actually the base href of index.html.

When you refer to base-href, are you referring to the command line
parameter or the base tag and href attribute? I think there is some
confusion there. Your initial post was missing the "--" from base-href.

Zachary S. Morgan
Hampden-Sydney College
Class of '14

On Tue, Jan 23, 2018 at 3:19 PM, clydin notifications@github.com wrote:

Could you elaborate on why using the --base-href option will not solve
the asset issue?

All relative fetches made by the browser will be prefixed by the provided
base href. This would include all relative asset URLs within the
application. This is also why it is generally a cleaner solution as opposed
to the --deploy-url option which requires the supplied URL to be embedded
throughout the application to function. The APP_BASE_HREF token (which is
used as the Angular router base path) would generally be set / in this
scenario; as the default value is actually the base href of index.html.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angular-cli/issues/4517#issuecomment-359917240,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AGtzhNWpbDTiBrLJ0YGFdOXHLsMPv-ydks5tNj7TgaJpZM4L6mvx
.

Reading all this, and it still doesn't explain how to have assets mapped to a CDN, even with using this APP_BASE_HREF

This is the build command, which maps base-href to /subpath/ and deployUrl to CDN:

ng build --prod --aot --base-href "/subpath/" --deployUrl="//cdn.example.com/subpath/"

So, the app is served off of a webserver host's subpath (so, Angular routing must work with this subpath, as the link I shared explains), but angular files are stored on the CDN. With the above build command, built JS/CSS files are correctly referenced with CDN URL in the index.html, but then, inside the app, all the assets should be referenced from the CDN as well, which is not the case.

What is needed is the way to --deployUrl be applied to all the /assets/ during the build. With this APP_BASE_URL they'd be referenced with the value of the --base-href parameter, if I understand it correctly (correct me if I'm wrong; but that was the conclusion in the comments of the StackOverflow question - not supported).

Thank you

The purpose of the --base-href option is to set the value of the base element's href attribute within index.html. So either would be relevant to the discussion.

@zappan Something similar to the following command:

ng build --prod --base-href="//cdn.example.com/subpath/"

with APP_BASE_HREF set to /subpath/ in the entry module should work. Relative URL usage within the app is critical as the browser will only apply the HTML base href to relative URLs.
As an aside, --aot is enabled by default with --prod.

Can some one throw light on this, how to achieve context path other than / for my application. I had been reading whole night for this issue but could not find a way

@zappan did it ever work for you? I tried without any luck and am stuck with it. Could you please assist?

@ga-kumar wrote a script using sed to replace paths that I run after the build.
Haven't tried what clydin suggested (or maybe I have and it didn't work, can't remember any more)

thanks @zappan , I also ended up doing same.. Clydin's suggestion didn't work for me either or not sure if I understood correctly.. anyway.. thanks again..

Having the same issue.
My first attempt was to use the --base-href but this will affect also the angular router so it is not a solution.

For now I am going to place a deployUrl to every src of html images.

@albanx Use --base-href for the applications assets and the APP_BASE_HREF token to control the Angular router.

Hi, @clydin I have encountered the similar problem, Please help.
angular-cli version:

Angular CLI: 6.2.5
Node: 8.12.0
OS: darwin x64

My deploy situation:

My site have to be deployed on server A because of domain, so I put index.html ( generated file in
the dist folder) on server A. And I want to deploy all the static files on another CDN server B, and I put all the dist folder on Server B as a folder named like 111. I tried build my site with following ways:

way 1: Failed with some assets link in html did not converted to CDN path, so assets link in html breaks

ng build --prod --base-href /111/ --deploy-url https://B.com/111/  

way 2: all the Angular router and http api both breaks, since all api and router are added with the base-href

ng build --prod --base-href https://B.com/111/

I have already set the APP_BASE_HREF token in src/app/app.module.ts:

@NgModule({
 ...
  bootstrap: [AppComponent],
  providers: [
    {provide: APP_BASE_HREF, useValue: '/'}
  ]
})

Please help and let me know if you want more information. Thanks!

Assets in ts file is has no impact on deployUrl. I was trying dynamic configuration https://christianlydemann.com/implementing-dynamic-environments-in-angular-for-avoiding-one-build-per-environment/

public init() {
    return from(
        fetch('assets/app-config.json').then(function(response) {
          return response.json();
        })
      ).pipe(
        map((config) => {
        window.config = config;
        return 
      })).toPromise();
  }

image

Can anyone help me how deployUrl can be used to update references ts file?

Still we don't have any solution for the same issue. Don't know why this ticket is closed.

I am building my application on cnd server and serving my index.html file from other domain which is my public domain.

The build command for same is like ng build --prod --aot --output-hashing none --deploy-url=https://ng.xyzcdn.in/. If I am running my application on https://ng.xyzcdn.in/, static content are are coming from same cdn domain are fine. But when I am using my main/public domain to serve application, the static content path is relative to my main/public domain.

My requirement will be fixed only when static content would served via deploy url.

Note: All the chucks file are serving correctly via deploy url path on main/public domain. Only facing issue with static contents which are deployed inside "svg" and "assets" folders.

Application is not working fine when I am trying to hard code cdn path of "assets" in angular.json file.

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._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

donaldallen picture donaldallen  Â·  3Comments

ericel picture ericel  Â·  3Comments

jmurphzyo picture jmurphzyo  Â·  3Comments

hartjo picture hartjo  Â·  3Comments

rajjejosefsson picture rajjejosefsson  Â·  3Comments