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

CSS images with relative path not included in production build #4806

Closed
arntj opened this issue Feb 18, 2017 · 31 comments · Fixed by #4803
Closed

CSS images with relative path not included in production build #4806

arntj opened this issue Feb 18, 2017 · 31 comments · Fixed by #4803
Assignees
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful

Comments

@arntj
Copy link

arntj commented Feb 18, 2017

Please provide us with the following information:

OS?

Windows 10

Versions.

1.0.0-beta.32.3

Repro steps.

  1. Create new app with ng new.
  2. Add an image anywhere outside the app directory, e.g. in the assets directory.
  3. Reference this image from the app.component.css, using a relative path.
    Example: background-image: url(../assets/some_image.png)
  4. Do the following: ng build --prod.
  5. Verify that the image is not copied along with the CSS in the build output, meaning the image reference is now broken.

The log given by the failure.

N/A

Mention any other details that might be useful.

The image is correctly copied if doing ng build without the --prod switch.


Thanks! We'll be in touch soon.

@filipesilva
Copy link
Contributor

Heya @arntj, can you do me a favor and verify the image really is broken within you app? For images smaller than 10kb we actually inline them, which is why it wouldn't be copied over.

@arntj
Copy link
Author

arntj commented Feb 18, 2017

Yes, I loaded it in an HTTP server and verified that the image was broken in the web browser. The image I tested it with is 60 kb.

@arntj
Copy link
Author

arntj commented Feb 18, 2017

The production output CSS links to a hashed image file that doesn't exist in the output dir.

@filipesilva
Copy link
Contributor

I can verify this happens:

  • touch ./src/assets/img.svg (using svg here because it always loads as a file regardless of size)
  • add h1 { background-image: url(../assets/img.svg) } to ./src/app/app.component.css
  • ng build
  • verify ./dist/img.svg exists and it's referenced in ./dist/main.bundle.js
  • ng build --prod
  • verify ./dist/img.[hash].svg does NOT exist but it's referenced in ./dist/main.[hash].bundle.js

Will investigate.

@filipesilva filipesilva self-assigned this Feb 18, 2017
@filipesilva filipesilva added command: build P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful labels Feb 18, 2017
@filipesilva
Copy link
Contributor

This seems to be related with AoT.

Workarounds for now:

  • use ng build --prod --no-aot
  • use an absolute path for the image (starting with /)

@JimiC
Copy link
Contributor

JimiC commented Feb 18, 2017

In my case, cause I use base-href './' the workaround is as follows:

  • use ng build --prod --no-aot --base-href ./
  • use a relative path to the images folder (i.e. ../assets/images/img.*)

@b4youleap
Copy link

This is a little different but maybe related?
OS?
Windows 10
Versions.
1.0.0-beta.32.3
Upgrading project from beta-31 - my issue showing up in dev when running ng serve

