angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.76k stars 11.97k forks source link

Images from library don't load, but are included #24695

Closed paddotk closed 1 year ago

paddotk commented 1 year ago

Command

build

Is this a regression?

The previous version in which this bug was not present was

No response

Description

I've been building a component library and am now using these in an application. Some components use images that are added as assets within this library.

When I do a production build and push it to NPM, everything seems to go right, but when using the library in our app, the images don't show. I get a 404 error. Now, this issue is one that many people have been getting for years, so it seems, but never has been resolved. All related tickets have timed out and gotten closed after some time.

Some points worth mentioning:

The issue seems to be related to how the image paths/references are compiled. Because when I include the image in the assets folder of the application that uses the library, it does work. Apparently the library looks for images based on the consuming app's directory rather than the library's root itself. I've spent over two days trying all sorts of configurations and ways to refer to the images, but nothing works. I'm at my wit's end here.

I'm trying to show the images simply in an img tag: <img src="assets/my-picture.svg" />

Technical details

My folder structure is like this:

my-lib
  /package.json
  /projects
    /my-lib // This is the folder that the production build targets
      /package.json
      /src
        /assets
        ...
      ...
  /src //this is the local test application which is not part of the build/library
    /app
    ...    
  ...

I build it using the command ng build vitas-toolkit --configuration production

// ng-package.json
"assets": [
    {
      "glob": "**/*",
      "input": "src/assets",
      "output": "/assets"
    },
    "./src/_lib/styles"
  ],

Minimal Reproduction

See above

Exception or Error

No response

Your Environment

@angular-devkit/architect       0.1402.10
@angular-devkit/build-angular   14.2.10
@angular-devkit/core            14.2.10
@angular-devkit/schematics      14.0.7
@angular/cli                    14.0.7
@schematics/angular             14.0.7
ng-packagr                      14.1.0
rxjs                            7.5.5
typescript                      4.7.4
webpack                         5.74.0

Anything else relevant?

No response

alan-agius4 commented 1 year ago

Looks like you are missing a vital step. as you also need to configure the assets option of the application builder to copy the the asset from the library distributable to the application output.

paddotk commented 1 year ago

@alan-agius4 You mean this right?

"assets": [
    {
      "glob": "**/*",
      "input": "src/assets",
      "output": "/assets"
    }
]

This does copy the assets to the build. They are included, yet the library seems to look for a file in the consuming app's assets folder rather than its own.

alan-agius4 commented 1 year ago

Yes I did mean that.

It is intended that assets in libraries needs to be copied by consumer application. In general, for libraries it's best to use assets which are embedded in CSS.

See: https://github.com/ng-packagr/ng-packagr/blob/main/docs/embed-assets-css.md

paddotk commented 1 year ago

@alan-agius4 I don't understand. The consuming applications need to have their own images placed in their own assets folder? That defeats the whole purpose of including assets in libraries. Or making a library in the first place, in some cases (like font-awesome).

I'll have to see if I can make it work with css background-images, but this is a pretty devious workaround if any. I want to ask you guys please to reconsider this design choice (if I understood you correctly), because it's a big limitation that shouldn't have to be.

PS I did read about the css solution, but I did not see anything in the docs about not being to use images otherwise.

alan-agius4 commented 1 year ago

Hi,

it's not a typically use-case to reference images in the component of a library. In this case this is needed it's likely to be a small icon which can be automatically embedded in CSS.

The library you mentioned @fortawesome/angular-fontawesome is in fact built using the Angular CLI and is a wrapper for Angular on top of the framework agnostic version @fortawesome/free-solid-svg-icons, where the icons are embedded in JS. This is because the concept of assets in a library is very different from that of an application. This is not soley to Angular.

Another example is bootstrap which users need to configure the path to where the fonts are located: https://github.com/twbs/bootstrap-sass/blob/6b0ca5025c64f2e5696c8719cfce7148c78d0a50/assets/stylesheets/bootstrap/_variables.scss#L84

paddotk commented 1 year ago

Ok, thank you. I did just try it with css though, but I got the same issue there; locally it works fine, in a consuming app it doesn't load (it isn't parsed into base64). I build with the command ng build my-lib --configuration production.

alan-agius4 commented 1 year ago

Ok, thank you. I did just try it with css though, but I got the same issue there; locally it works fine, in a consuming app it doesn't load (it isn't parsed into base64). I build with the command ng build my-lib --configuration production.

Please provide a reproduction.

paddotk commented 1 year ago

I don't think I can create or run a build in a codepen, but you can try our library npm install vitas-toolkit@0.0.59. Simply use the component <VtLoader></VtLoader> somewhere in your app. This is supposed to display two images.

This is what the installed library's looks like in node_modules image

And this is what I see when used in an application image

ng build vitas-toolkit --configuration production is used to build.

The component's template

<div class="vitas-kit vt-loader">
    <span class="--vt-img-1></span>
        <span class="--vt-img-2></span>
</div>

The component's relevant css

 .vitas-kit .--vt-img-1 {
   background-image: url('/assets/vitas-pijltje.svg');
/* Also tried other things like `assets/` as base path */
}
 .vitas-kit .--vt-img-2 {
   background-image: url('/assets/vitas-balkje.svg');
}
alan-agius4 commented 1 year ago

Resources in CSS need to be referenced using a relative path from the stylesheet. In this case also, it's redundant to have them as assets.

paddotk commented 1 year ago

Ah, damn. That was the one attempt that I missed; indeed that works. The documentation here mentions an absolute path though, so that threw me off

background: url('logo.png');

Thanks for helping me through this! Perhaps a good idea to edit that documentation page ;)

angular-automatic-lock-bot[bot] commented 1 year ago

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.