diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 974077515a6..871cebb84ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,15 +45,9 @@ jobs: with: run: npm run test:chrome -- --single-run -# - name: Test node -# run: npm run test:node - - name: Check Lint run: npm run lint - - name: Check Build - run: npm run build - - name: Check Build Minified run: npm run dist diff --git a/package.json b/package.json index e4f9ab908f1..466fbc24634 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,10 @@ "homepage": "https://aframe.io/", "main": "dist/aframe-master.js", "scripts": { - "browserify": "browserify src/index.js -s 'AFRAME' -p browserify-derequire", - "build": "shx mkdir -p build/ && npm run browserify -- --debug -t [ envify --INSPECTOR_VERSION dev ] -o build/aframe.js", - "dev": "npm run build && cross-env INSPECTOR_VERSION=dev node ./scripts/budo -t envify", - "dist": "node scripts/updateVersionLog.js && npm run dist:min", - "dist:max": "npm run browserify -s -- --debug | exorcist dist/aframe-master.js.map > dist/aframe-master.js", - "dist:min": "npm run dist:max && terser dist/aframe-master.js -c --source-map 'content=dist/aframe-master.js.map,url=aframe-master.min.js.map' -o dist/aframe-master.min.js", + "dev": "cross-env INSPECTOR_VERSION=dev webpack serve", + "dist": "node scripts/updateVersionLog.js && npm run dist:min && npm run dist:max", + "dist:max": "webpack --config webpack.config.js", + "dist:min": "webpack --config webpack.prod.config.js", "docs": "markserv --dir docs --port 9001", "preghpages": "node ./scripts/preghpages.js", "ghpages": "ghpages -p gh-pages/", @@ -20,7 +18,7 @@ "prepush": "node scripts/testOnlyCheck.js", "prerelease": "node scripts/release.js 1.2.0 1.3.0", "start": "npm run dev", - "start:https": "cross-env SSL=true npm run dev", + "start:https": "npm run dev -- --server-type https", "test": "karma start ./tests/karma.conf.js", "test:docs": "node scripts/docsLint.js", "test:firefox": "npm test -- --browsers Firefox", @@ -37,6 +35,7 @@ "vendor/**/*" ], "dependencies": { + "buffer": "^6.0.3", "custom-event-polyfill": "^1.0.6", "debug": "ngokevin/debug#noTimestamp", "deep-assign": "^2.0.0", @@ -51,25 +50,20 @@ "webvr-polyfill": "^0.10.12" }, "devDependencies": { - "browserify": "^17.0.0", - "browserify-css": "^0.15.0", - "browserify-derequire": "^1.1.1", - "browserify-istanbul": "^3.0.1", - "budo": "^11.8.4", + "@babel/core": "^7.17.10", + "babel-loader": "^8.2.5", + "babel-plugin-istanbul": "^6.1.1", "chai": "^4.3.6", "chai-shallow-deep-equal": "^1.4.0", "chalk": "^1.1.3", "cross-env": "^7.0.3", - "envify": "^4.1.0", - "exorcist": "^2.0.0", + "css-loader": "^6.7.1", "ghpages": "0.0.8", "git-rev": "^0.2.1", "glob": "^8.0.3", "husky": "^0.11.7", - "istanbul": "^0.4.5", "jsdom": "^20.0.0", "karma": "^6.4.0", - "karma-browserify": "^8.1.0", "karma-chai-shallow-deep-equal": "0.0.4", "karma-chrome-launcher": "^3.1.1", "karma-coverage": "^2.2.0", @@ -78,6 +72,7 @@ "karma-mocha": "^2.0.1", "karma-mocha-reporter": "^2.2.5", "karma-sinon-chai": "^2.0.2", + "karma-webpack": "^5.0.0", "markserv": "github:sukima/markserv#feature/fix-broken-websoketio-link", "mocha": "^10.0.0", "replace-in-file": "^2.5.3", @@ -87,17 +82,15 @@ "sinon": "<12.0.0", "sinon-chai": "^3.7.0", "snazzy": "^5.0.0", - "terser": "^5.15.0", + "style-loader": "^3.3.1", "too-wordy": "ngokevin/too-wordy", + "webpack": "^5.73.0", + "webpack-cli": "^4.10.0", + "webpack-dev-server": "^4.11.0", + "webpack-merge": "^5.8.0", "write-good": "^1.0.8" }, "link": true, - "browserify": { - "transform": [ - "browserify-css", - "envify" - ] - }, "semistandard": { "ignore": [ "build/**", @@ -120,9 +113,6 @@ "web-components", "webvr" ], - "browserify-css": { - "minify": true - }, "engines": { "node": ">= 4.6.0", "npm": ">= 2.15.9" diff --git a/scripts/budo.js b/scripts/budo.js deleted file mode 100644 index 52ec16171f3..00000000000 --- a/scripts/budo.js +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env node - -var exec = require('child_process').exec; -var urlParse = require('url').parse; - -var budo = require('budo'); - -function execCmd (cmd) { - var p = exec(cmd); - p.stderr.pipe(process.stderr); - p.stdout.pipe(process.stdout); - return p; -} - -var consts = { - NAME: 'AFRAME', - ENTRY: './src/index.js', - DIST: 'dist/aframe-master.js', - BUILD: 'build/aframe-master.js', - WATCH: 'examples/**/*', // Additional files to watch for LiveReload - PORT: 9000 -}; - -var opts = { - debug: process.env.NODE_ENVIRONMENT !== 'production', - verbose: true, - live: true, - stream: process.stdout, - host: process.env.HOST, - port: process.env.PORT || consts.PORT, - watchGlob: consts.WATCH, - ssl: process.env.SSL, - browserifyArgs: ['-s', consts.NAME], - middleware: function (req, res, next) { - // Route `dist/aframe-master.js` to `build/aframe-master.js` so we can - // dev against the examples :) - var path = urlParse(req.url).pathname; - if (path.indexOf('/' + consts.DIST) !== -1) { - req.url = req.url.replace('/dist/', '/build/'); - } - // TODO: Consider adding middleware that targets specific directories - // (such that editing `examples/a.html` doesn't reload `examples/b.html`). - next(); - } -}; - -var app = budo(consts.ENTRY + ':' + consts.BUILD, opts); -app.on('update', function () { - execCmd('semistandard -v | snazzy'); -}); diff --git a/src/components/animation.js b/src/components/animation.js index 5e3ac7555f9..e3ef1474fcf 100644 --- a/src/components/animation.js +++ b/src/components/animation.js @@ -1,4 +1,4 @@ -var anime = require('super-animejs'); +var anime = require('super-animejs').default; var components = require('../core/component').components; var registerComponent = require('../core/component').registerComponent; var THREE = require('../lib/three'); diff --git a/src/core/component.js b/src/core/component.js index bbb15d73f5e..f4d77926479 100644 --- a/src/core/component.js +++ b/src/core/component.js @@ -48,7 +48,7 @@ var Component = module.exports.Component = function (el, attrValue, id) { this.el.components[this.attrName] = this; this.objectPool = objectPools[this.name]; - const events = this.events; + var events = this.events; this.events = {}; eventsBind(this, events); diff --git a/src/index.js b/src/index.js index 8fc57ca1729..39b4762a3bd 100644 --- a/src/index.js +++ b/src/index.js @@ -99,7 +99,7 @@ module.exports = window.AFRAME = { AComponent: require('./core/component').Component, AEntity: AEntity, ANode: ANode, - ANIME: require('super-animejs'), + ANIME: require('super-animejs').default, AScene: AScene, components: components, coreComponents: Object.keys(components), diff --git a/src/lib/three.js b/src/lib/three.js index 4617de88c78..504e8f5db23 100644 --- a/src/lib/three.js +++ b/src/lib/three.js @@ -1,4 +1,4 @@ -var THREE = global.THREE = require('super-three'); +var THREE = require('./three.module.js').default; // Allow cross-origin images to be loaded. @@ -18,17 +18,6 @@ if (THREE.Cache) { THREE.Cache.enabled = true; } -// TODO: Eventually include these only if they are needed by a component. -require('../../vendor/DeviceOrientationControls'); // THREE.DeviceOrientationControls -require('super-three/examples/js/loaders/DRACOLoader'); // THREE.DRACOLoader -require('super-three/examples/js/loaders/GLTFLoader'); // THREE.GLTFLoader -require('super-three/examples/js/loaders/KTX2Loader'); // THREE.KTX2Loader -require('super-three/examples/js/loaders/OBJLoader'); // THREE.OBJLoader -require('super-three/examples/js/loaders/MTLLoader'); // THREE.MTLLoader -require('super-three/examples/js/utils/BufferGeometryUtils'); // THREE.BufferGeometryUtils -require('super-three/examples/js/lights/LightProbeGenerator'); // THREE.LightProbeGenerator -require('super-three/examples/js/utils/WorkerPool'); // WorkerPool used by KTX2Loader - THREE.DRACOLoader.prototype.crossOrigin = 'anonymous'; THREE.GLTFLoader.prototype.crossOrigin = 'anonymous'; THREE.KTX2Loader.prototype.crossOrigin = 'anonymous'; diff --git a/src/lib/three.module.js b/src/lib/three.module.js new file mode 100644 index 00000000000..3f7b2e2052c --- /dev/null +++ b/src/lib/three.module.js @@ -0,0 +1,23 @@ +import * as SUPER_THREE from 'super-three'; +import { DRACOLoader } from 'super-three/examples/jsm/loaders/DRACOLoader'; +import { GLTFLoader } from 'super-three/examples/jsm/loaders/GLTFLoader'; +import { KTX2Loader } from 'super-three/examples/jsm/loaders/KTX2Loader'; +import { OBJLoader } from 'super-three/examples/jsm/loaders/OBJLoader'; +import { MTLLoader } from 'super-three/examples/jsm/loaders/MTLLoader'; +import * as BufferGeometryUtils from 'super-three/examples/jsm/utils/BufferGeometryUtils'; +import { LightProbeGenerator } from 'super-three/examples/jsm/lights/LightProbeGenerator'; + +var objectAssign = require('object-assign'); +var THREE = window.THREE = objectAssign({}, SUPER_THREE); + +// TODO: Eventually include these only if they are needed by a component. +require('../../vendor/DeviceOrientationControls'); // THREE.DeviceOrientationControls +THREE.DRACOLoader = DRACOLoader; +THREE.GLTFLoader = GLTFLoader; +THREE.KTX2Loader = KTX2Loader; +THREE.OBJLoader = OBJLoader; +THREE.MTLLoader = MTLLoader; +THREE.BufferGeometryUtils = BufferGeometryUtils; +THREE.LightProbeGenerator = LightProbeGenerator; + +export default THREE; diff --git a/tests/__init.test.js b/tests/__init.test.js index 7d49faeae44..244a11e2d2c 100644 --- a/tests/__init.test.js +++ b/tests/__init.test.js @@ -1,4 +1,4 @@ -/* global AFRAME, sinon, setup, teardown */ +/* global sinon, setup, teardown */ /** * __init.test.js is run before every test case. @@ -19,13 +19,14 @@ navigator.getVRDisplays = function () { return Promise.resolve([mockVRDisplay]); }; -require('index'); +const AFRAME = require('index'); var AScene = require('core/scene/a-scene').AScene; // Make sure WebGL context is not created since Travix CT runs headless. // Stubs below failed once in a while due to asynchronous tesst setup / teardown. AScene.prototype.setupRenderer = function () {}; setup(function () { + window.AFRAME = AFRAME; this.sinon = sinon.createSandbox(); // Stubs to not create a WebGL context since Travis CI runs headless. this.sinon.stub(AScene.prototype, 'render'); diff --git a/tests/karma.conf.js b/tests/karma.conf.js index 5e2362e55f7..253ae83f90e 100644 --- a/tests/karma.conf.js +++ b/tests/karma.conf.js @@ -1,5 +1,7 @@ // Karma configuration. +var path = require('path'); var glob = require('glob'); +var webpackConfiguration = require("../webpack.config.js"); // Define test files. var FILES = [ @@ -14,15 +16,20 @@ if (process.env.TEST_FILE) { } }); } else { - FILES.push('tests/**/*.test.js'); + glob.sync('tests/**/*.test.js').forEach(function (filename) { + FILES.push(filename); + }); } +// add 'src' to be able to resolve require('utils/tracked-controls') for +// example in the tests +webpackConfiguration.resolve.modules = ['src', 'node_modules']; +// webpack will create a lot of files, use build directory instead of dist +webpackConfiguration.output.path = path.resolve(__dirname, '../build'); + var karmaConf = { basePath: '../', - browserify: { - debug: true, - paths: ['src'] - }, + webpack: webpackConfiguration, browsers: ['Firefox', 'Chrome'], customLaunchers: { ChromeTravis: { @@ -38,28 +45,19 @@ var karmaConf = { 'TEST_ENV' ], files: FILES, - frameworks: ['mocha', 'sinon-chai', 'chai-shallow-deep-equal', 'browserify'], + frameworks: ['mocha', 'sinon-chai', 'chai-shallow-deep-equal', 'webpack'], preprocessors: { - 'tests/**/*.js': ['browserify', 'env'] + 'tests/**/*.js': ['webpack', 'env'] }, reporters: ['mocha'] }; // Configuration for code coverage reporting. if (process.env.TEST_ENV === 'ci') { - Object.assign(karmaConf.browserify, { - transform: [ - [ - 'browserify-istanbul', { - instrumenterConfig: { - embedSource: true - }, - defaultIgnore: true, - ignore: ['**/node_modules/**', '**/tests/**', '**/vendor/**', '**/*.css'] - } - ] - ] - }); + // modify the babel-loader rule + karmaConf.webpack.module.rules[0].use.options = { + plugins: [['istanbul', { 'exclude': ['**/node_modules/**', '**/tests/**', '**/vendor/**', '**/*.css'] }]] + }; karmaConf.coverageReporter = { dir: 'tests/coverage', includeAllSources: true, @@ -69,7 +67,6 @@ if (process.env.TEST_ENV === 'ci') { ] }; karmaConf.reporters.push('coverage'); - karmaConf.preprocessors['src/**/*.js'] = ['coverage']; karmaConf.browsers = ['Firefox', 'ChromeTravis']; } diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000000..4404d0883ca --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,57 @@ +var path = require('path'); +var webpack = require('webpack'); + +module.exports = { + entry: './src/index.js', + output: { + library: 'AFRAME', + libraryTarget: 'umd', + path: path.resolve(__dirname, 'dist'), + publicPath: '/dist/', + filename: 'aframe-master.js' + }, + devtool: 'source-map', + mode: 'development', + devServer: { + host: 'local-ip', + port: process.env.PORT || 9000, + hot: false, + liveReload: true, + static: { + directory: 'examples' + } + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.INSPECTOR_VERSION': JSON.stringify( + process.env.INSPECTOR_VERSION + ) + }), + new webpack.ProvidePlugin({ + process: 'process/browser', + Buffer: ['buffer', 'Buffer'] + }) + ], + resolve: { + alias: { + three: 'super-three' + } + }, + module: { + rules: [ + { + test: /\.js$/, + use: { + loader: 'babel-loader' + // options: { + // presets: ['@babel/preset-env'], + // }, + } + }, + { + test: /\.css$/, + use: ['style-loader', 'css-loader'] + } + ] + } +}; diff --git a/webpack.prod.config.js b/webpack.prod.config.js new file mode 100644 index 00000000000..535acd1df39 --- /dev/null +++ b/webpack.prod.config.js @@ -0,0 +1,14 @@ +var path = require('path'); +var merge = require('webpack-merge').merge; +var commonConfiguration = require('./webpack.config.js'); + +module.exports = merge(commonConfiguration, { + output: { + library: 'AFRAME', + libraryTarget: 'umd', + path: path.resolve(__dirname, 'dist'), + publicPath: '/dist/', + filename: 'aframe-master.min.js' + }, + mode: 'production' +});