Angular-cli: Importing adhoc 3rd party lib fail

Created on 19 May 2016  路  26Comments  路  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?)

angular-cli: 1.0.0-beta.4
node: 5.7.0
os: darwin x64

  1. Versions. Please run ng --version. If there's nothing outputted, please
    run in a Terminal:
    node --version
    And paste the result here.
  2. Repro steps. Was this an app that wasn't created using the CLI? What change did you
    do on your code? etc.

App created with ng-cli

1 - npm install phoenix_js --save

2 - Update system-config.ts

const map: any = {
"phoenix_js": "vendor/phoenix_js/dist/phoenix.js"
};

const packages: any = {
"phoenix_js": {
"format": "cjs",
"defaultExtension": "js",
"main": "index",
}

3 - Update angular-cli-build.js

module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
...
'phoenix_js/dist/phoenix.js',
]
});
};

4 - Update main.ts

import { Socket } from 'phoenix_js'

  1. The log given by the failure. Normally this include a stack trace and some
    more information.

Error: Typescript found the following errors:
./tmp/broccoli_type_script_compiler-in
main.ts (6, 24): Cannot find module 'phoenix_js'.
at BroccoliTypeScriptCompiler._doIncrementalBuild (./node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:115:19)
at BroccoliTypeScriptCompiler.build (./node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:43:10)

...

  1. Mention any other details that might be useful.

Thanks! We'll be in touch soon.

I did see the post about integrating 3rdparty libs but only includes moment and material -> No help for adhoc thirdparty lib inclusions.

Stuck! Thanks for your help.

RFC / discussion / question

Most helpful comment

@SergeySolonko Clearly, that wiki page didn't help one bit. Was the first thing I read. Wouldn't be writing a comment here, otherwise.

For the record, after hours of pointlessly staring at my screen in bewilderment, I managed to make ng2-charts work. Here's a summary of what I did:

Configure URLs and packages

Edit system-config.ts and have it declare ng2-charts and _all its dependencies_. Manually. The only way of knowing which dependencies are those, AFAIK, is running your application and keep track of all 404 you'll get. Or dig out each package.json for a list. Once you do that, repeat the step for the dependencies of the dependencies.

After some trial and error, I figured out ng2-charts depends on color-name, color-convert and chart.js. In turn, _chart.js_ depends on chartjs-color, chartjs-color-string and moment.

So, you need to follow all steps on the wiki guide for _each one of those_.

Also, bear in mind that deps may be bundled or distributed differently. So when configuring them, you need to specify their correct format.

In the end, my system-config.ts looked like this:

/***********************************************************************************************
 * User Configuration.
 **********************************************************************************************/
/** Map relative paths to URLs. */
const map: any = {
  'ng2-charts': 'vendor/ng2-charts',
  'chartjs': 'vendor/chart.js/dist/Chart.bundle.min.js',
  'color-name': 'vendor/color-name/index.js',
  'color-convert': 'vendor/color-convert/index.js',
  'chartjs-color': 'vendor/chartjs-color/dist/color.js',
  'chartjs-color-string': 'vendor/chartjs-color-string/color-string.js',
  'moment': 'vendor/moment/moment.js'
};

/** User packages configuration. */
const packages: any = {
  'ng2-charts': { defaultExtension: 'js', main: 'ng2-charts.js' },
  'chartjs': { defaultExtension: 'js', format: 'cjs' }
};

Update your CLI build

Add the following to the angular-cli-build.js file on the vendorNpmFiles array:

      'color-name/**/*.+(js|js.map)',
      'color-convert/**/*.+(js|js.map)',
      'chart.js/dist/Chart.bundle.min.js',
      'chartjs-color/dist/color.js',
      'chartjs-color-string/color-string.js',
      'ng2-charts/**/*.+(js|js.map)',
      'moment/moment.js'

Manually import charts.js

You need to import 'chartjs'; somewhere in your application to make System.js load Chart.js. I did that on my root component. Otherwise, ng2-chart will just fail silently.


So, all in all, the state of the art looks very bleak presently. At least for me. Unless I'm missing something important or doing something terribly wrong, this is right-down unusable. Whatever we are doing to Javascript needs to stop. Now.

(Ok, that was a joke... but really, this _is_ very cumbersome).

All 26 comments

I tried with d3. I am stuck in the same place. I am not able to import third party library.

Same over here with ng2-charts. Can't make this work, either.

use this link https://github.com/angular/angular-cli/wiki/3rd-party-libs that works perfectly

be sure that you've pointed correctly all necessary files in vendorNpmFiles in angular-cli-build.js
same for map and packages in system-config.ts

@SergeySolonko Clearly, that wiki page didn't help one bit. Was the first thing I read. Wouldn't be writing a comment here, otherwise.

For the record, after hours of pointlessly staring at my screen in bewilderment, I managed to make ng2-charts work. Here's a summary of what I did:

Configure URLs and packages

Edit system-config.ts and have it declare ng2-charts and _all its dependencies_. Manually. The only way of knowing which dependencies are those, AFAIK, is running your application and keep track of all 404 you'll get. Or dig out each package.json for a list. Once you do that, repeat the step for the dependencies of the dependencies.

After some trial and error, I figured out ng2-charts depends on color-name, color-convert and chart.js. In turn, _chart.js_ depends on chartjs-color, chartjs-color-string and moment.

So, you need to follow all steps on the wiki guide for _each one of those_.

Also, bear in mind that deps may be bundled or distributed differently. So when configuring them, you need to specify their correct format.

In the end, my system-config.ts looked like this:

/***********************************************************************************************
 * User Configuration.
 **********************************************************************************************/
/** Map relative paths to URLs. */
const map: any = {
  'ng2-charts': 'vendor/ng2-charts',
  'chartjs': 'vendor/chart.js/dist/Chart.bundle.min.js',
  'color-name': 'vendor/color-name/index.js',
  'color-convert': 'vendor/color-convert/index.js',
  'chartjs-color': 'vendor/chartjs-color/dist/color.js',
  'chartjs-color-string': 'vendor/chartjs-color-string/color-string.js',
  'moment': 'vendor/moment/moment.js'
};

/** User packages configuration. */
const packages: any = {
  'ng2-charts': { defaultExtension: 'js', main: 'ng2-charts.js' },
  'chartjs': { defaultExtension: 'js', format: 'cjs' }
};

Update your CLI build

Add the following to the angular-cli-build.js file on the vendorNpmFiles array:

      'color-name/**/*.+(js|js.map)',
      'color-convert/**/*.+(js|js.map)',
      'chart.js/dist/Chart.bundle.min.js',
      'chartjs-color/dist/color.js',
      'chartjs-color-string/color-string.js',
      'ng2-charts/**/*.+(js|js.map)',
      'moment/moment.js'

Manually import charts.js

You need to import 'chartjs'; somewhere in your application to make System.js load Chart.js. I did that on my root component. Otherwise, ng2-chart will just fail silently.


So, all in all, the state of the art looks very bleak presently. At least for me. Unless I'm missing something important or doing something terribly wrong, this is right-down unusable. Whatever we are doing to Javascript needs to stop. Now.

(Ok, that was a joke... but really, this _is_ very cumbersome).

in your example above https://github.com/angular/angular-cli/issues/845#issuecomment-221288257 where is the reference to phoenix_js ?

I tried the same steps at https://github.com/angular/angular-cli/wiki/3rd-party-libs with moment and d3. moment worked fine, however d3 failed with message Cannot find module 'd3'

ng init
npm install moment d3 --save
typings install d3 moment --ambient --save
file: *angular-cli-build.js*
vendorNpmFiles: [
      ...
      ..,
      'd3/d3.js',
      'moment/moment.js'
    ]
file: *system-config.ts*
const map: any = {
  'd3':'vendor/d3/d3.js',
  'moment':'vendor/moment/moment.js'
};
import * as d3 from 'd3';
import * as moment from 'moment';
Could not start watchman; falling back to NodeWatcher for file system events.
Visit http://ember-cli.com/user-guide/#watchman for more info.
Build failed.
The Broccoli Plugin: [BroccoliTypeScriptCompiler] failed with:
Error: Typescript found the following errors:
  /Users/abey.tom/github/abeytom/ext-test/tmp/broccoli_type_script_compiler-input_base_path-1lxf3vVu.tmp/0/src/app/ext-test.component.ts (2, 21): Cannot find module 'd3'.
    at BroccoliTypeScriptCompiler._doIncrementalBuild (/Users/abey.tom/github/abeytom/ext-test/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:115:19)
    at BroccoliTypeScriptCompiler.build (/Users/abey.tom/github/abeytom/ext-test/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:43:10)
    at /Users/abey.tom/github/abeytom/ext-test/node_modules/angular-cli/node_modules/broccoli-caching-writer/index.js:152:21
    at lib$rsvp$$internal$$tryCatch (/Users/abey.tom/github/abeytom/ext-test/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1036:16)
    at lib$rsvp$$internal$$invokeCallback (/Users/abey.tom/github/abeytom/ext-test/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1048:17)
    at lib$rsvp$$internal$$publish (/Users/abey.tom/github/abeytom/ext-test/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1019:11)
    at lib$rsvp$asap$$flush (/Users/abey.tom/github/abeytom/ext-test/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1198:9)
    at doNTCallback0 (node.js:417:9)
    at process._tickCallback (node.js:346:13)

