Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
892 views
in Technique[技术] by (71.8m points)

javascript - Require.js not loading Three.js

So I have some generated JavaScript (from TypeScript):

define(["require", "exports", "three", "jquery", "./test"], function (require, exports, THREE, jQuery, Test) {
var Main = (function () {
    function Main() {
        this.container = jQuery('#test');
        this.scene = new THREE.Scene();
...

This ends up with an error in the browser (on the last line of above):

Uncaught TypeError: Cannot read property 'Scene' of undefined

Interestingly jQuery has no problems; it's as if Three.js is simply not being loaded.

Require config:

requirejs.config({
    baseUrl: "src",
    paths: {
        "main": "../main",
        "test": "../test",
        "three": "../three/three",
        "sizzle": "/src/sizzle/dist/sizzle"
    }
});

jQuery is in the 'js/src' folder, whereas Three.js is at 'js/three/three.js' (Express is being used so the js folder is hidden to the browser, and it doesn't seem to make any difference if I move three.js to the src folder). Sizzle is sitting on it's own because it was causing errors from being in a subfolder inside src.

Am I missing anything obvious about this? I have no leads

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

From r72 onwards

From r72 onwards, three does call define. So you should not set a shim. If you do not have code that relies on THREE being available in the global space, you're done.

However, if there is code that relies on THREE being available in the global space, that's a problem because, as a well-behaved AMD module, THREE no longer just leaks to the global space. For code that needs THREE in the global space, you can just create a module like this which you can put just before your call to requirejs.config:

define("three-glue", ["three"], function (three) {
    window.THREE = three;
    return three;
});

Your RequireJS configuration should contain this map:

map: {
  '*': {
    three: 'three-glue'
  },
  'three-glue': {
    three: 'three'
  }
}

This tells RequireJS "wherever three is required, load three-glue instead, but when three is required in three-glue load three."

All together:

define("three-glue", ["three"], function (three) {
    window.THREE = three;
    return three;
});

requirejs.config({
    baseUrl: "src",
    paths: {
        "main": "../main",
        "test": "../test",
        "three": "../three/three",
        "sizzle": "/src/sizzle/dist/sizzle"
    },
    map: {
        '*': {
            three: 'three-glue'
        },
        'three-glue': {
            three: 'three'
        }
    }
});

(Technical note: r72 actually still performed the leak to the global space, and some versions after it do. The latest released version at the time of editing this answer (r83) does not leak to the global space by itself. I've not examined every version between r72 and r83 to check when the change was made. Using the code above with an old AMD-compliant version that does the leak is safe. It just results in unnecessary code.)

For r71 and earlier

If this file is any guide, three does not call define. So you need a shim for it if you want it to have a value when you require it as a module. Something like this:

shim: {
    three: {
        exports: 'THREE'
    }
}

Based on the config you have in your question:

requirejs.config({
    baseUrl: "src",
    paths: {
        "main": "../main",
        "test": "../test",
        "three": "../three/three",
        "sizzle": "/src/sizzle/dist/sizzle"
    },
    shim: {
        three: {
            exports: 'THREE'
        }
    }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...