- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 4.2k
Switch to webpack to support ESM #5116
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
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.
| ] | ||
| }; | ||
| 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
| 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
| "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
| 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. | 
| }; | ||
|  | ||
| 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.jsfile 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
Bufferandprocess.browserand for dev server I kept the same behavior for the host, port, watching files.For the
Bufferpolyfill, it's needed by thebuffer-equalpackage, dependency ofnode_modules/load-bmfont/package.jsonand
Bufferis used innode_modules/load-bmfont/lib/is-binary.jsload-bmfontis used insrc/components/text.jsWebpack 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').defaulteverywhere I did the following:I created a
lib/three.module.jsfile where I now import the jsm versions instead of js versions of all the loaders and inlib/three.jsI userequire('./three.module.js').default;so that's the only place where we use.defaultlike 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-envpackage.I tested:
npm run startnpm run start:httpsgenerates a certificate on Ubuntu 22.04 successfully, this closes Self Signed SSL error #5084TEST_ENV=ci npm run test:chromeand open the coverage tests/coverage/report/index.htmlnpm run buildcreate the non minified and minified build (1.3MB, webpack is using terser with -c -m options I guess) with sourcemaps working