Skip to content
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

Add Rollup Config to module examples to UMD #15526

Merged
merged 5 commits into from
Jan 7, 2019

Conversation

gkjohnson
Copy link
Collaborator

Related to #15518

Changes

This change adds a new rollup config for converting all js modules in the example/jsm folder into UMD equivalents in example/js and moves towards the module syntax being the primary way to maintain the examples. The files are converted in a way that is backwards compatible with how the example scripts are currently used so no other code changes will be needed.

Rollup Output

To build the jsm files just run npm run build-examples. You can see examples of the output in the linked GLTFLoader and OrbitControls. You can verify the list of examples with the new files here.

Moving forward converted modules will just need to be moved into the jsm folder in the same folder structure as js and they will be converted. One caveat of this conversion method to support backwards compatibility (extending the global THREE object in the UMD files) is that the modules must use named imports and not default ones. For example export { OrbitControls }; is good while export default OrbitControls; is bad.

@donmccurdy
Copy link
Collaborator

Nice, thanks!

This change works with the current script-based usage, as in our example demos, but UMD modules are also meant to work as CommonJS modules and in that case we have this output:

require('../../../build/three.module.js')

I think the generated file should depend on the UMD build file instead? Or even just three.

One caveat of this conversion method to support backwards compatibility (extending the global THREE object in the UMD files) is that the modules must use named imports and not default ones.

I think that's preferable in any case.

banner:
'/**\n' +
` * Generated from '${ path.relative( '.', inputPath.replace( /\\/, '/' ) ) }'\n` +
' **/\n'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typically the header would end in */ rather than **/ I think

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this, too! Thanks

@donmccurdy
Copy link
Collaborator

For example, Browserify-based apps can currently do something like this:

const THREE = window.THREE = require('three');
require('three/examples/js/loaders/GLTFLoader.js');

That second line appends GLTFLoader to the window.THREE global, and fails if the global isn't there. That was never ideal, and if this change means the hack above doesn't work but the following does, that's fine with me:

const THREE = require('three');
const GLTFLoader = require('three/examples/js/loaders/GLTFLoader.js');

@gkjohnson
Copy link
Collaborator Author

Good catch -- I just updated the config so it converts the .../build/three.module.js path to three in the UMD files. I updated the linked example scripts, as well.

I'm less familiar with Browserify but my experience with other bundlers says you should be able to just import GLTFLoader and it will pull three in implicitly. However keep in mind that because the modules are using named exports your code will probably look like this:

const { GLTFLoader } = require('three/examples/js/loaders/GLTFLoader.js');

@donmccurdy
Copy link
Collaborator

^Looks good, thanks!

@mrdoob mrdoob added this to the r101 milestone Jan 7, 2019
@mrdoob mrdoob merged commit 63ffe8d into mrdoob:dev Jan 7, 2019
@mrdoob
Copy link
Owner

mrdoob commented Jan 7, 2019

Thanks!

@mrdoob
Copy link
Owner

mrdoob commented Jan 7, 2019

The script currently produces this:

this.manager = ( manager !== undefined ) ? manager : three_module_js.DefaultLoadingManager;

Shouldn't it stay like this?

this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

@gkjohnson
Copy link
Collaborator Author

Shouldn't it stay like this?

this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

The UMD wrapper is pretty convoluted to read but it's the same thing.

The relevant factory call in the UMD wrapper when loading with a script tag is factory(global.THREE = global.THREE || {}, global.THREE), which calls the body function with a signature defined as function (exports, three_module_js). global gets set to window so window.THREE gets passed into the body function as three_module_js.

@gkjohnson gkjohnson deleted the rollup-jsm-examples branch January 7, 2019 23:53
@donmccurdy
Copy link
Collaborator

For readability I suppose we could just include an inline plugin function renaming three_module_js back to a local variable THREE.

@gkjohnson
Copy link
Collaborator Author

My thought was that the built UMD modules shouldn't even necessarily be considered read-able (and to maybe even minify the builds) to discourage editing of them directly and instead provide a banner pointing to edit the source js modules instead. Of course this means that copying and editing the UMD variants wouldn't be all that easy, which was always one of the features promoted by naming the folder "examples" in the first place.

I don't think I have any strong opinions about either approach, though. I just hope we don't start getting PRs submitting fixes for the UMD files instead of the jsm ones

@mrdoob
Copy link
Owner

mrdoob commented Jan 8, 2019

We are just starting a transition. I think we should keep them readable and with the least changes possible. So I agree that we should rename three_module_js to THREE.

@looeee
Copy link
Collaborator

looeee commented Jan 8, 2019

It might prevent some confusion for people not following this discussion to include a banner at the top of the generated files saying not to edit the file directly.

@gkjohnson
Copy link
Collaborator Author

@mrdoob
Sounds fair. I've added a PR to convert that variable name here: #15543

@looeee
I agree -- at the moment the banner says the file was generated, at least, but maybe it could be more explicit?

@looeee
Copy link
Collaborator

looeee commented Jan 8, 2019

at the moment the banner says the file was generated

Oops, I totally missed that. But yes, perhaps just add something like "It's not recommended to edit this file directly".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants