Skip to content

Commit 7ac47c0

Browse files
Fix ES usage in node (#5522)
* rename three.module.js to three.mjs * make the imports works in node 22 with --experimental-require-module flag * stop polyfilling process.browser and modify isBrowserEnvironment check * make node test running * alias super-three to three in package.json so it works on node * window.THREE is set in index.js, no need to do it in lib/three.mjs * we still need process polyfill for the browser tests * update documentation about jsdom * strip npm:super-three@ when showing the three version in console * use a global INSPECTOR_VERSION variable instead of process.env.INSPECTOR_VERSION * put back a comment about mocked process in isBrowserEnvironment * use THREE.REVISION to log three version, when using aframe as ES module, three version may actually be different than the version defined in aframe dependencies
1 parent 81caf89 commit 7ac47c0

File tree

13 files changed

+58
-61
lines changed

13 files changed

+58
-61
lines changed

docs/core/globals.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,14 @@ global. This same interface is also exposed if requiring with CommonJS
5252

5353
## Requiring `AFRAME` in a Node.js Environment
5454

55-
It is possible to run A-Frame in [Node.js](https://nodejs.org/en/about) to get access to its globals. The only catch is we need to supply a browser `window` mock since Node.js lacks a `window` object. A-Frame is tested with [jsdom](https://github.com/jsdom/jsdom), although any JavaScript-based browser implementation should work.
55+
It is possible to run A-Frame in [Node.js](https://nodejs.org/en/about) to get access to its globals. The only catch is we need to supply a browser `window` mock since Node.js lacks a `window` object. You can do that with [jsdom-global](https://www.npmjs.com/package/jsdom-global), and you also need to mock `customElements`.
5656

5757
```js
58-
const jsdom = require("jsdom");
59-
global.window = new jsdom.JSDOM().window;
58+
const cleanup = require('jsdom-global')();
59+
global.customElements = { define: function () {} };
6060
var aframe = require('aframe/src');
6161
console.log(aframe.version);
62+
cleanup();
6263
```
6364

64-
Although A-Frame can load in Node.js, A-Frame isn't (yet) able to run any simulations at run time.
65+
You can't use jsdom to run tests with aframe components because `customElements` api is missing. A-Frame is using karma to open a real browser to run the tests.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"test:firefox": "npm test -- --browsers Firefox",
2525
"test:chrome": "npm test -- --browsers Chrome",
2626
"test:nobrowser": "NO_BROWSER=true npm test",
27-
"test:node": "mocha --ui tdd tests/node"
27+
"test:node": "node --experimental-require-module ./node_modules/mocha/bin/mocha --ui tdd tests/node"
2828
},
2929
"repository": "aframevr/aframe",
3030
"license": "MIT",
@@ -40,7 +40,7 @@
4040
"deep-assign": "^2.0.0",
4141
"load-bmfont": "^1.2.3",
4242
"super-animejs": "^3.1.0",
43-
"super-three": "0.164.0",
43+
"three": "npm:super-three@0.164.0",
4444
"three-bmfont-text": "dmarcos/three-bmfont-text#eed4878795be9b3e38cf6aec6b903f56acd1f695",
4545
"webvr-polyfill": "^0.10.12"
4646
},
@@ -60,7 +60,8 @@
6060
"git-rev": "^0.2.1",
6161
"glob": "^8.0.3",
6262
"husky": "^0.11.7",
63-
"jsdom": "^20.0.0",
63+
"jsdom": "^24.0.0",
64+
"jsdom-global": "^3.0.2",
6465
"karma": "^6.4.0",
6566
"karma-chai-shallow-deep-equal": "0.0.4",
6667
"karma-chrome-launcher": "^3.1.1",

src/components/scene/inspector.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global AFRAME */
1+
/* global AFRAME, INSPECTOR_VERSION */
22
var AFRAME_INJECTED = require('../../constants').AFRAME_INJECTED;
33
var pkg = require('../../../package');
44
var registerComponent = require('../../core/component').registerComponent;
@@ -16,7 +16,7 @@ function getFuzzyPatchVersion (version) {
1616

1717
var INSPECTOR_DEV_URL = 'https://aframe.io/aframe-inspector/dist/aframe-inspector.js';
1818
var INSPECTOR_RELEASE_URL = 'https://unpkg.com/aframe-inspector@' + getFuzzyPatchVersion(pkg.version) + '/dist/aframe-inspector.min.js';
19-
var INSPECTOR_URL = process.env.INSPECTOR_VERSION === 'dev' ? INSPECTOR_DEV_URL : INSPECTOR_RELEASE_URL;
19+
var INSPECTOR_URL = typeof INSPECTOR_VERSION !== 'undefined' && INSPECTOR_VERSION === 'dev' ? INSPECTOR_DEV_URL : INSPECTOR_RELEASE_URL;
2020
var LOADING_MESSAGE = 'Loading Inspector';
2121
var LOADING_ERROR_MESSAGE = 'Error loading Inspector';
2222

src/core/scene/a-scene.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global Promise, screen, CustomEvent */
1+
/* global Promise, customElements, screen, CustomEvent */
22
var initMetaTags = require('./metaTags').inject;
33
var initWakelock = require('./wakelock');
44
var loadingScreen = require('./loadingScreen');
@@ -920,7 +920,7 @@ function constrainSizeTo (size, maxSize) {
920920
return size;
921921
}
922922

923-
window.customElements.define('a-scene', AScene);
923+
customElements.define('a-scene', AScene);
924924

925925
/**
926926
* Return the canvas size where the scene will be rendered.

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ require('./extras/primitives/');
8080

8181
console.log('A-Frame Version: 1.5.0 (Date 2024-05-03, Commit #9fe641ce)');
8282
console.log('THREE Version (https://github.com/supermedium/three.js):',
83-
pkg.dependencies['super-three']);
83+
THREE.REVISION);
8484
console.log('WebVR Polyfill Version:', pkg.dependencies['webvr-polyfill']);
8585

8686
// Wait for ready state, unless user asynchronously initializes A-Frame.

src/lib/three.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
var THREE = require('./three.module.js').default;
1+
var THREE = require('./three.mjs').default;
2+
// TODO: Eventually include these only if they are needed by a component.
3+
global.THREE = THREE;
4+
require('../../vendor/DeviceOrientationControls');
25

36
// In-memory caching for XHRs (for images, audio files, textures, etc.).
47
if (THREE.Cache) {

src/lib/three.mjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as SUPER_THREE from 'three';
2+
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
3+
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
4+
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
5+
import { OBB } from 'three/addons/math/OBB.js';
6+
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
7+
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
8+
import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js';
9+
import { LightProbeGenerator } from 'three/examples/jsm/lights/LightProbeGenerator.js';
10+
11+
var THREE = { ...SUPER_THREE };
12+
THREE.DRACOLoader = DRACOLoader;
13+
THREE.GLTFLoader = GLTFLoader;
14+
THREE.KTX2Loader = KTX2Loader;
15+
THREE.OBJLoader = OBJLoader;
16+
THREE.MTLLoader = MTLLoader;
17+
THREE.OBB = OBB;
18+
THREE.BufferGeometryUtils = BufferGeometryUtils;
19+
THREE.LightProbeGenerator = LightProbeGenerator;
20+
21+
export default THREE;

src/lib/three.module.js

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/utils/debug.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var debug = require('debug');
2+
var isBrowserEnvironment = require('./device').isBrowserEnvironment;
23

34
var settings = {
45
colors: {
@@ -114,6 +115,6 @@ if (ls && (parseInt(ls.logs, 10) || ls.logs === 'true')) {
114115
debug.enable('*:error,*:info,*:warn');
115116
}
116117

117-
if (process.browser) { window.logs = debug; }
118+
if (isBrowserEnvironment) { window.logs = debug; }
118119

119120
module.exports = debug;

src/utils/device.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,9 @@ module.exports.isLandscape = function () {
200200
* We need to check a node api that isn't mocked on either side.
201201
* `require` and `module.exports` are mocked in browser by bundlers.
202202
* `window` is mocked in node.
203-
* `process` is also mocked by browserify, but has custom properties.
203+
* `process` is also mocked by webpack running with karma, but has custom properties like process.browser.
204204
*/
205-
module.exports.isBrowserEnvironment = !!(!process || process.browser);
205+
module.exports.isBrowserEnvironment = typeof process === 'undefined' || process.browser === true;
206206

207207
/**
208208
* Check if running in node on the server.

0 commit comments

Comments
 (0)