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 build-examples script #21584

Merged
merged 6 commits into from
Apr 6, 2021
Merged

Conversation

marcofugaro
Copy link
Contributor

@marcofugaro marcofugaro commented Apr 6, 2021

Related issue: #19986 (comment) #20527

Description

Add the build-examples script that allows to convert esmodule files to non-esmodule files and optionally transpile them for older browsers.

It works like this:

  1. Compile the files through rollup without importing dependencies
  2. Feed the file through babel which optionally transpiles it
  3. Run the unmodularize script, which just like the modularize script but reversed
  4. Clean up the babel output with eslint to make it conform to the repo coding styleguide

Here is an example:

Input

import { LineSegments2 } from '../lines/LineSegments2.js';
import { LineGeometry } from '../lines/LineGeometry.js';
import { LineMaterial } from '../lines/LineMaterial.js';

var Line2 = function ( geometry, material ) {

	if ( geometry === undefined ) geometry = new LineGeometry();
	if ( material === undefined ) material = new LineMaterial( { color: Math.random() * 0xffffff } );

	LineSegments2.call( this, geometry, material );

	this.type = 'Line2';

};

Line2.prototype = Object.assign( Object.create( LineSegments2.prototype ), {

	constructor: Line2,

	isLine2: true

} );

export { Line2 };

Output

( function () {

	var Line2 = function ( geometry, material ) {

		if ( geometry === undefined ) geometry = new THREE.LineGeometry();
		if ( material === undefined ) material = new THREE.LineMaterial( {
			color: Math.random() * 0xffffff
		} );
		THREE.LineSegments2.call( this, geometry, material );
		this.type = 'Line2';

	};

	Line2.prototype = Object.assign( Object.create( THREE.LineSegments2.prototype ), {
		constructor: Line2,
		isLine2: true
	} );

	THREE.Line2 = Line2;

} )();

Currently I left out the nodes files, it's a bit more tricky because of the Nodes namespace, but will do it in a future PR.

I also left out some other files (such as the webxr ones) because the library they're using doesn't currently provide a non-module version. See the ignore list for details.

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 6, 2021

Let's take FlakeTexture as an example. Right now, the script produces this:

class FlakesTexture {

	constructor( width = 512, height = 512 ) {

		const canvas = document.createElement( 'canvas' );
		canvas.width = width;
		canvas.height = height;
		const context = canvas.getContext( '2d' );
		context.fillStyle = 'rgb(127,127,255)';
		context.fillRect( 0, 0, width, height );

		for ( let i = 0; i < 4000; i ++ ) {

			const x = Math.random() * width;
			const y = Math.random() * height;
			const r = Math.random() * 3 + 3;
			let nx = Math.random() * 2 - 1;
			let ny = Math.random() * 2 - 1;
			let nz = 1.5;
			const l = Math.sqrt( nx * nx + ny * ny + nz * nz );
			nx /= l;
			ny /= l;
			nz /= l;
			context.fillStyle = 'rgb(' + ( nx * 127 + 127 ) + ',' + ( ny * 127 + 127 ) + ',' + nz * 255 + ')';
			context.beginPath();
			context.arc( x, y, r, 0, Math.PI * 2 );
			context.fill();

		}

		return canvas;

	}

}

THREE.FlakesTexture = FlakesTexture;

Meaning the global namespace is polluted with FlakesTexture. Is it possible to do this (never tried it):

class THREE.FlakesTexture {

@CodyJasonBennett
Copy link
Contributor

That doesn't seem possible without some magic from the likes of Babel.

This would be similar to:

const THREE.someConstant = value

@marcofugaro
Copy link
Contributor Author

@Mugen87 I think you meant

THREE.FlakesTexture = class FlakesTexture {

It is definitely possible with some regex magic but currently it's really hard because of files such as CCDIKSolver.js which creates an unnecessary wrapper and makes the regex stuff difficult.

It's safer to wait for the classes conversion of examples/jsm, in the meantime I'll wrap the file in a ( function () { } )()

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 6, 2021

in the meantime I'll wrap the file in a ( function () { } )()

That sounds good to me.

@mrdoob
Copy link
Owner

mrdoob commented Apr 6, 2021

💪💪💪

@mrdoob mrdoob added this to the r128 milestone Apr 6, 2021
@mrdoob mrdoob merged commit 157fd1c into mrdoob:dev Apr 6, 2021
@mrdoob
Copy link
Owner

mrdoob commented Apr 6, 2021

Thanks!

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 6, 2021

Great! Should we remove now utils/modularize.js and run the new script once (in order to update examples/js)?

This was referenced Apr 6, 2021
@mrdoob
Copy link
Owner

mrdoob commented Apr 6, 2021

Great! Should we remove now utils/modularize.js and run the new script once (in order to update examples/js)?

I think so! @marcofugaro are you taking care of that?

@marcofugaro
Copy link
Contributor Author

Okay! I'll do a big PR with the new examples/js folder!

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 6, 2021

BTW: I've tested various loader and post-processing examples with the generated files and all worked (of course after updating the imports^^).

This was referenced Apr 6, 2021
@mrdoob
Copy link
Owner

mrdoob commented Apr 7, 2021

@Mugen87 I think we should add @gkjohnson for this item in the change log 👍

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 7, 2021

Noted!

@gkjohnson
Copy link
Collaborator

gkjohnson commented Apr 7, 2021

It should also be noted in the migration guide that postprocessing/Pass.js must be included in the page because it's no longer bundled into EffectComposer.js. I'm not sure what else might have broken in that way. #20527 tried to ensure that all previously bundled files in js would continue to be bundled after building the js (though it may not have been successful in every case now that I think about it again) which would also let us break up some of the monolithic jsm files into multiple smaller scripts but that's not enabled here. Something similar could be added to the new script so jsm can be written and updated more freely.

@Mugen87
Copy link
Collaborator

Mugen87 commented Apr 7, 2021

It should also be noted in the migration guide that postprocessing/Pass.js must be included in the page because it's no longer bundled into EffectComposer.js.

It seems the new script handles this use case, see:

THREE.EffectComposer = EffectComposer;
THREE.Pass = Pass;

I've tested post-processing examples without including Pass and it worked. However, CopyShader and ShaderPass have to be included now again (like in the earlier days). The composer notifies the user with a warning if they are missing.

@gkjohnson
Copy link
Collaborator

It seems the new script handles this use case, see:

Oh I see, you're right -- I was confused because it's also specified as a separate file now. Looks good!

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.

5 participants