I found that you need to run ng build or ng serve at least once before attempting to import the third-party lib in a component (so between steps 4 and 5 in the wiki). This first run will actually copy the script file to /dist. The CLI probably needs to change the build order to copy those vendor files over before compiling.

Also I noticed that the wiki omits the fact that you also need to drop a <script> tag into index.html pointing to the lib, the src being something like vendor/lib/script.js.

Only after doing these things was I then able to successfully import a third-party lib into my component(s).

@SergeySolonko I wasn't trying to add phoenix_js as a dependency, but ng2-charts.

@filoxo

Also I noticed that the wiki omits the fact that you also need to drop a <script> tag into index.html pointing to the lib, the src being something like vendor/lib/script.js.

No, you don't. The whole "five step process" is to, actually, _avoid_ using a <script> tag. System.js will load the script for you.

I pasted the typing for d3 in the browser and main folder (typings/browser and typings/main). and added the reference in main.d.ts and browser.d.ts. and added the map file in index.html file. It worked for me.

The same procedure worked for me with lodash

@nfanton yea, good call. I've just been battling this for long enough that I forgot the purpose of registering the lib with system.js.

@filoxo You are not in this fight alone, my man.

A bit late to the party, but is anyone still having trouble importing 3rd party libs here?

@filipesilva Did you ditch SystemJS entirely :stuck_out_tongue:? No? Then, yes. Using any fancy module loader makes adding stuff incredibly bothersome.

I am loathe to mention any other big tools, but this whole category of problem is approximately what JSPM solves. There is some chance that by iteratively solving this problem again here, this project will reinvent JSPM.

this whole category of problem is approximately what JSPM solves

This ^.

Except, that it doesn't. At least, not that well. And not without bringing a whole other bunch of problems along. And you still have to keep manual track of your dependencies in yet another config file.

Why is it _so_ hard for the JS community in general -for us all- to just stick with _one_ tool that does the job well? Instead, we have a plethora of not-so-good solutions (like package formats, module loaders, builders, seed projects, package managers...) each one claiming to have reinvented a wheel that has been turning around for years.

Indeed. I should have said, aims to solve. Though I don't think it deserves anywhere near as much negative comment as it gets. Particularly because, as far as I know, no other tool has stood up to do the same things better. But relevant to this item, I think to achieve a level of automation JSPM aspires to (and to a considerable extent delivers), CLI may end up needing mechanisms analogous to most of the mechanisms in JSPM. I don't know how deeply this will go; possibly by setting aside the notion of consuming non-NPM packaging, the result can be less work than JSPM has been. Hopefully, because JSPM has been under development for a long time, and the Angular community could benefit from a fairly complete CLI in a short time.

About your question of why, I agree wholeheartedly. However, this is the sort of problem that seems exasperating from afar and is exasperating in a totally different way from near. For example, why couldn't we just stick with the old CommonJS module format? The answer is, because it just does not work for various things that are pretty important today.

This is the sort of problem that seems exasperating from afar and is exasperating in a totally different way from near.

Couldn't have put it better.

Exasperation everywhere you turn your head. So, where exactly are we failing? It's certainly _not_ for lack of ideas. Why is it that when we finally _seem_ to be settling on a given tool (say npm for installing dependencies with -almost- zero hassle), some new wave comes along and somehow manages to disrupt that little peace of mind we had? From afar, it looks like involution. From up close, that involution disguises itself as "future-proof" promises.

This very CLI project is one marvelous example of this. Ultimately, it generates an empty HTML website with a static "It works!" text legend. Not so long ago, this could be written as:

<p>It works!</p>

Save that as index.html and double click it. That's it. You can even drop the p tags.

Now, apparently, we need 10Mb of JS scripts, an internet connection, a hierarchical folder structure, 15+ configuration files, a module loader, a builder, a CLI tool, a package manager, a working registry, typings, a typing installer and a transpiler. :shrug:

