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

--deploy-url will have no effect on assets paths #4517

Closed
ghost opened this issue Feb 8, 2017 · 44 comments
Closed

--deploy-url will have no effect on assets paths #4517

ghost opened this issue Feb 8, 2017 · 44 comments
Assignees
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix

Comments

@ghost
Copy link

ghost commented Feb 8, 2017

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.

@merwok
Copy link

merwok commented Feb 8, 2017

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.

@es-lab
Copy link

es-lab commented Feb 21, 2017

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.

@victormejia
Copy link

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.

@filipesilva
Copy link
Contributor

Largely fixed by #4803.

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

@filipesilva filipesilva self-assigned this Mar 9, 2017
@filipesilva filipesilva added type: bug/fix P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful and removed type: enhancement labels Mar 9, 2017
@es-lab
Copy link

es-lab commented Mar 9, 2017

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

@merwok
Copy link

merwok commented Mar 9, 2017

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

@filipesilva
Copy link
Contributor

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

@merwok
Copy link

merwok commented Mar 10, 2017

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

@filipesilva
Copy link
Contributor

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

@merwok
Copy link

merwok commented Mar 12, 2017

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.

@milankr
Copy link

milankr commented Mar 13, 2017

@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">

@filipesilva
Copy link
Contributor

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

@merwok
Copy link

merwok commented Mar 14, 2017

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!

@tomasklingen
Copy link

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

@macrivello
Copy link

macrivello commented Apr 21, 2017

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

@bergben
Copy link

bergben commented Jun 10, 2017

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

@yordis
Copy link

yordis commented Jun 13, 2017

@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 👎

@yordis
Copy link

yordis commented Jun 13, 2017

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

@merwok
Copy link

merwok commented Jun 13, 2017

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

@naveedahmed1
Copy link

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)

@filipesilva
Copy link
Contributor

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

@MaximeMorin
Copy link

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

@Nodarii
Copy link

Nodarii commented Sep 20, 2017

@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)?

@pagimaxx
Copy link

pagimaxx commented Oct 7, 2017

When you deploy to prod, extract <base "/"> of the index.html, just this!

@merwok
Copy link

merwok commented Oct 9, 2017

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.

@sir-captainmorgan21
Copy link

sir-captainmorgan21 commented Oct 11, 2017

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.

@MaximeMorin
Copy link

MaximeMorin commented Oct 11, 2017

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

@zappan
Copy link

zappan commented Jan 23, 2018

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.

@clydin
Copy link
Member

clydin commented Jan 23, 2018

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.

@sir-captainmorgan21
Copy link

@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

@clydin
Copy link
Member

clydin commented Jan 23, 2018

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.

@sir-captainmorgan21
Copy link

sir-captainmorgan21 commented Jan 23, 2018 via email

@zappan
Copy link

zappan commented Jan 23, 2018

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

@clydin
Copy link
Member

clydin commented Jan 23, 2018

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.

@rajjaiswalsaumya
Copy link

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

@ga-kumar
Copy link

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

@zappan
Copy link

zappan commented Sep 11, 2018

@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)

@ga-kumar
Copy link

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

@albanx
Copy link

albanx commented Nov 4, 2018

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.

@clydin
Copy link
Member

clydin commented Nov 5, 2018

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

@brantxiong
Copy link

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!

@rijine
Copy link

rijine commented Mar 19, 2019

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?

@pravesh364
Copy link

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.

@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 Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix
Projects
None yet
Development

No branches or pull requests