Skip to content

Proposal: Auto add (providers, directives, pipes, styles, styleUrls) when adding 3rd party libs, etc. #96

Closed

Description

@NathanWalker

Discussion on AngularAir today regarding 3rd party libraries (https://plus.google.com/events/c7m79d5o04nom5eednk5ecqtebk) brought up an interesting thought.
See also: angular/angular#5503

If 3rd party libs all adhered to a certain naming convention and style when exporting necessary services, directives, pipes, etc., it would be incredibly helpful if this CLI could auto-annotate the src code files with the necessary directives, providers, pipes, etc.

Consider the following scenario:

  1. User wants to use ng2-image-lazy-load (https://github.com/NathanWalker/ng2-image-lazy-load)
  2. Since it followed certain conventions, IMAGELAZYLOAD_PROVIDERS, the CLI might provide an additional helpful aid (command can be whatever, just using add-lib for example):
ng add-lib ng2-image-lazy-load 

It would proceed to run npm install ng2-image-lazy-load, then prompt with a couple questions:

$ Would you like this provider as part of the bootstrap? (y/n)

If "y":

$ Please provide the path to the src file which bootstraps your app:
$ src/bootstrap.ts

It would add the import statements and append the aptly named [lib_prefix]_PROVIDERS in the user's app bootstrap.
If the lib contained no constants with PROVIDERS in the name, it would modify nothing.

If "n":

$ Please provide the path of the component you would like the providers added to:
$ src/components/main.component.ts

It would add the import statements and append the libraries aptly named PROVIDERS in the viewProviders of the component.

Similar scenarios would apply for DIRECTIVES, PIPES, etc.

If this were possible, every 3rd party lib could suggest using the CLI as the first option to install, followed by manual npm install.

/cc @jvandemo, @gdi2290, @valorkin, @ocombe, @jeffwhelpley, @PascalPrecht, @mgechev, @ludohenin, @robwormald

Activity

  1. changed the title [-]Auto add PROVIDERS, DIRECTIVES, PIPES when adding 3rd party libs, etc.[/-] [+]Proposal: Auto add PROVIDERS, DIRECTIVES, PIPES when adding 3rd party libs, etc.[/+] on Dec 9, 2015
  2. IgorMinar commented on Dec 10, 2015

    @IgorMinar
    Contributor

    the proposal sounds reasonable to me (with some tweaks). I think that we should prefer local import over global import, so I'd reorder the options.

    Would you like to create a test package(s) in npm that we can experiment with?

  3. NathanWalker commented on Dec 10, 2015

    @NathanWalker
    ContributorAuthor

    adjective: adlib; adverb: adlib
    _musical context_:

    Jazz musicians may adlib during a performance, meaning they are free to vary tempo and instrumentation.

    _programmers context_:

    When using any framework to create an application, there will come a time when a developer must adlib to complete the applications specifications.

    Might be a fun command: adlib

  4. robwormald commented on Dec 10, 2015

    @robwormald
    Contributor

    i think perhaps a simple solution for this would be something along the lines of

    //myPluginRoot.ts
    import {MyPluginServiceA, MyPluginServiceB} from './services';
    import {MyDirectiveA, MyDirectiveB} from './directives';
    import {MyPipeA, MyPipeB} from './pipes';
    
    //export the named stuff for granular usage
    export * from './services'
    export * from './directives'
    export * from './pipes'
    
    //use es6 default syntax to export the "plugin"
    export default {
      providers: [MyPluginServiceA, MyPluginServiceB],
      directives: [MyDirectiveA, MyDirectiveB],
      pipes: [MyPipeA, MyPipeB]
    }

    users and tooling are then easily able to do :

    //naming is irrelevant here
    import myPlugin from 'myPlugin'
    
    //now its consistent:
    myPlugin.directives
    myPlugin.services
    myPlugin.pipes

    and this is easily done with templating, as the actual name of the export is "default" - no weird lookups necessary and no NAMING_CONVENTIONS to force / invent.

    see http://plnkr.co/edit/Yi1e3ifiX0gSqd8Qs2h4?p=preview - i added a little plugin registration helper too, which @IgorMinar will probably yell at me about.

  5. NathanWalker commented on Dec 10, 2015

    @NathanWalker
    ContributorAuthor

    That's the best solution I've heard yet @robwormald. Very clean and simple.

    I could pull your plunk (the gist of it anyway) into a repo tomorrow or
    Friday and publish it so it could be experimented with in this setup.

  6. ludohenin commented on Dec 10, 2015

    @ludohenin

    @robwormald I like it very much

  7. ocombe commented on Dec 10, 2015

    @ocombe
    Contributor

    +1 on this solution @robwormald :)

  8. jvandemo commented on Dec 10, 2015

    @jvandemo

    @robwormald — Brilliant, love your proposal! 👍

  9. robwormald commented on Dec 10, 2015

    @robwormald
    Contributor

    Go for it! (maybe not the helper thing...)

    On Dec 10, 2015, at 12:16 AM, Nathan Walker notifications@github.com wrote:

    That's the best solution I've heard yet Rob. Very clean and simple.

    I could pull your plunk (the gist of it anyway) into a repo tomorrow or
    Friday and publish it so it could be experimented with in this setup.

    On Thu, Dec 10, 2015 at 12:03 AM Rob Wormald notifications@github.com
    wrote:

    i think perhaps a simple solution for this would be something along the
    lines of

    //myPluginRoot.tsimport {MyPluginServiceA, MyPluginServiceB} from './services';import {MyDirectiveA, MyDirectiveB} from './directives';import {MyPipeA, MyPipeB} from './pipes';
    //export the named stuff for granular usageexport * from './services'export * from './directives'export * from './pipes'
    //use es6 default syntax to export the "plugin"export default {
    providers: [MyPluginServiceA, MyPluginServiceB],
    directives: [MyDirectiveA, MyDirectiveB],
    pipes: [MyPipeA, MyPipeB]
    }

    users and tooling are then easily able to do :

    //naming is irrelevant hereimport myPlugin from 'myPlugin'
    //now its consistent:
    myPlugin.directives
    myPlugin.services
    myPlugin.pipes

    and this is easily done with templating, as the actual name of the export
    is "default" - no weird lookups necessary and no NAMING_CONVENTIONS to
    force / invent.

    see http://plnkr.co/edit/Yi1e3ifiX0gSqd8Qs2h4?p=preview - i added a
    little plugin registration helper too, which @IgorMinar
    https://github.com/IgorMinar will probably yell at me about.

    —
    Reply to this email directly or view it on GitHub
    #96 (comment).

    —
    Reply to this email directly or view it on GitHub #96 (comment).

  10. valorkin commented on Dec 10, 2015

    @valorkin
    Contributor

    Will not this push to use MVC like folder separation?
    Like for angular 1 really was really popular controllers\directives\templates separation
    which became really fast unusable in large apps
    that all moved to components separation all related to component in one folder
    a bit later nested components and common folders appeared as a practice

    +1 to @robwormald that we should not push/invent name conventions

    PS: I am never using generators, and not allow to, guys should understand what and why they are doing :)

  11. robwormald commented on Dec 10, 2015

    @robwormald
    Contributor

    this is for third party packages (like yours) which will presumably ship via NPM, and thus the structure of the package is mostly irrelevant to the user. The structure internal to the module / plugin is entirely up to you, that was just a quick and dirty demo.

  12. jvandemo commented on Dec 10, 2015

    @jvandemo

    @valorkin — I think using a folder structure with directives, services and pipes makes sense for libraries (the Angular team also does this internally in the Angular source code) although the library author could decide to use another structure.

    The structure for an actual application (not a library) would be component driven though, if that makes sense.

  13. valorkin commented on Dec 10, 2015

    @valorkin
    Contributor

    just said my IMHO
    Angular team actually uses components structure (but call it modules) and MVC separation inside of it
    https://github.com/angular/angular/tree/master/modules/angular2/src

  14. jvandemo commented on Dec 10, 2015

    @jvandemo

    @valorkin — I think the Angular repository (in its current form) is hard to compare to a third party library.

    However, if we peek inside one of the modules, then we can see a similar structure e.g.: https://github.com/angular/angular/tree/master/modules/angular2/src/common

    I think such a structure is probably closer to what most (smaller) libraries will contain.

    If you have a larger library that contains modules then it definitely makes sense to create a module folder structure. Ultimately the library author should decide.

    Although one could argue that it would be better to split into different repositories than in different modules.

    Would be great if there is an Angular 2 ecosystem with a lot of very small libraries (as in node).

    What are your thoughts on splitting into different repositories? Thanks!

  15. valorkin commented on Dec 10, 2015

    @valorkin
    Contributor

    Taking in account user option to to require and bundle only require part of libs
    it is awesome opportunity to minimize js size and bootstrap time
    (as a consequence of reduced amount of js to be parsed by VM)

    modules are optional
    splitting in components like this: https://github.com/angular/angular/tree/master/modules/angular2/src
    seems to me as proven concept, IMHO

  16. 21 remaining items

  17. NathanWalker commented on Dec 19, 2015

    @NathanWalker
    ContributorAuthor

    Turns out a really cool guy @superchris tried out the lib today on his own brave accord and in the process helped reveal a couple things, of which I just fixed in 1.0.7. (it was previously installing its own dependencies in node_modules (within the lib's folder) after installing).

    His project shows an example implementation of the ng2-cli-test-lib:
    https://github.com/superchris/angular-cli-test

    One thing of interest is that the ComponentMetadata:
    providers, viewProviders, directives, and pipes all support nested arrays.

    However styles and styleUrls do not.
    I'm sure this is for good reason but maybe it should be consistent for all metadata.

    Given this, when integrating the library in, I had to do this:
    https://github.com/superchris/angular-cli-test/blob/master/src/app/angular-cli-test.ts#L10
    Which is not 1/1 consistent with the others. Not sure if this should be reported as an issue or if this difference is warranted.

    Lastly, until the cli implements some of the features aforementioned, styleUrls will be a more manual process when installing/using 3rd party libs, so I did not implement that in @superchris awesome test project.

  18. PatrickJS commented on Dec 21, 2015

    @PatrickJS
    Contributor

    we should be using spread operator whenever possible since it also clearly shows which ones are collections and which ones aren't (as if all caps wasn't enough)

    import {FORM_DIRECTIVES} from 'angular2/common';
    import {APP_PROVIDERS} from '../app-providers';
    import {MyDirective} from './my-directive';
    import {APP_STYLES, APP_THEME_STYLES} from '../app-styles';
    @Component({
      selector: 'home',
      providers: [
        ...APP_PROVIDERS
      ],
      directives: [
        ...FORM_DIRECTIVES,
        MyDirective
      ],
      styles: [
        ...APP_THEME_STYLES,
        `
          .main {
            background: gray;
          }
        `
      ],
      template: `
        <my-directive></my-directive>
      `
    })
    export class App {}

    for styles: we can use the spread operator for now. I made a pull-request to spread all the collections angular/angular#6049

  19. NathanWalker commented on Dec 23, 2015

    @NathanWalker
    ContributorAuthor

    @gdi2290 +1 nice :)

  20. jkuri commented on Jan 7, 2016

    @jkuri
    Contributor

    I got something working. See #135
    Based on @NathanWalker test lib https://github.com/NathanWalker/ng2-cli-test-lib

  21. jkuri commented on Jan 9, 2016

    @jkuri
    Contributor

    Is it possible to add 3rd party library without adding mappings to system config?

  22. NathanWalker commented on Jan 10, 2016

    @NathanWalker
    ContributorAuthor

    With @jkuri 's help, we were able to modify ng2-cli-test-lib to be compatible with SystemJS specifically, and therefore angular cli.
    This makes the lib work with the incredible effort @jkuri put forth here: #135

  23. jkuri commented on Jan 10, 2016

    @jkuri
    Contributor

    Please check out my last commit. Any suggestions/tests/fixes/comments are very welcome. If someone interested to check it out, here is usage example

    git clone https://github.com/jkuri/angular-cli -b 3rd-party-libs
    cd angular-cli
    npm i
    [sudo] npm link
    

    then create new project using ng new somewhere

    ng new project
    cd project
    npm link angular-cli
    ng libs install ng2-cli-test-lib
    ng libs uninstall ng2-cli-test-lib
    

    I tested out and the project builds properly, with injecting with custom or automatic injection or uninstalling the lib afterwards (cleans properly).

    If this will hopefully be accepted by maintainers we can define how the library must be created to be compatible with ng libs command and rework the code afterwards. Now ng2-cli-test-lib library uses systemjs-builder to generate SystemJS compatible format and the script looks like this.
    If we decided to also support other loaders than system, to facilitate the work of developers of the libs, this script can easily be tweaked to export other formats.

  24. robwormald commented on Jan 12, 2016

    @robwormald
    Contributor

    The more I think about this idea, the less I like it, at least in regards to automatic code generation and injection and the like. I think it's an overreach for what the CLI should do.

  25. NathanWalker commented on Jan 12, 2016

    @NathanWalker
    ContributorAuthor

    I can certainly understand that.

    To me, cli tools in general are merely a toolbox containing commands that
    make tasks easier. Some use more commands all the time whereas to others
    maybe never.

    The goal here was to simply offer an additional helpful aid to those that
    find it helpful.

    Personally, this is the type of tool in the toolbox that I would use for
    rapid prototyping where a boss comes to me and says, "I'd like to see
    what's possible for this idea by tomorrow." I may not use it all the time
    but there are times where I would appreciate it.

    I think most advanced users (pros) always have a sour taste for tools that
    offer to sugar up an otherwise easy task for them. Git GUI apps vs. command
    line: perfect example of this.

    In the end, it's just about helpful options to me. Ya like honey on your
    toast? Great. And for you, grape jam? Fantastic.

    On Tue, Jan 12, 2016 at 1:44 AM Rob Wormald notifications@github.com
    wrote:

    The more I think about this idea, the less I like it, at least in regards
    to automatic code generation and injection and the like. I think it's an
    overreach for what the CLI should do.

    —
    Reply to this email directly or view it on GitHub
    #96 (comment).

  26. jkuri commented on Jan 12, 2016

    @jkuri
    Contributor

    @robwormald you can simply answer "no" to the first question after installing a lib with that command/task.

  27. NathanWalker commented on Feb 4, 2016

    @NathanWalker
    ContributorAuthor

    This has been merged. Documentation is here: #173

  28. smtx-AliNafees commented on Jul 15, 2017

    @smtx-AliNafees

    I am using it with angular4 and getting error with ng serve that 'ERROR in ImageLazyLoadModule is not an NgModule'?
    any suggestion please?

  29. angular-automatic-lock-bot commented on Sep 7, 2019

    @angular-automatic-lock-bot

    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.

  30. locked and limited conversation to collaborators on Sep 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions