Description: Regarding the file size of the final build I would like to make a few suggestions on how to reduce it.
First of all I think A-Frame is a great piece of software. It's API over the DOM elements was very novel for me and IMHO it's great to build even complex, fast and maintainable applications. So keep doing! Hope I can help with some PRs on the way. 👍
So let's talk about some ideas in how to improve the final build size.
Remove warn, console.warn and other similar calls in the final build. Similar to React I IMO it's nice practice to have code warnings to help developers only in the development and not production/minified version of A-Frame. Played around with this a little and was able to reduce file size by 20 KB. Finding more parts of the code only used for improving developer experience can increase this savings even more.
Do not include the whole package.json. Have the version numbers of A-Frame and three.js is again really useful in development. However I thinks it's not necessary to include the whole package.json into the build. This can either be fixed by a similar matter like in the first suggestion, or by defining global variables read from the package file to get included in the build as simple variables.
Maybe you have other ideas and ways in mind how to further improve the build size? Happy to hear what you think.
Hi @lennerd — A key distinction between A-Frame and React is that A-Frame doesn't require use of a bundler — most of our users are probably loading A-Frame as a <script src="..."/> from CDN, and are often unfamiliar with more advanced JS tooling. My vote would be to avoid introducing separate production and development builds, because for many users just opening the JS console is an "AHA" moment. If there were a fork, development should be the default in our documentation.
Omitting unused portions of package.json sounds very reasonable. Perhaps we could consider moving from Browserify to Webpack or Rollup (I believe the latter two support tree-shaking?).
As a baseline of discussion, v0.5.0 weighs in at:
Of that, THREE.js is responsible for about half:
Thanks for the quick reply.
A-Frame doesn't require use of a bundler
Talking about JSX, you're probably right. This language extension needs a proper build process. But essentially React also works without any build process at all by using React.createElement or the React.createFactory methods.
My vote would be to avoid introducing separate production and development builds, because for many users just opening the JS console is an "AHA" moment.
I totally agree with this. And I favor libraries working with schema validations and developer warnings to improve performance and reduce errors. My proposal however would be to use the minified version of A-Frame also as the production build (which IMHO goes hand in hand), similar to how React or other libraries are doing it when you use the minified version from some CDN. React also claims to have better performance in the minified version by removing for example component property validation. Maybe similar techniques are also possible with A-Frame?
In short: IMO the minified version is also the production build and should as such be as small and performant as possible, while the development build is the unminified version providing better developer experience.
Perhaps we could consider moving from Browserify to Webpack or Rollup (I believe the latter two support tree-shaking?).
Thought the same and would like to create a PR for moving to Webpack if appropriate.
Sounds good. Experimenting with the build seems like the right first step, especially if we can compare sizes of the resulting binaries. Webpack is more popular ofc, but Three.js recently switched to Rollup so I'm curious what that's like.
(And will need to defer to @ngokevin or @dmarcos for final say)
We'd have to narrow down exactly what we'd be able to shave off, if anything, if we moved to Webpack. In A-Frame, schemas primarily define parsing, not validation, and even then the code is extremely thin for that.
As Don said, React is a different ecosystem where you're pretty much mandated to use build tools. Even though you could theoretically do it, no one uses React without build tools. I'd be interested in seeing the build size comparisons, and I do prefer Webpack, but I don't think you save much size besides the tiny overhead for each module.
As Don said, React is a different ecosystem where you're pretty much mandated to use build tools. Even though you could theoretically do it, no one uses React without build tools.
To be clear, I don't want use React to compare the build process. I agree, that A-Frame should be useable without one. What I wanted to compare is the difference between production and development build, between minified and unminified version of A-Frame.
I'd be interested in seeing the build size comparisons, and I do prefer Webpack, but I don't think you save much size besides the tiny overhead for each module.
I think that this is better than nothing. We want to use A-Frame to be able to quickly build 3D embeds into bigger editorial articles working both on desktop and mobile. We are happy about every byte we can spare on the way.
One thing I'd like to add is the compatibility with other Webpack, Rollup and browserify setups. I would like to use the refactoring to also make it easier to include A-Frame and Three.js into an existing build process. This would also solve issues like https://github.com/aframevr/aframe/issues/1989 or https://github.com/aframevr/aframe/issues/1041. AFAIK this will not mean to break compatibility with CDN usage. My goal would be to have the same build steps and build files exporting to global, like before.
If you have any more feedback, don't hesitate to share it.
A quick update: Worked on the refactoring for a while now and was able to reduce the file size of the minified build to 976 kB (268 kB gzipped). This build still includes the warnings. So there is a bit more, we can gain.
Though I still have a problem with using this build in the examples due to a weird behaviour of the Webpack style-loader. Hope to be able to fix it soon.
125kb savings sounds promising so far! Took a look through the minified code and have a couple more ideas. Haven't verified much of this, but it looks like:
isMobile total size 7kbOther things we're already considering deprecating and moving into separate repos:
<a-animation/> code (??kb)One thing I would like to comment on this. While reducing the size of the build is important we have to evaluate how much energy is worth investing on it. The size of the assets that the average VR application is going to load will make a-frame build size negligible in comparison. For instance, The vive controller model weights already 1.5 MB from the obj and another 1.X MB from the textures (https://github.com/aframevr/assets/blob/gh-pages/controllers/vive/vr-controller-vive.obj) and that's just a single asset :-)
Certainly there's a point of diminishing returns; i'd agree 3-5kb changes are probably not worth conditional logic in normal/minified builds. But if webpack shaves 125kb, that's relevant to mobile users. 50kb of SVG is similarly suspicious. Want to deal with just those two?
To be honest, I think 1.5MB is too much for the vive controllers, too. That's >30,000 tris before you've even added any content to the scene. And it's <600kb after conversion to glTF. 😬
The vive controllers can indeed be optimized. It's an example illustrating that just a couple of assets will make the build size responsible for just a tiny fraction of the loading time. In an asset heavy medium I would not go out of our way to optimize the build size of a-frame. Webpack enforcing workflows and tooling into our users is another cost that has to be factored in.
I would look first on cheap ways to improve our build size without replacing the tooling
@lennerd Can you provide more info about your particular use case? How big is the a-frame build compared to other assets that your average embed loads?
@donmccurdy very nice findings. Will try to tackle what is possible with Webpack. Especially the working on the size of the SVG files sounds promising.
The size of the assets that the average VR application is going to load will make a-frame build size negligible in comparison.
@dmarcos Agree on this. We just had the problem of creating low-poly meshes to reduce script size. Nice to know, that the controllers can be simplified, too.
Can you provide more info about your particular use case? How big is the a-frame build compared to other assets that your average embed loads?
I'm working for the interactive team of an online news site and we plan to create more 3D and VR visualisations to enhance reading experience. More than 50 % of our users surf the website with a mobile device, therefore the size of assets is very important for us. The average size of embed assets is between 60 to 200 kB. But we are aware that WebGL based experiences come with some overhead. However as I said we are happy for every byte we can spare.
I'm very sorry, but my job situation changed and I'm therefore not able to spend so much time on this issue any longer. I'll try to find time in the coming month to create a WIP PR to share my current state with implementing Webpack.
wontfixing as it's hard to go from here, but can look at PRs for smaller, more specific changes if anyone wants to do. considering the size of A-Frame is equivalent to an image, KBs here and there aren't as weighted as they would be on a normal 2D page's expectations IMO
Most helpful comment
One thing I would like to comment on this. While reducing the size of the build is important we have to evaluate how much energy is worth investing on it. The size of the assets that the average VR application is going to load will make a-frame build size negligible in comparison. For instance, The vive controller model weights already 1.5 MB from the obj and another 1.X MB from the textures (https://github.com/aframevr/assets/blob/gh-pages/controllers/vive/vr-controller-vive.obj) and that's just a single asset :-)