Angular-cli: Feature request: Adding a lib from npm should not be a 5-step process.

Created on 21 May 2016  路  18Comments  路  Source: angular/angular-cli

Please provide us with the following information:

  1. OS? Windows 7, 8 or 10. Linux (which distribution). Mac OSX (Yosemite? El Capitan?)

Mac OS X (El Capitan)

  1. Versions. Please run ng --version. If there's nothing outputted, please
    run in a Terminal:
    node --version
    And paste the result here.

angular-cli: 1.0.0-beta.5
node: 6.0.0
os: darwin x64

(node 6.0.0)

  1. Repro steps. Was this an app that wasn't created using the CLI? What change did you
    do on your code? etc.

This is more of a feature request than a bug. However taking a look at this page in the docs https://github.com/angular/angular-cli/wiki/3rd-party-libs begs a question: why is integrating a lib from npm this complex?

In webpack it's just npm install --save foo (and maybe typings install --save foo). I understand that SystemJS requires a lot more config, which is one reason I have avoided it in the past.

However if we must go with SystemJS it would be nice to provide a wrapper command at least (e.g. ng install --save foo); adding 3rd-party deps is a common operation which other toolchains make fairly simple.

Most helpful comment

Yeah the 3rd party lib scenario isn't very friendly. As far as contrasting it with webpack, that discussion is underway on https://github.com/angular/angular-cli/issues/909.

Regarding the boilerplate... a lot of config can't be derived, and even if it could not all installed npm packages should be added to SystemJS.

I'm leaving this issue open for people to pitch in suggestions on how the current 3rd party libs journey could be improved, but please let's keep the system vs webpack vs whatever out of it.

All 18 comments

What's the reason all of that boilerplate couldn't be automatically derived from package.json?

I mean,

  1. vendorNpmFiles: ['moment/moment.js'] in angular-cli-build.js
  2. 'moment': 'vendor/moment/moment.js' in system-config.ts

Can both be easily extracted and generated dinamically from package.json at build time.

One advantage of SystemJS over Webpack is the ability to dynamically load modules in the browser, in dev mode.

Unfortunately async module loading is a feature I typically avoid. The large number of HTTP requests it produces makes it unsuitable for production; and the existence of source maps means that you can have a decent dev mode experience even with a single JS bundle created using commonJS at build-time.

So the main feature of SystemJS (or async module loaders in general) is something that I don't find very useful; this makes its extra layers of config on top of package.json even more troublesome.

That said I'm sure you have good reasons for doing it this way. Therefore something to automate the addition of npm modules would be appreciated if at all possible.

@SethDavenport webpack supports async module loading (not that you would need it for dev env), additionally it has webpack-dev-server that is a 2 line setup that has multiple varieties of sourcemaps available (depending on how fast you want your builds to run), and support incremental HMR, and watch.

@TheLarkInn oh, I know :) I use webpack most of the time ... huge fan.

Yeah the 3rd party lib scenario isn't very friendly. As far as contrasting it with webpack, that discussion is underway on https://github.com/angular/angular-cli/issues/909.

Regarding the boilerplate... a lot of config can't be derived, and even if it could not all installed npm packages should be added to SystemJS.

I'm leaving this issue open for people to pitch in suggestions on how the current 3rd party libs journey could be improved, but please let's keep the system vs webpack vs whatever out of it.

Regarding the boilerplate... a lot of config can't be derived, and even if it could not all installed npm packages should be added to SystemJS.

Why not? What do we lose/gain? Trimming the final build?

Couldn't we solve this by adding a simple --yes-I-want-this-to-be-added-to-systemjs flag when installing with npm i in tandem with a "postinstall" script?

Trimming the final build is a concern, yes. The tree shaking might take care of it automatically though.

A postinstall script could maybe work, although I'm not sure of the technical details of making that work. For instance, how to get the installed package names, how to auto determine the module format.

Also it would require a custom flag on install or something similar, which is already deviating from how users would expect npm install to work.

@filipesilva

Also it would require a custom flag on install or something similar, which is already deviating from how users would expect npm install to work.

Understood. But the only alternatives I can think of are actually worse: manually editing files or an entirely new CLI tool/command. Have you ever considered integrating jspm?

@nfantone we did at a time, but it suffered from a similar problem: you'd need to install packages using something other than npm. It'd configure systemjs for you, which was a plus, but wouldn't configure CLI stuff and there was no clear integration with ember-cli.

So at the time we didn't pursue it more. That is, of course, something that might change.

Is dynamic module loading even a hard requirement? What about old school <script> tags? I'd go that way every time if it meant to keep using the tools we all know.

We want to make it a seamless process for people to use. Therefore when somone does ng install some-lib we need to do the following:

  • fetch module from npm via npm install

    • optionally install types from @types/some-lib

  • if there is a way to determine what kind of module it is (we need to tell said builder how to resolve it in the build process)
  • import the module into vendors file.
  • import the typings for the file.

Maybes:

  • if can't determine what kind of module the some-lib is, need to warn/notify the user (if really needed).

@TheLarkInn I'd like to refer you to https://github.com/angular/angular-cli/issues/845#issuecomment-223435495.

  • Points one to three are already solved by jspm - or, at least, it tries to do so.
  • Types are installed by typings.

Remaining things are CLI-related. We should find a way to get rid or work around those. Why do need _yet another_ tool?

@nfantone Not debating that. I'm just leaving some points that should be covered however/whenever it is implemented.

+1

For packages that have their own dependencies, this is more like 100x step process for including third-party processes. Been trying to include @horizon/client for a couple of hours now and still haven't managed it.

For that third-party lib alone, this is what I have so far to try and load all of it's individual dependencies and I'm still getting 404 errors from SystemJS:

/** Map relative paths to URLs. */
const map: any = {
  '@horizon/client': 'vendor/@horizon/client/dist',
  'ws': 'vendor/engine.io-client/lib',
  'babel-runtime': 'vendor/babel-runtime',
  'snake-case': 'vendor/snake-case',
  'sentence-case': 'vendor/sentence-case',
  'lower-case': 'vendor/lower-case',
  'engine.io-client': 'vendor/engine.io-client/lib',
  'engine.io-parser': 'vendor/engine.io-parser/lib',
  'isomorphic-fetch': 'vendor/isomorphic-fetch',
  'core-js': 'vendor/core-js',
};

/** User packages configuration. */
const packages: any = {
  '@horizon/client': { main: 'horizon-dev' },
  'ws': { main: 'index' },
  'babel-runtime': { main: 'index' },
  'snake-case': { main: 'snake-case' },
  'sentence-case': { main: 'sentence-case' },
  'lower-case': { main: 'lower-case' },
  'engine.io-client': { main: 'index' },
  'engine.io-parser': { main: 'index' },
  'isomorphic-fetch': { main: 'index' },
  'core-js': { main: 'index' },
};

I refresh the page, and get another 5 more 404 errors. This sort of thing is exactly what JSPM is trying to solve.
You want to include one third-party library and not have to configure where to find all of it's own dependencies from.

After telling SystemJS where to find Horizon's dependencies, I'm now getting 404s that need mapping for some more: component-emitter, debug, indexof, parseuri, parsejson, parsegs, utf8, after
Adding 1 library can be anything between 2 minutes -> 5hrs - I want to cry :'(

I want to cry :'(

We feel you, brother.

Fixed in #1455.

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