Under my src directory I have a theme file: ui-framework-theme.css It is referenced in my index.html as <link href="ui-framework-theme.css" rel="stylesheet" />
(apologies if this is bad practice - I'm learning)
Was getting a 404 error on the file until I changed it to
<link href="/src/ui-framework-theme.css" rel="stylesheet" />

filipesilva added a commit to filipesilva/angular-cli that referenced this issue Feb 20, 2017
Fixing component css in angular#4667 uncovered errors in CSS url processing.

This PR correctly composes absolute urls when using `--base-href` and/or `--deploy-url`.

It also fixes asset output on `--aot` mode.

Fix angular#4778
Fix angular#4782
Fix angular#4806
@janwo
Copy link

janwo commented Feb 20, 2017

I referenced my images in html like <img src="../../someimage.svg"> and webpack is also not emitting this file.

filipesilva added a commit that referenced this issue Feb 20, 2017
Fixing component css in #4667 uncovered errors in CSS url processing.

This PR correctly composes absolute urls when using `--base-href` and/or `--deploy-url`.

It also fixes asset output on `--aot` mode.

Fix #4778
Fix #4782
Fix #4806
@janwo
Copy link

janwo commented Feb 20, 2017

@filipesilva Does this affect images in html as well?

@filipesilva
Copy link
Contributor

@janwo no, images in html aren't processed at all.

@kylecordes
Copy link

@filipesilva It would be nice to have the same processing of images referred to from CSS versus HTML. Ideally with the typical webpack processing for both, alternatively disabling asset URL processing for both would be more consistent and easier to understand and explain than the current feature set. Is a move toward one of those things on the roadmap?

@filipesilva
Copy link
Contributor

@kylecordes it would be nice if we could have HTML processing on part with CSS processing but I haven't looked into it much.

I had a short look at https://github.com/webpack-contrib/html-loader but wasn't too sure of the interactions between image urls and interpolated properties.

If someone knows how safe it is, I'd be happy to add it in.

@kylecordes
Copy link

So if I understand right, the obstacle is: we need to be confident that HTMLLoader (or a fork thereof) applies its usual processing to plain URLs, but leaves any attribute values that look like an Angular expression, unchanged.

Here are its test cases:

https://github.com/webpack-contrib/html-loader/blob/master/test/loaderTest.js

It appears as though there is already a way to pass a config which tells it to ignore expressions that match a pattern:

https://github.com/webpack-contrib/html-loader/blob/master/test/loaderTest.js#L68

The example used in the test case tells it to leave expressions that include "{{" untouched. I wonder if that bit of config would be enough for what CLI needs?

@clydin
Copy link
Member

clydin commented Feb 20, 2017

The HTML templates are inherently dynamic, as a result static analysis to determine asset usage is exceedingly error prone. Combine that will the vast multitude of methods to reference assets (and their varying foms) and attempts at HTML template static analysis becomes far more trouble than it's worth.

@kylecordes
Copy link

@clydin Certainly there will always be cases where a template can be made to referenced an asset that could not be determined statically. But I have applications that have highly numerous assets that are always mentioned statically from HTML templates. Handling those the same way as assets mentioned from CSS would be a great improvement to ergonomics.

@kylecordes
Copy link

Also related, this person suggests a set of HtmlLoader settings to work with Angular templates:

webpack-contrib/html-loader#67 (comment)

@martinmcwhorter
Copy link

Rather than --no-aot shouldn't -oh bundles be a sufficient workaround with absolute image paths?

@filipesilva
Copy link
Contributor

@kylecordes I had a preliminary look at html-loader and it seems to be ok with Angular templates overall.

I couldn't find how to rewrite absolute urls without processing them though. I had to do that for absolute styles in this bit of code:
https://github.com/angular/angular-cli/blob/master/packages/@angular/cli/models/webpack-configs/styles.ts#L50-L60

Do you know of a similar way to do it with html? The root query parameter won't work since afterwards it will process the url.

@martinmcwhorter I don't see how that would work. Can you elaborate?

@clydin
Copy link
Member

clydin commented Feb 21, 2017

Something to note from an app design standpoint is that outside actual page content (which will be overwhelming dynamic anyway), css background images and icon fonts (SVG in particular for custom design elements) are a far more flexible alternative to static HTML img elements.

@filipesilva
Copy link
Contributor

Yeah it wouldn't be a big problem in image urls on html would always need to be absolute.

@martinmcwhorter
Copy link

@filipesilva -- I experienced the issue where the images filenames in CSS (actually SCSS if that matters) were being hashed, but the actual image file names were not being hashed on build.

To work around this issue I used absolute file names in CSS, example /assets/logo.png and built with the -oh=bundles flag, rather than --no-aot, to prevent webpack from adding the hash to the path in CSS.

This workaround works for me, though I don't know the internals of Angular-CLI or the webpack config that is used -- so I understand I may be mistaken on the specifics.

@filipesilva
Copy link
Contributor

@martinmcwhorter I see now, yeah. Your workaround would work, since you're taking the resource extraction out of the equation. You shouldn't have to do that though... next release it should be ok.

@martinmcwhorter
Copy link

martinmcwhorter commented Feb 22, 2017 via email

asnowwolf pushed a commit to asnowwolf/angular-cli that referenced this issue Apr 12, 2017
Fixing component css in angular#4667 uncovered errors in CSS url processing.

This PR correctly composes absolute urls when using `--base-href` and/or `--deploy-url`.

It also fixes asset output on `--aot` mode.

Fix angular#4778
Fix angular#4782
Fix angular#4806
9034725985 added a commit to betternode/fakenews that referenced this issue May 15, 2017
angular/angular-cli#4806

i have to do --no-aot and then deploy to firebase for the image to appear
if I don't, then the image does not appear

I think this is an issue with cli --aot as described in

angular/angular-cli#4806

Signed-off-by: Kushal Hada (developer) <[email protected]>
@wtho
Copy link

wtho commented Jun 5, 2018

So is there a way to configure the cli to end up with relative paths in the CSS, e.g. url('assets/...')?

@demiahmed
Copy link

Hey guys! I'm new to angular and I'm facing the same problem in my app where the local version works perfectly great whereas the github deployment breaks all the URLs for images. My images are placed in src/assets/xyz.jpg directory and I have tried changing the base href as well as my image url and still the image appears to be broken.

I'm using angular 6. Would be really thankful if I get my issue sorted out.

Thanks in advance.

@yousefashraf
Copy link

Hey guys! I'm new to angular and I'm facing the same problem in my app where the local version works perfectly great whereas the github deployment breaks all the URLs for images. My images are placed in src/assets/xyz.jpg directory and I have tried changing the base href as well as my image url and still the image appears to be broken.

I'm using angular 6. Would be really thankful if I get my issue sorted out.

Thanks in advance.

i have this issue too

@frostbytedata
Copy link

frostbytedata commented Oct 29, 2018

No news on this issue? I am seeing the same thing on Angular 6. Building on Unix seems to be broken, but strangely, I never have the issue when building on Windows.

Oddly enough, when I reference assets in this fashion:

url("/assets/myimage.jpg")

instead of

url("../../../assets/myimage.jpg")

it works fine locally, and during my unix production build.

@benwelker
Copy link

Similar to @frostbytedata but I'm on Angular 7 and my url still differed slightly to get it working.

url("assets/myimage.png")

Having that preceding forward slash before assets was breaking for me, along with the other method of the url("../../assets/myimage.png")

@nhhockeyplayer
Copy link

Im having to hardwire with an appRootPrefix in environment.ts in order to serve up internationalized language files beneath my assets folder and various sporadic app images off the template or from within the component fed to the template.

export const environment = {
    appRootPrefix: '/api',
}

and then

    ngOnInit() {
        this.image.nativeElement.setAttribute(
            'src',
            `${environment.appRootPrefix}/assets/logo-pp.png`
        )
    }

or

        this.image.nativeElement.setAttribute(
            'src',
            `${environment.appRootPrefix}/assets/avatar.png`
        )

or

export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(
        http,
        `${environment.appRootPrefix}/assets/i18n/`,
        '.json'
    )
}

