Angular-cli: How to instruct Angular CLI to NOT inline images less than 10Kb in size

Created on 20 Dec 2017  路  14Comments  路  Source: angular/angular-cli

Versions

Angular CLI: 1.6.0
Node: 8.9.0
OS: darwin x64
Angular: 5.0.0
... compiler, compiler-cli, core, service-worker

Repro steps

  • Make sure your app has assets, e.g. images of size less than 10Kb referenced from your css
  • run ng build --target=production

Observed behavior

Assets, e.g. images of size less than 10kb are inlined in CSS

Desired behavior


When building an Angular app with Angular CLI, resources in CSS, e.g. svg images, less than 10kb in size will be inlined.

This sounds like a good concept from the performance point of view, however, it violates very strict Content Security Policies in my app, which I 'm not allowed to change.

data: Allows data: URIs to be used as a content source. This is insecure; an attacker can also inject arbitrary data: URIs. Use this sparingly and definitely not for scripts.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/img-src

I want an option to NOT to inline any assets, e.g. images, in CSS due to strict CSP requirements.

Mention any other details that might be useful (optional)

feature

Most helpful comment

ok, 10KB sounds like fine right? until you have 100 of them
a 1MB+ styles file is not a good thing
on a localhost or fast connection, you won't notice it,
but not all connections are created equally
we should at least be able to disable this all together
in .angular-cli.json or so

All 14 comments

For extremely strict environments, an option is to eject the configuration and customize the webpack configuration for the applications target environment.

Out of curiosity, that warning may sound alarming but is there any research that suggests a data URI as an image source represents a security issue? As opposed to scripts which are a completely different matter (which that warning is pointing towards).

Also, note that unsafe-inline will be needed for style-src and currently unsafe-eval may also be needed for script-src (this can be eliminated by removing reflect polyfills, running in AOT mode, and removing the webpack node global shim from an ejected configuration).

@clydin Well, I submitted a request to verify the possibility to add img-src data:; rule in the CSP headers. Though, it's almost Christmas, may take a while before I get a response.

From my understanding the issue is in the fact that img-src can only define schema, e.g. img-src data:; but cannot define a specific resource type, e.g. img-src data:image/svg+xml;, so all resource types will be allowed...

Meanwhile, I created a PR to add --inline-asset-max-size build flag https://github.com/angular/angular-cli/pull/8967

ok, 10KB sounds like fine right? until you have 100 of them
a 1MB+ styles file is not a good thing
on a localhost or fast connection, you won't notice it,
but not all connections are created equally
we should at least be able to disable this all together
in .angular-cli.json or so

Got response from the security. It appears adding img-src data:; to the CSP headers is not a big security issue.
This issue is not relevant t me anymore, though, it would be good to have options.

Created a dumb example to show how dangerous this can be to bundle sizes.

This generates 850kb styles.css with ng build -prod:
https://github.com/intellix/cli-inline-svg/blob/master/src/scss/_coloured.scss

I'm thinking it could happen easily within a team of developers when someone has a folder full of language flag SVGs and then someone decides to add some extra background colours.

It's definitely unexpected and I think even this example generating 20kb is pretty bad:

.visa-1 { background: url('assets/visa.svg'), transparent }
.visa-2 { background: transparent, url('assets/visa.svg') }

I'm thinking if there's more than 1x reference to the same URL, it should skip inlining it but then you're still screwed in the language-flag scenario.

With it auto inlining we don't get a choice whether an image is lazily loaded or not either

This has become a big problem for the project I am on. We need the background image to be customizable per deployment. The ability to swap images in a folder seemed like a good solution at the time.
background: url('#{$custom-images-folder}background-logo.svg') center

I'm pretty disappointed to see that #8967 was closed. There is a comment on that PR stating that the next major release would "more easily support this feature", but it doesn't sound like it is being considered for that major release.

Does anyone have a work-around suggestion?

In case someone else needs a solution suggestion...

We're using gradle to build our OSGi project. The build process copies Angular's dist folder to a location that bndtools can easily bundle.

I added a filter to our gradle script copy task to put the path/filename back.

filter { 
    String line -> 
    line.replaceAll(/background:url\("data:image.*?background-logo.*?"\)/, "background:url(\"custom/assets/images/background-logo.svg\")")
}

One more reason to allow modify this option: devserver recompiles the app on < 10kb resource change, but the old version of resource is served. Process must be terminated and restarted again if working with small files.

There is a tool that can help with situations like this => patch-package, you only need to change this value to 0 and problem solved.

Please make this option configurable and do not let developers guess if resources will be inlined and if they need to be preloaded in advance, or not. It's not intuitive now.

Yeah, that will be great to disable images inlining.

Due to http 2.0 this is unnecessary

Inlining has been completely removed in the upcoming 7.0. As indicated, considering caching and with the advent of HTTP/2.0 inlining is no longer needed.

@clydin i have been using custom elements to package a angular project into just a single javascript file which i could easily include in a 3rd party website without additional dependencies. the JS included all resources because the referenced images were inlined. without inlining, is there any suggestion how i could bundle everything up into 1 js file, or do I have to do some post processing myself?

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