Skip to content

[Feature] Ability to reference files from assets directory from CSS/Templates OR use relative links without rewriting #5491

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

Closed
1 of 2 tasks
LyraelRayne opened this issue Mar 17, 2017 · 12 comments
Labels
feature Issue that requests a new feature

Comments

@LyraelRayne
Copy link

Bug Report or Feature Request (mark with an x)

  • bug report -> please search issues before submitting
  • feature request

Versions.

Future version

Description of problem being solved

Now that CSS path rewriting works with component CSS there is no way to make plain old CSS relative links. This effectively means that in order to reference assets/ files (or files in other configured directories to be copied to dist/ on build) a root relative path must be used. This works well for standard deployments where the app will be deployed to a single base URL which is known at compile time as angular-cli will rewrite URLs.

Some deployments will either deploy to a base URL unknown at compile time or will deploy to multiple base URLs. For example J2EE applications will have a "context root" which is configurable by the server administrator. Applications built for such environments should use relative URLs only in order to work in this environment.

Desired functionality.

It is desirable that a CSS/LESS/SASS file be able to refer to assets from angular-cli.json's apps.assets (i.e. assets which will be copied to dist/ ) and have those be represented as relative links (which the browser will load from the base href at runtime).

Current workarounds

All of the below assume that the asset is in the assets folder and that it will be referenced by both HTML and CSS (which is what I currently do).

  1. Include all assets in the component, even if they are repeated. Simple to do, harder to maintain.
  2. Use paths relative to the source location (e.g. ../assets/file.png). This will cause webpack to make a second copy of the file in the root of dist/ meaning that dist/assets/file.png and dist/file.png will both exist (and browsers will need to load the same content twice).
  3. Use root relative path. Make separate builds for different context roots with different deploy url for each target so that angular rewrites the paths. This will require N builds (one for each target) which can get tedious. It also doesn't solve the problem for unknown root at compile time.
  4. Use a root relative path with a fake path (e.g. /@assets/file.png) and use postprocessing on the dist/ directory to replace these with relative paths. This adds an extra step to the build and defeats the objective of having angular-cli be a one stop build tool for angular.
  5. Don't use assets in CSS. Find a way to do this in HTML instead. Obviously this isn't going to work for all cases and is somewhat onerous.

Potential solutions (somewhat in order of preference)

  1. Webpack resolver which is aware of the angular-cli.json apps.assets and resolves resources to relative paths accordingly.
  2. Resolver alias which, when used in a path, causes the resolver to transform it to a relative path and do resolution based on the expected dist/ structure. For example relative:assets/file.png or @relative/assets/file.png
  3. Same as the previous, but without resolving resources (may result in broken links)
  4. Flag to globally turn off CSS path resolution (developers will need to know what the path will be of their assets and code accordingly).
@LyraelRayne
Copy link
Author

This is related to the closed issue #4858

@filipesilva filipesilva added freq1: low Only reported by a handful of users who observe it rarely P5 The team acknowledges the request but does not plan to address it, it remains open for discussion severity2: inconvenient feature Issue that requests a new feature type: discussion labels Mar 18, 2017
@filipesilva
Copy link
Contributor

I'm having a hard time understanding the exact conditions where our current options are insufficient.

Can you give me a concrete example? Please include all relevant paths.

@LyraelRayne
Copy link
Author

LyraelRayne commented Mar 19, 2017

OK to boil it down to the most basic concrete example with a single image (we will probably have more than one image in this situation):

Angular app

I have an application which is basically a search engine for locations our clients will be intersted in. A picture of a map pin is used in multiple places.

I will use %pinurl% to refer to a picture of the map pin at 'assets/icons/map-pin.svg' (in the output). The image is located in src/assets/map-pin.svg

  1. src/components/search-results/app-search-results.less - list-style-image: url('%pinurl%'); // This adds the map pin next to each search result.
  2. src/components/location-details/app-location-details.html - As an img with src='%pinurl%') // Added by our designer as a bit of fluff to fill some white space.
  3. src/components/location-details/app-location-details.ts - %pinurl% added as a graphic on an ESRI maps Graphics layer. // This is used to display the search result on the map.

Hosting Environment

The application is hosted in two different sites for two different sets of clients (there will be some non-trivial differences in what is presented to each).

  1. https://www.website.com/merchants/finder
  2. https://www.website.com/customers/finder

A JSP in each storefront will load the web application and set the base URL to /%contextroot%/finder where %contextroot% is 'merchants' or 'customers' depending on which storefront the user is accessing.

The problem

The image is being accessed from multiple locations in the application, some of which don't support resource resolving (AFAIK URIs in HTML templates and TS files cannot be resolved, correct?) and some of which have mandatory resource resolving for relative paths.

  • For TS/HTML templates the only option is to specify the assets folder as an "asset" in .angular-cli.json resulting in the file being copied to dist/assets/map-pin.svg. It may then be referred to using 'assets/map-pin.svg', allowing the browser to resolve it using base href.
  • For CSS files the only option is to refer to an image path on the file-system, resulting in a copy of the image included in dist/map-pin.%hash%.svg and a rewritten CSS referring to "map-pin.%hash%.svg" or to use a root relative URL.