I _know_ what I'm writing is rather far fetched and unfair. But the whole idea really goes against the grain.

@nfantone @kylecordes I appreciate the feedback and ideas. I really do. I can tell you right now that _all_ of what you said in your last four comments has come up many _many_ many times in our internal discussions, and having it written down here helps reinforce how important the complexity of the topic is. We don't want to reinvent module loading, nor module definition, nor module configuration, but using tool X or Z for it usually does come with its fair share of problems at well.

However, saying:

@filipesilva Did you ditch SystemJS entirely :stuck_out_tongue:? No? Then, yes. Using any fancy module loader makes adding stuff incredibly bothersome.

doesn't help me solve this specific issue that seems to be about having trouble using phoenix_js or ng2-charts.

For this issue, I would prefer to stay out of the relative problems and merits of alternative solutions to the 3rd party lib issue, as there is a better discussion thread in https://github.com/angular/angular-cli/issues/882

If the original issue itself remains unsolved, please let me know so I can reopen this issue.

@nfantone Thanks for your post, it is very helpful. I'm trying to use filesaver.js in my project.

As for a more permenant solution... Could there be an angularCli import command?

I come from ruby gems, and all this javascript stuff with npm just seems like a cheap imitation to me. Don't get me wrong, I love the AngularCLI tool, I just wish I could go:

ng install {npm package | /path_to/my/javascript.js}

and have it put it in the right place in my project.

I actually cannot import my thirdparty app. It can't find the module.

My system-config.ts:

const map: any = {
  'filesaverjs': 'vendor/filesaver.js',
};

/** User packages configuration. */
const packages: any = {
  'filesaverjs': {defaultExtension: 'js', main: 'FileSaver.min.js'},
};

My angular-cli-build.js:

module.exports = function(defaults) {
  return new Angular2App(defaults, {
    vendorNpmFiles: [
     // ...  other files... systemjs, @angular, etc.
    'filesaver.js/*.js'
    ]
  });
};

I tried to just do this in the component that I needed it in:

import * as filesaver from 'filesaverjs';

but that fails with Cannot find module filesaverjs. I also tried to import it in my main.ts file:

import {} from 'filesaverjs';

which doesn't give me errors, but doesn't actually help.

What am I missing?

@filipesilva What would actually help the original issue? A working example of bringing in this library?

https://www.npmjs.com/package/phoenix-js

I thought of making such an example, but it is hard to get motivated to do so. The current scheme for bringing in libraries appears to be a rough early idea, I assume that the internal discussion you mentioned will later lead to a complete revamp that makes whatever we "outside" figure out now irrelevant anyway, right?

I did go through that process to get @ngrx/router working in CLI, it was not a lot of fun, and led me to the same conclusion that surely the current mechanism for configuring libraries in CLI will be replaced... with something that achieves what @jdell64 asked for. Which means it ends up solving many of the same problems as JSPM that I mentioned earlier, which of course is how we got to this point in the conversation which I agree is far off track.

How can I help? It is possible the right answer is that those of us trying to use CLI with various libraries today, should just go away for a while and give you guys on the core team time to work on the core problems? That is a totally acceptable answer.

Welp, these are the struggles of early adopters...

@kylecordes I get the feeling that the people trying to use specific libraries in this thread have managed to do so, thus I think it's closed. We do hope that the solution to the 3rd party lib problem will end up making all the needed arcane knowledge irrelevant, in the sense that it won't be needed at all.

Meanwhile the best issue I see for discussion is https://github.com/angular/angular-cli/issues/882, where we really appreciate the ideas and feedback. Having it in one place is really useful when directing people and trying to pool together people's solutions.

@jdell64 we actually had an ng install command at a time, but it actually proved to be both impractical and not very well liked. Users didn't like not using npm, and it was very hard to cover all cases.

Apologies for getting back here late, but:

doesn't help me solve this specific issue that seems to be about having trouble using phoenix_js or ng2-charts.

@filipesilva You are totally right. It doesn't. What _does_ help is my previous comment on installing ng2-charts, which expands a step by step solution to the problem.

My last comment was meant as a silly joke, remarking the fact that we we'll _always_ have problems installing things with this CLI tool as long as we (as a community) don't develop, adopt and follow at least one good way of managing deps. It wasn't even a good joke and it certainly wasn't a rant of sorts. I apologize if it came out that way.

@nfantone Holy smokes dude, saved me a ton! Thanks for the beautiful walk through the systemJS config and the cli-build! You came in clutch with that! Thank You!

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