MurhafSousli / ngx-sharebuttons

Angular Share Buttons ☂
https://ngx-sharebuttons.netlify.app/
MIT License
518 stars 124 forks source link

v14 (and v15) now requires icon dependencies #673

Closed janpapenbrock closed 1 month ago

janpapenbrock commented 1 month ago

Hey there, thanks for your work on this project!

The issue

I've just upgraded from v13 to v14 and am now seeing compiler errors:

./node_modules/ngx-sharebuttons/fesm2022/ngx-sharebuttons-icons.mjs:2:0-65 - Error: Module not found: Error: Can't resolve '@fortawesome/angular-fontawesome' in '/my-project/node_modules/ngx-sharebuttons/fesm2022'

./node_modules/ngx-sharebuttons/fesm2022/ngx-sharebuttons-icons.mjs:3:0-218 - Error: Module not found: Error: Can't resolve '@fortawesome/free-brands-svg-icons' in '/my-project/node_modules/ngx-sharebuttons/fesm2022'

./node_modules/ngx-sharebuttons/fesm2022/ngx-sharebuttons-icons.mjs:4:0-133 - Error: Module not found: Error: Can't resolve '@fortawesome/free-solid-svg-icons' in '/my-project/node_modules/ngx-sharebuttons/fesm2022'

I switched from SharedModule to SharedButtonDirective. I bring my own icons instead of using any of the provided icons.

Reproduction

I have reproduced the error with v15, too, on a fresh Angular v18 installation. I've pushed this as a repository here: https://github.com/janpapenbrock/ngx-sharebuttons-angular-18.

I basically followed this Wiki page (first usage example without icons): https://github.com/MurhafSousli/ngx-sharebuttons/wiki/Share-Button-Directive

This is the component: https://github.com/janpapenbrock/ngx-sharebuttons-angular-18/blob/main/src/app/app.component.ts

Error output

✘ [ERROR] Could not resolve "@fortawesome/angular-fontawesome"

    node_modules/ngx-sharebuttons/fesm2022/ngx-sharebuttons-icons.mjs:2:30:
      2 │ import { FaIconLibrary } from '@fortawesome/angular-fontawesome';
        ╵                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  You can mark the path "@fortawesome/angular-fontawesome" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@fortawesome/free-brands-svg-icons"

    node_modules/ngx-sharebuttons/fesm2022/ngx-sharebuttons-icons.mjs:3:181:
      3 │ ...okMessenger, faTelegramPlane, faMix, faXing, faLine } from '@fortawesome/free-brands-svg-icons';
        ╵                                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  You can mark the path "@fortawesome/free-brands-svg-icons" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

✘ [ERROR] Could not resolve "@fortawesome/free-solid-svg-icons"

    node_modules/ngx-sharebuttons/fesm2022/ngx-sharebuttons-icons.mjs:4:97:
      4 │ ...faPrint, faExclamation, faLink, faEllipsisH, faMinus } from '@fortawesome/free-solid-svg-icons';
        ╵                                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  You can mark the path "@fortawesome/free-solid-svg-icons" as external to exclude it from the
  bundle, which will remove this error and leave the unresolved path in the bundle.

Context

I don't see why the icons module should even be compiled, as I'm not using the icons at all.

Also wondering whether there maybe are (peer?) dependencies missing in this file: https://github.com/MurhafSousli/ngx-sharebuttons/blob/master/projects/ngx-sharebuttons/package.json?

Environment

MurhafSousli commented 1 month ago

I realized that in the new version, the share directive package we are using only the interface IconProp from the core package @fortawesome/fontawesome-svg-core, We can resolve this issue by replace the interface with any or add the core icons package it as dependency, this way it will be installed automatically with npm i ngx-sharebuttons but no code will be used from FontAwesome, only an interface.

But the problem here is that the icons package is being bundled even when not being used, I opened an issue to learn what is wrong https://github.com/ng-packagr/ng-packagr/issues/2860

janpapenbrock commented 1 month ago

Looked into it a bit more, and it seems it is this import chain that leads to the packages being required:

  1. SharedButtonDirective imports ShareService in https://github.com/MurhafSousli/ngx-sharebuttons/blob/master/projects/ngx-sharebuttons/src/lib/share-button.directive.ts#L19
  2. ShareService imports SHARE_ICONS from ngx-sharebuttons/icons in https://github.com/MurhafSousli/ngx-sharebuttons/blob/master/projects/ngx-sharebuttons/src/lib/share.service.ts#L7C30-L7C52
  3. SHARE_ICONS imports all three @fortawesome/... dependencies in https://github.com/MurhafSousli/ngx-sharebuttons/blob/master/projects/ngx-sharebuttons/icons/src/share-icons.ts

I'm not familiar with injection tokens, but maybe defining that token in its own file would help, to split up the imports?

At least @angular/components defines some injection tokens in their own files, examples:

MurhafSousli commented 1 month ago

Whoops, good catch! I didn't notice that import line.

MurhafSousli commented 1 month ago

We are still using IconProp interface from FontAwesome.

https://github.com/MurhafSousli/ngx-sharebuttons/blob/30c35371ea1b6d7e0ad67844ab9d62f0963ab396/projects/ngx-sharebuttons/src/lib/share-button.directive.ts#L17

I added it as a dependency

https://github.com/MurhafSousli/ngx-sharebuttons/blob/916105cba32594d76e0e60c68777b34dc58bce48/projects/ngx-sharebuttons/package.json#L1-L14

This mean the package will be installed behind the seen without the need to install it manually, is that fine?

I just publish a beta version 15.0.1-beta.0 try it out and tell me if that works well with you.

janpapenbrock commented 1 month ago

Thanks! I just tried it, works :+1:

--

I believe though that the dependency is not really necessary for just importing that type information in the directive, as it will not be included in the compilation anyways, so I believe it would not fail even if I did not have that dependency installed.

You could also write this which would make it more explicit, I belive:

import type { IconProp } from '@fortawesome/fontawesome-svg-core';

Looking at the compiled directive seems to confirm this:

import { Directive, Input, Output, HostListener, inject, signal, effect, computed, input, EventEmitter, ElementRef } from '@angular/core';
import { ShareService } from './share.service';
import { SHARE_BUTTONS_CONFIG, } from './share.models';
import { DEFAULT_OPTIONS, SHARE_BUTTONS } from './share.defaults';
import { SHARE_BUTTONS_PROP } from './custom-share-button-provider';
import * as i0 from "@angular/core";
export class ShareButtonDirective {

The import from the external package does not show up. So I guess just splitting out the injection token would do the trick here.

But regardless of which solution you choose, great to see this working with the next release :)

MurhafSousli commented 1 month ago

@janpapenbrock I used the type imports and removed the dependency, could you try 15.0.1 and see if that works.

janpapenbrock commented 2 weeks ago

Works, thanks a lot!