Using file system path results in two copies of the file and requires brittle relative paths.

Using root relative URLs is undesirable as it will make changing the context root difficult in the future (we intend to host multiple angular applications in a similar manner, all of them would need to be updated) and because it doubles (or triples, etc. if we add more context roots) build time.

@LyraelRayne
Copy link
Author

Writing all of that out has made me realise that potentially this could also be resolved by allowing resources to be resolved from HTML templates and TS files. This would allow consistent referencing of resources from HTML, TS and CSS removing the file duplication.

Preferably this would go along with adding the ability to specify such paths relative to .angular-cli.jsons' apps.root, probably using some kind of prefix. For example my src/tsconfig.json defines a "paths" entry with "@me/" mapped to "/" so I don't need to use relative paths in my import declarations, making refactoring easier. Being able to use something like this consistently across CSS, HTML and TS would be helpful for maintainability.

As such the problem can be restated as

  • Resource resolving is inconsistent across the three main types of source file (CSS, HTML, TS) meaning that in some cases resources must be duplicated.
  • Using relative paths to refer to other resources is brittle. Can we have a mechanism to resolve paths relative to the src/ folder that works for the three main types of source file (CSS, HTML and TS).

@filipesilva
Copy link
Contributor

It is true that resources are resolved differently across HTML, CSS and TS. CSS fully resolves and fingerprints resources, while TS and HTML don't. The HTML bit is being tracked in #3415.

I don't think there's any way to truly solve this problem at the moment though.

Regarding relative/absolute paths... that's also a though cookie, because it's really not about src/ but rather where the built app is deployed.

Keeping the issue open for discussion.

@filipesilva filipesilva removed freq1: low Only reported by a handful of users who observe it rarely P5 The team acknowledges the request but does not plan to address it, it remains open for discussion severity2: inconvenient labels May 23, 2017
@filipesilva filipesilva self-assigned this May 23, 2017
@ghost
Copy link

ghost commented Oct 13, 2017

We have a similar problem here. We've converted all links of form /assets/file.png to ../../assets/file.png to solve this for now. I've tried --base-href . and --deploy-url ./, but this didn't help; /assets/file.png still ends up as /assets/file.png (which doesn't exist), while ../../assets/file.png ends up as ./file.xxxxx.png (as expected with fingerprinting).

Maybe the best solution to this problem would be that /assets/file.png should end up as ./assets/file.png when --deploy-url ./ is specified?

(NB: when using --deploy-url ., i.e. without a final slash, ../../assets/file.png ends up as .file.xxxxx.png, which doesn't work. Is that a bug or intended behavior?)

@thienedits
Copy link

thienedits commented Oct 17, 2017

@ffdybuster what was the ng command that you ran? I updated my links to use ../../ but when i ran ng build --prod --no-aot --deploy-url . the images in the assets folder do not have any fingerprint. Only images referenced in CSS files have fingerprinting. Images referenced within the html templates seem to not have any fingerprinting.

@ghost
Copy link

ghost commented Oct 19, 2017

@thienedits: I ended up with ng build -prod --environment prod --base-href ./ --deploy-url

I forgot to mention that I was only looking at images in SCSS, since we don't have images in templates (yet).

@rvalimaki
Copy link

@filipesilva

This is something that was fixed on webback years ago with alias paths. What makes it impossible to have alias paths relative to (compile time) app root with angular-cli, as that was the commonplace with webpack aliases?

Having to use fully relative paths (../../../../../../../assets/img/xy.svg) is a MAJOR PITA. Also paths absolute to web server root (/assets/img/xy.svg) do not work on many virtual test server environments.

Funnily enough, when using absolute paths + run time modified base url in index.html we get assets referred from less files working IFF they are from a lazy loaded module, but NOT when they are from non-lazy-loaded module. That is when app is run in "www.somehost.com/non-root-url/#/" of course.

@mgechev
Copy link
Member

mgechev commented Dec 17, 2018

@LyraelRayne this is out of our scope for now. Please, take a look at ngx-build-plus. I believe it may help you to achieve this. If I'm missing something, and there are a lot of folks who'd want to see this feature in the CLI, please open a new issue.

@mgechev mgechev closed this as completed Dec 17, 2018
@func0der
Copy link

func0der commented Jan 14, 2019

This is the second issue like with this topic that got closed. I am talking about: #3415. In fairness, you close them at the same day, but anyway.
There are a lot of other issues in the other one, that reference that problem.
How many are "a lot of folks who'd want to see this feature" to you?
There seems to be a lot of people already and they seem to be ignored completely.

@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
feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests

7 participants