not good for production


C:\apache-tomcat-9.0.14\api>ng --version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / ? \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 7.2.3
Node: 8.12.0
OS: win32 x64
Angular: 7.2.2
... animations, cdk, common, compiler, compiler-cli, core, forms
... http, language-service, material, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.12.3
@angular-devkit/build-angular     0.12.3
@angular-devkit/build-optimizer   0.12.3
@angular-devkit/build-webpack     0.12.3
@angular-devkit/core              7.2.3
@angular-devkit/schematics        7.2.3
@angular/cli                      7.2.3
@angular/flex-layout              7.0.0-beta.19
@ngtools/webpack                  7.2.3
@schematics/angular               7.2.3
@schematics/update                0.12.3
rxjs                              6.3.3
typescript                        3.2.4
webpack                           4.28.4


C:\apache-tomcat-9.0.14\api>

@akgupta002
Copy link

No news on this issue? I am seeing the same thing on Angular 6. Building on Unix seems to be broken, but strangely, I never have the issue when building on Windows.

Oddly enough, when I reference assets in this fashion:

url("/assets/myimage.jpg")

instead of

url("../../../assets/myimage.jpg")

it works fine locally, and during my unix production build.

It worked in my case too. After removing ellipsis, angular7 found this asset in no time. Amazing! Thank you @frostbytedata for sharing this.

@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
Projects
None yet
Development

Successfully merging a pull request may close this issue.