Katana24
Katana24

Reputation: 8959

Loading third party library with Angular-cli

This is related to this question here and this one here but neither of those fit my needs.

I'm migrating an Angular2 app over to the angular-cli structure and I'm trying to include the .OBJLoader & .MTLLoader for the threejs library in my migrated project.

I've included the scripts from the threejs node folder in my .angular-cli.json file like this:

      "styles": [
        "styles.css"
      ],
      "scripts": [
        "../node_modules/three/examples/js/loaders/OBJLoader.js",
        "../node_modules/three/examples/js/loaders/MTLLoader.js"
      ],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }

Because the .OBJLoader & .MTLLoader don't have typings I thought that I'd have to create them myself in the typings.d.ts file:

/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
  id: string;
}

// OBJLoader
declare var objloader: OBJLoader;
interface OBJLoader {

}

// MTLLoader
declare var mtlloader: MTLLoader;
interface MTLLoader {

}

I then tried to import the modules into the service I required them in like this:

import { Injectable } from '@angular/core';

import * as THREE from 'three';
import * as OBJLoader from 'OBJLoader';
import * as MTLLoader from 'MTLLoader';

@Injectable()
export class LoaderService {

    constructor() {}

    setupMTLLoader(appPath) {
        var mtlLoader = new MTLLoader(); 
        return mtlLoader;
    }

    setupObjLoader(materials, appPath) {
        var objLoader = new OBJLoader();
        return objLoader;
    }
}

but angular-cli complains that:

Module not found: Error: Can't resolve 'OBJLoader' in '/my-path/src/app/shared/services'
 @ ./src/app/shared/services/loader.service.ts 12:0-39

Several questions here:

I'm confused as to what to do here.

Upvotes: 1

Views: 943

Answers (2)

Katana24
Katana24

Reputation: 8959

Thanks to @Joe Clay for the help but I ended up going with an alternative to allow me to require whatever file/s I needed. I edited the typings.d.ts file at the root of the src folder and added this:

/* Allow the use of require in the code  */
declare var require : any;

This allowed me to use the following when grabbing the .MTLLoader or .OBJLoader:

var MTLLoader = require('three-mtl-loader');
var OBJLoader = require('three-obj-loader'); 

Upvotes: 0

Joe Clay
Joe Clay

Reputation: 35847

The scripts section of the CLI config file doesn't relate to import and export - it just adds the scripts as tags in your HTML. If you want to import something from within node_modules that isn't the main export, you can do something along the lines of this:

// Your typings would need to match!
import * as OBJLoader from "three/examples/js/loaders/OBJLoader";

However, if you try to do that you'll immedialy run into a much trickier issue: Neither OBJLoader or MTLLoader are JavaScript/TypeScript modules. They don't export anything, instead just attaching stuff to the global THREE variable - which, since you're importing THREE, doesn't exist!

By adding typings, you're effectively saying "when I compile my code, these modules will exist", but it doesn't change the reality that the actual files don't match up to this.

You could try to do some Webpack trickery to make things hook in properly, but that would require ejecting your CLI config and using Webpack on its own...

Honestly, I think the best option here is to just copy the code into your project. Directly importing code from a package's examples seems like it could end up being pretty fragile.

Upvotes: 1

Related Questions