The examples/js directory will be removed with r148

This can be mitigated with semver. Blindly upgrading major would be a disaster, but blindly upgrading minor/patch is ok.

major revision changes have slowed down significantly as well. for example, I was able to up certain code by almost 40 revisions (109 to 147) with the only breaking change being applyMatrix renamed to applyMatrix4 :sweat_smile:


Just because the part of the project that you use didn’t break doesn’t mean nothing broke. All breaking changes per version are listed here:

So technically every version is breaking in some way - in part because example code changes. I agree semver is nice but if it’s going to be adopted in any way the structure of the project would need to change which I don’t expect to happen.

1 Like

obviously different codes will run into different number of problems, it just feels like the overall number of these problems is lower than it used to be with earlier versions. then, of course, this is just a feeling not hard statistical data.

1 Like

I suspect there are ways we could de-complicate this. Like considering most (or all?) of three/addons/* as {experimental | alpha | beta} and not restricting breaking changes there to major version updates. New APIs like THREE.ColorManagement would get the same treatment initially. JSDoc and TSDoc have tags for this. Then doing breaking changes and major version updates in three.js core less often, maybe once or twice a year.

But it does take up-front planning and management, and that isn’t free. Discussion for another time perhaps!


semver doesn’t have to be adopted, it’s just a view into some data. Every version of three is a major version. There have been 140+ different major versions of three, and a handful of minor I believe.

1 Like

Like considering most (or all?) of three/addons/* as {experimental | alpha | beta} and not restricting breaking changes there to major version updates.

This would be nice but if this were to happen I’d think there should be a distinction between “addons” that are versioned and “example” files which are wild west. The reality of it is that people treat and rely on addons as part of the versioned library. If the goal is to be able to specify a version and get patch or minor releases automatically then if classes like OrbitControls or GLTFLoader incur breaking changes they shouldn’t be automatically updated with a patch release because core didn’t change.

Anyway just some thoughts.

There have been 140+ different major versions of three, and a handful of minor I believe.

Yeah my only point was that even following a “semver” model every monthly version of three.js should be major because it’s breaking. Patches are made when hotfixes are made immediately after a new version.

The reality of it is that people treat and rely on addons as part of the versioned library.

just to add to what you said. three-stdlib is a real life example of what addons could become:

  "dependencies": {
    "@webgpu/glslang": "^0.0.15",
    "chevrotain": "^10.1.2",
    "draco3d": "^1.4.1",
    "fflate": "^0.6.9",
    "ktx-parse": "^0.4.5",
    "mmd-parser": "^1.0.4",
    "opentype.js": "^1.3.3",
    "potpack": "^1.0.1",
    "zstddec": "^0.0.2"
  "peerDependencies": {
    "three": ">=0.122.0"

by pinning dependencies to an exact version, or allow for patch updates and even minors it can progress on its own while clamping down version ranges for the things it bases on.

if you have mis-matching packages, say three 150 and addons targets 140.x, then running npm install will fail, the CLI will notify you about matching ranges. it’s rather hard to mess up in practice, and after all this is a well understood problem since practically every library on npm is in the same boat.

1 Like

@drcmda @gkjohnson @dubois @makc3d let’s continue the semver thread in Three.js, semver, and addons perhaps?


I have made a simple online tool to convert a Three.js module from examples/jsm into examples/js. Conversion is done by studying differences and similarities of jsm and js in r147, so it may not work in future release. In any case, in another project of mine I have successfully used converted FontLoader.js, GLTFExporter.js, OrbitControls.js and TextGeometry.js from r148.

The tool is here:

1 Like
var regex = /\/\/[^\n]*\n|\/\*[^]*?\*+\/|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|[^\s\,\;\(\)\.\[\:\{\}]+|\,|\;|\(|\)|\.|\[|\:|\{|\}/g;

holy shit :smiley:


AWESOME, this will help me alot

1 Like

Is there any easy way to just convert the whole folder and save it out? I use over 20 files to convert and thought if I could just do the whole folder it might make it easier with each update. BTW I looked a little bit of the code and on the hash js file it list 147 and 148. Will this have to change with each update?


I didn’t find an easy and browser independent way to drag a folder and get its contents in client-side JavaScript. However, it is possible to select many files and drag them together. This will at least save you half of the mouse clicks.

The hash table is used only to find whether a file has changed and to indicate the expectation whether the conversion is OK. It does not affect the conversion process. When r149 comes out, I will add r149 hashes to the table. I plan to update the hashes for an year.

Note, that the demoduler is a temporary tool, so I didn’t spend much efforts on it. Most likely the demoduler will become obsolete in an year.

– Pavel

Well I didn’t see a way, but thought I would ask. I may try to do a php update to automate since you plan on doing a years worth of updates, that certainly makes it worth it.

You say you didn’t spend much time? Man you undersell what you have done :). Seems like a LOT to me and again, thanks so much for writing this, now at least I know I can still update for a year… I’m soooo happy !

1 Like


The process might not be easily PHP-able. For each JSM file that has changed, I convert it to JS and then I manually compare the result against the old r147 JS file. If the differences are not essential, I mark the new file as good. So far most changes are minor (like extra parentheses, updated comments, added default values, etc).

One year is not that much. These are 12 releases.

– Pavel

Well by php I simply mean loading a list of files, read from the folder and loop through the js part that does the magic, then post to a php page to save the files out based on the list to a new folder with same structure, so basically just a lazy man’s way of getting and saving the files. OR just get off my lazy ass and do as you suggested and drag n drop a bunch together :slight_smile:

1 Like

@MrBodean I’ve read previously that you have a project dependent on the now deprecated js files part of 3js but honestly this sounds like so much more work than just spending a couple hours understanding how es6 modules can benefit and work for you, it’s like 6 lines of code a slight change of importing files and a non trivial update to name spaces, just my honest opinion but this all sounds like a right mare just to inevitably have to make the transition at some point anyway… peace and love

Yep I know, but the main reason I don’t is that my current project talks to iframes and other scripts, which in es6 cant be done externally, it only works with functions inside the module code, but your right and I am aware, your not the first to tell me I’m nuts :slight_smile:

1 Like

I’m not sure I get exactly what you mean but other non es6 scripts can be used along side three as they would be loaded in order before any module script and defined before a module loads internal functions, iframes can also be accessed via querySelector, of course I don’t know the exact flow of coding style you’ve got going on but sounds doable if using three in an es6 environment…