1

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:

  • What do I need to change to get this to work?
  • Does the typings folder examine the @types folder in the node_nodules for declared types?
  • How do scripts get loaded in and made available in typescript?

I'm confused as to what to do here.

Pop-A-Stash
  • 6,572
  • 5
  • 28
  • 54
Katana24
  • 8,706
  • 19
  • 76
  • 118

2 Answers2

1

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.

Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • when you say copy the code into your project do you mean doing that through the .angular-cli.json? Or perhaps (and this is the way it was before) placing it into the assets folder under a libs folder and passing it THREE? I was originally using webpack for this but had to migrate to the angular-cli way of doing things – Katana24 Jun 02 '17 at 15:07
  • @Katana24: If you want to `import` it, you don't want to do either of those options. You'll need to add it in your `src` folder and modify the code so that it exports `OBJLoader` instead of trying to add it to the `THREE` variable. – Joe Clay Jun 02 '17 at 15:12
  • @Katana24: Oh - or alternatively, someone's [packaged that up as a NPM package](https://www.npmjs.com/package/three-obj-loader), so you can just do `import * as OBJLoader from "three-obj-loader"`. You'll still need to write your own typings, but it's probably a lot easier :) – Joe Clay Jun 02 '17 at 15:14
  • thanks for that link - i prefer to think that that module only just got uploaded in the past 15 minutes haha – Katana24 Jun 02 '17 at 15:30
0

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'); 
Katana24
  • 8,706
  • 19
  • 76
  • 118