-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Switch to webpack to support ESM #5116
Conversation
|
FILES.push('tests/**/*.test.js'); | ||
glob.sync('tests/**/*.test.js').forEach(function (filename) { | ||
FILES.push(filename); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't quite understand why the previous code didn't work anymore, it gave me 16 tests instead of 355 tests. Doing the glob myself like it's done when you use TEST_FILE=atestfile npm run test:chrome
(the if above) fixed it.
@@ -69,7 +67,6 @@ if (process.env.TEST_ENV === 'ci') { | |||
] | |||
}; | |||
karmaConf.reporters.push('coverage'); | |||
karmaConf.preprocessors['src/**/*.js'] = ['coverage']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing this line is on purpose, this is not an error, https://github.com/istanbuljs/babel-plugin-istanbul#karma is saying to not add the coverage preprocessor.
I compared the report coverage before and after this PR, this is working properly.
'process.env.INSPECTOR_VERSION': JSON.stringify( | ||
process.env.INSPECTOR_VERSION | ||
) | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to know more about DefinePlugin: https://webpack.js.org/plugins/define-plugin/
liveReload: true, | ||
static: { | ||
directory: 'examples' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For you to understand, before you had a specific build for budo and replaced /dist by /build in the script. In webpack-dev-server, the build is done in memory when you are accessing /dist/aframe-master.js
, all the other files are served from the examples directory.
new webpack.ProvidePlugin({ | ||
process: 'process/browser', | ||
Buffer: ['buffer', 'Buffer'] | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://webpack.js.org/plugins/provide-plugin/
I found the solution for process.browser
and Buffer
here https://www.alchemy.com/blog/how-to-polyfill-node-core-modules-in-webpack-5
Note that webpack gave me this information at the beginning:
ERROR in ./node_modules/buffer-equal/index.js 1:13-37
Module not found: Error: Can't resolve 'buffer' in '/home/vincentfretin/workspace/aframe/node_modules/buffer-equal'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "buffer": require.resolve("buffer/") }'
- install 'buffer'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "buffer": false }
but using resolve.fallback
didn't work because buffer-equal
doesn't even use require('buffer')
, it just uses Buffer
directly.
], | ||
resolve: { | ||
alias: { | ||
three: 'super-three' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is super important otherwise you get three not found when importing the jsm files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filename: 'aframe-master.min.js' | ||
}, | ||
mode: 'production' | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file exists just to change the filename and the mode to production so that we have a minified build.
https://webpack.js.org/configuration/mode/
}, | ||
{ | ||
test: /\.css$/, | ||
use: ['style-loader', 'css-loader'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style-loader will inject two style tags in the DOM corresponding to the two css files we import, similar to browserify-css
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one gave me a hard time. I'm not sure how this worked with browserify with karma before, I think karma-browserify injected the AFRAME
variable in each file but I'm not really sure. With webpack with karma AFRAME
was an empty object in some tests, defining as a global variable in setup
fixed it.
"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", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The webpack command comes from the webpack-cli package. The serve
argument is available when you have the webpack-dev-server package. webpack serve
use the devServer
configuration in webpack.config.js
@@ -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", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose to use the parameter here but we could have used an environment variable and set it in the config https://webpack.js.org/configuration/dev-server/#devserverserver
@@ -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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For you to understand webpack by default is importing the package from the field 'browser', 'module', 'main' in this order of priority by default if those fields are defined in package.json
. super-animejs has a module field defined pointing to an ESM build.
https://webpack.js.org/configuration/resolve/#resolvemainfields
Great! Much appreciated. Thanks for making a surgical as possible. |
@@ -19,13 +19,14 @@ navigator.getVRDisplays = function () { | |||
return Promise.resolve([mockVRDisplay]); | |||
}; | |||
|
|||
require('index'); | |||
const AFRAME = require('index'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the const
here :) you can modify it to var
directly on master if you want.
I didn't expect you to merge it so quickly, I expected at least one question lol. I guess you didn't have any because I added a lot of comments to explain the changes. ;-) |
this is fantastic! |
@dmarcos you will see that webpack generates |
Note that in the dist there is now usage of And super-animejs is also using rollup to convert the code to ES6 (ES6 and ES2015 is the same thing) via @rollup/plugin-buble. |
Actually there was already usage of |
Description:
Browserify doesn't support ESM (ES6 modules), the PR #5101 broke master after it has been merged because of three r144 that removed the
examples/js/KTX2Loader.js
file as I said in my commentand three.js will remove all the umd builds from their repo by the end of the year
I don't think you want to maintain umd builds yourself in the super-three repo @dmarcos so I think it's time to move away from browserify/budo. In this PR I propose to switch to webpack.
Changes proposed:
I kept the changes to the minimum, so I kept polyfilling
Buffer
andprocess.browser
and for dev server I kept the same behavior for the host, port, watching files.For the
Buffer
polyfill, it's needed by thebuffer-equal
package, dependency ofnode_modules/load-bmfont/package.json
and
Buffer
is used innode_modules/load-bmfont/lib/is-binary.js
load-bmfont
is used insrc/components/text.js
Webpack is using ESM first if found, then fallback to UMD. For the super-animejs package that supports both, this means we need to replace
require('super-animejs')
byrequire('super-animejs').default
. This is how imported ESM build behave when importing withrequire()
.For
lib/three.js
, to not change torequire('lib/three.js').default
everywhere I did the following:I created a
lib/three.module.js
file where I now import the jsm versions instead of js versions of all the loaders and inlib/three.js
I userequire('./three.module.js').default;
so that's the only place where we use.default
like that.Important part, import from "three" that are included in jsm files are aliased to super-three.
Although we use
babel-loader
, we don't do any transpiling, I didn't add the@babel/preset-env
package.I tested:
npm run start
npm run start:https
generates a certificate on Ubuntu 22.04 successfully, this closes Self Signed SSL error #5084TEST_ENV=ci npm run test:chrome
and open the coverage tests/coverage/report/index.htmlnpm run build
create the non minified and minified build (1.3MB, webpack is using terser with -c -m options I guess) with sourcemaps working