Three.js: Fortsetzung der Unterstützung für JS-Bibliotheken neben ES6-JSM-Bibliotheken

Erstellt am 5. Okt. 2020  ·  51Kommentare  ·  Quelle: mrdoob/three.js

Bezieht sich Ihre Feature-Anfrage auf ein Problem?

Ich glaube, es ist eine gute Bibliothekshygiene, sowohl Modul- als auch klassische statische Dateiimporte zu unterstützen. Dadurch bleibt die Bibliothek für eine breitere Gruppe von Entwicklern zugänglich und ermöglicht es Entwicklern, ihren bevorzugten Stil zu verwenden.

Persönlich versuche ich wirklich, die Verwendung von Modulen im Allgemeinen zu vermeiden, ich mag Projekte, die statische Dateien mit klassischen einfachen JS-Datei-Includes sind. Vielleicht bin ich nur ein Verrückter, aber ich hasse es wirklich, wie sehr Frameworks Sie unnötig von Dingen abstrahieren und wie sehr sie Räder neu erfinden oder Sie auf andere Weise in eine Blackbox verwandeln. Ich weiß, dass Sie Module ohne Frameworks verwenden können, aber Moduleinbindungen sind weniger intuitiv als traditionelle JS-Einbindungen, sie haben mich oft im Stich gelassen, als ich versuchte, sie in einem statischen Datei-Setup zu verwenden.

Die Verwendung von ES6-Modulen ist nicht für jede Bereitstellung ideal, obwohl sie sicherlich eine willkommene Ergänzung sind. Ich bringe vielen neuen Programmierern Threejs bei, weil ich die Bibliothek liebe und meiner Meinung nach eine großartige und befriedigende Möglichkeit ist, in die Programmierung einzusteigen. Es ist viel einfacher, Leuten grundlegendes Vanilla-CSS/JS/HTML beizubringen, ohne ihnen gleichzeitig den gesamten Node/npm + -Framework-Stack in den Hals zu schieben. Statische Bibliotheken sind einfacher zu verwenden/zu verstehen und halten hier die Einstiegshürde niedrig.

Stilistisch ziehe ich es auch vor, THREE mit zusätzlicher Funktionalität zu überladen, anstatt neue benannte Funktionen hinzuzufügen, die frei herumfliegen. Obwohl dies offensichtlich eine Präferenz ist.

Beschreiben Sie die gewünschte Lösung

Vielleicht kann ich dies besser beantworten, nachdem ich ein wenig mehr Informationen darüber erhalten habe, warum die Entscheidung getroffen wurde, nur auf Module umzusteigen, aber ich werde es versuchen.

Die Dokumentation geht darauf ein, dass ES6-Module möglicherweise nicht in jeder Situation funktionieren, und schlägt für diese Situationen die Verwendung eines Bundlers wie browserify/rollup/webpack/parcel usw. vor.

Meine Lösung wäre, dass ein automatisches ES6-Bundler-Skript die Module in /examples/jsm durchläuft , um /examples/js Nicht-Modul-Versionen zu generieren. Auf diese Weise müssen sich Entwickler nicht mehr darum kümmern, an zwei Stellen Änderungen vorzunehmen, und können weiterhin die JS-Nicht-Modul-Versionen und den globalen Var-Importstil verwenden, wenn sie möchten.

Diese automatische Generierung von JS-Nichtmoduldateien könnte als Teil des Build-Prozesses erfolgen oder ein Befehl in der Datei „package.json“ sein, den jemand manuell ausführen könnte. Obwohl ich mich für die automatische Generierung entscheiden würde.

Das Erstellen dieser Automatisierung oder das anderweitige Warten der JS-Nicht-Modul-Versionen dieser Bibliothek ist etwas, wofür ich meine Zeit aufwenden kann. Wenn der Grund für den Wechsel zu ES6 nur darin besteht, dass nicht nur zwei parallele Versionen derselben Sache manuell aktualisiert werden müssen, würde ich gerne andere Lösungen diskutieren, um diese Bedenken ebenfalls auszuräumen.

Beschreiben Sie Alternativen, die Sie in Betracht gezogen haben

Die offensichtliche andere Überlegung wäre, die Dinge so zu lassen, wie sie sind, und die JS- und JSM-Versionen aller Bibliotheken weiterhin zu pflegen. Obwohl ich die Ankündigung bedenke, dass diese veraltet sind, halte ich dies für etwas unwahrscheinlich. Aber ich würde gerne die Verantwortung dafür übernehmen, sicherzustellen, dass JS-Bibliotheken manuell mit ihren JSM-Gegenstücken auf dem neuesten Stand bleiben, wenn wir uns für diesen Weg entscheiden.

Zusätzlicher Kontext

Viel Liebe zu dieser Bibliothek und allen, die entweder im Code oder durch das Melden/Diskutieren von Problemen beitragen.

Suggestion

Hilfreichster Kommentar

Vielen Dank an alle für das Teilen der Vor- und Nachteile. Es ist immer gut, diese zu teilen, um sicherzustellen, dass wir fundierte Entscheidungen treffen.

Das ist etwas, wofür ich dieses Jahr einige Gehirnzyklen aufgewendet habe, und ich habe sogar Browser-Anbieter nach ihren Prioritäten gefragt, damit ich vorausplanen konnte.

Ich stimme zu, dass ES6-Module die Zukunft sind, aber die Entwicklung mit ihnen ohne Importkarten kann große Kopfschmerzen verursachen und Ihren Fluss vollständig unterbrechen. Als wir uns entschieden haben, examples/js , hatte ich gehofft, dass Import Maps mehr Zugkraft haben würde, aber es scheint, dass es derzeit keine Priorität für Browser hat.

Aus diesem Grund habe ich mich entschieden, die Einstellung des examples/js -Ordners auszusetzen, bis Browser Import-Maps implementieren. Ich würde es hassen, Neulinge dazu zu zwingen, etwas über Polyfills oder Bundler zu lernen, um ihren ersten Cube zu rendern.

Ich bin zum gleichen Schluss gekommen wie @Bug-Reaper. Heute schaue ich mir an, wie man ein Skript erstellt, das examples/js aus examples/jsm -Dateien erstellt.

Alle 51 Kommentare

Es ist viel einfacher, Leuten grundlegendes Vanilla-CSS/JS/HTML beizubringen, ohne ihnen gleichzeitig den gesamten Node/npm + -Framework-Stack in den Hals zu schieben. Statische Bibliotheken halten hier die Einstiegshürde niedrig.

Nur um die js-Beispielmodule, wie sie in diesem Projekt verwaltet werden, zu verdeutlichen, benötigen Sie keinen Knoten, npm oder ein Build-Framework. Sie können genau wie die alten globalen Importe als statisch bereitgestellte Dateien verwendet werden. Sie benötigen nur die es6-Importsyntax, um sie zu verwenden, aber das funktioniert in allen modernen Browsern.

Nur um die js-Beispielmodule, wie sie in diesem Projekt verwaltet werden, zu verdeutlichen, benötigen Sie keinen Knoten, npm oder ein Build-Framework. Sie können genau wie die alten globalen Importe als statisch bereitgestellte Dateien verwendet werden. Sie benötigen nur die es6-Importsyntax, um sie zu verwenden, aber das funktioniert in allen modernen Browsern.

Danke für die Abklärung! Das ist in der Tat ein guter Punkt!
Ich glaube:

<script type="module">

  import { OrbitControls } from 'https://unpkg.com/three@<VERSION>/examples/jsm/controls/OrbitControls.js';

  const controls = new OrbitControls();

</script>
````
is perhaps less intuitive and harder to understand for newcomers than: 

Moment mal... wir haben noch:

<script src="path/to/local/build/three.js"></script>

im Gegensatz zu:

<script type=module src="path/to/local/build/three.module.js"></script>

Das erste ist ein statisches Skript, das nach der alten globalen Methode in jemandes HTML verwendet werden kann ... richtig? Was konnten Sie nach einem Wechsel zu ES6 nicht mehr tun?

Wenn ich das richtig verstehe, ist geplant, neben der "/build/three.module.js" noch eine "/build/three.js" einzufügen.

Jawohl. Ob dieser Ansatz jedoch sinnvoll ist, ist fraglich. Wenn examples/js entfernt wird, bleiben nur noch wenige Anwendungsfälle übrig, in denen three.js und three.min.js noch nützlich sind.

Es wäre tatsächlich vorteilhaft, three.js und three.min.js zu entfernen, da es uns erlauben würde, den Einstiegspunkt main des Pakets npm zu ändern, siehe #19575.

Wenn wir dies problemlos tun können, halte ich es für sinnvoll, /examples/js weiterhin zu unterstützen, indem sie automatisch über ein ES6-Bundler-Skript als Teil des Build-Prozesses generiert werden.

Die Idee ist, examples/jsm auf modernere JavaScript-Sprachfunktionen wie Klassen umzustellen. Da examples/js immer noch mit älteren Browsern funktionieren sollte, wäre es notwendig, einen neuen (Beispiel-)Build mit Code-Transpilationsfunktionen zu konfigurieren. Außerdem würden wir immer noch die doppelte Codebasis ( examples/js vs. examples/jsm ) beibehalten, was meiner Meinung nach ein schlechter Ansatz ist. Das macht die Wartung komplizierter.

Ich glaube, der Benutzer muss sich bei Bedarf um die Konvertierung von ES6 zu ES5 kümmern. Gleiches gilt für die Code-Minifizierung oder andere Build-bezogene Aufgaben.

Ich glaube, Sie haben recht. Wenn ich das richtig verstehe, ist geplant neben der " /build/three.module.js " noch eine " /build/three.js " einzubinden.

Wahr

Das Problem mit Dateien aus dem Ordner /examples besteht darin, dass Sie Dateien aus /examples/js verwenden müssen, wenn Sie /build/three.js verwendet haben, und Dateien aus /examples/jsm , wenn Sie /build/three.module.js verwendet haben

Warum? Denn bei der Verwendung von Modulimporten ist das Hauptobjekt $ THREE nicht mehr ein einfaches js-Objekt THREE = {} , sondern ein Modulobjekt eines internen Browsers, das versiegelt (nicht erweiterbar) ist, daher Dateien von /examples/js der versucht, eine neue Eigenschaft in das Objekt THREE zu schreiben, schlägt fehl.

Sie können also nicht import * as THREE from '/build/three.module.js und THREE.WhateverExample = function() ... mischen

Eine Möglichkeit besteht darin, den Namen der importierten Bibliothek in etwas anderes als THREE zu ändern und ein einfaches js THREE globales Objekt neu zu erstellen, damit Beispiele darin geschrieben werden können ...

Dies ist typischerweise das Problem von

traditionelles JS enthält

das verschmutzt die globale Raumbenennung, und weil Sie keine Namen in der geladenen Datei ändern können, erhalten Sie möglicherweise solche Fehler ...
Auf der anderen Seite erhält der Benutzer bei Modulen die Möglichkeit, während des Imports Namen zu vergeben, und es ist nicht mehr der Autor der Bibliothek, der den resultierenden Namen auswählt ...

Ex:

<script>
// a script you can't modify already use the name THREE
var THREE = document.getElementById('div-nb-3')
</script>

<script type="module">
import * as foo from '/build/three.module.js'

THREE.appendChild( new foo.WebGLRenderer().domElement )
</script>

@Mugen87 Du hast 100% Recht. Wenn wir die /examples/js fallen lassen , können wir genauso gut die three.js & three.min.js fallen lassen, da sie im Wesentlichen mit keinem der Zusatzmodule kompatibel sind. Ihr Anwendungsfall wäre eine Nische, und dies wird fast garantiert Verwirrung stiften.

@devingfx Sie haben Recht, dass Module Vorteile haben und potenzielle globale Namenskonflikte beseitigen. In den Jahren der Verwendung hatte ich noch nie einen Konflikt mit der globalen Variablen THREE, und ich denke, dies ist ein unwahrscheinliches Szenario, aber Ihr Punkt ist technisch korrekt.

was meiner Meinung nach ein schlechter Ansatz ist. Das macht die Wartung komplizierter.

Ich glaube, der Benutzer muss sich bei Bedarf um die Konvertierung von ES6 zu ES5 kümmern. Gleiches gilt für die Code-Minifizierung oder andere Build-bezogene Aufgaben.

@ Mugen87 Ist es wirklich so schrecklich, ein traditionelles js-Include zu pflegen, das zusätzlich zu einem Modul eine globale Variable verwendet? Viele Bibliotheken unterstützen beides, und soweit ich das beurteilen kann, wird die traditionelle JS-Version oft genauso häufig verwendet wie die Gegenstücke der Modulversion. Beide haben Vor- und Nachteile, und einige davon laufen auf die Präferenz hinaus. Ist es nicht gut, Entwicklern die Möglichkeit zu geben, eine Bibliothek in einem Nicht-Modul-Kontext zu verwenden?

Ich bin bereit, mich um das Erstellen/Testen der erforderlichen Code-Transpilationsfunktionen zu kümmern, um automatisch three.min.js, three.js und /examples/js aus den three.module.js und /examples/jsm zu generieren. Nachdem der Transpilations-Workflow verfeinert wurde, erfordert er möglicherweise eine minimale Wartung, aber es != die Wartung von zwei parallelen Versionen. Zum größten Teil müsste der Code nur in den Moduldateien aktualisiert werden, und nur gelegentlich müssten Sie einige Transpilationsfehler beheben.

Ich habe genug Projekte, die sich auf die traditionelle globale Syntax verlassen, und beinhaltet, dass ich sowieso die Arbeit für die Automatisierung der Transpilation der Module erledigen werde. Ich denke, wir könnten zumindest einen Befehl in die package.json aufnehmen und ihn "legacy-build" nennen, der die Module in three.min.js, three.js und /examples/js transpiliert, die sich ähnlich wie das Original verhalten Dateien jetzt. Diese Dateien müssen nicht einmal an das Repo übergeben oder standardmäßig erstellt werden. Wir könnten auch warnen, dass sie für Legacy-Unterstützung sind, es ist nicht garantiert, dass sie funktionieren, wir schlagen vor, stattdessen Module zu verwenden usw.

Realistischerweise halte ich es jedoch für sinnvoller, sie im Repo zu belassen und sie einfach automatisch durch Transpiling beim Build generieren zu lassen.

einen Befehl in der package.json und nennen Sie ihn "Legacy-Build", der die Module transpiliert

scheint vernünftig. wurde babel nicht vor kurzem zusammengeführt? Also ich denke, das könnte so machbar sein

Bearbeiten: Um zu verdeutlichen, dass der neue Befehl nicht von irgendjemandem ausgeführt werden soll, außer von den Benutzern, die den Build wünschen

Ist es wirklich so schrecklich, ein herkömmliches js-Include zu pflegen, das zusätzlich zu einem Modul eine globale Variable verwendet?

Ich denke, die Komplexität der Aufrechterhaltung wird unterschätzt. Leider finde ich das mit der Art und Weise, wie Beispiele im Projekt aufgebaut werden, nicht so einfach.

Schauen wir uns GLTFLoader als Beispiel an. Derzeit ist der gesamte GLTFLoader in einer einzigen Datei enthalten, was es einfach macht, ihn am Anfang einer HTML-Datei einzufügen. Einer der Vorteile von Modulen besteht darin, dass einige der größeren Dateien in separate Dateien aufgeteilt werden können, die GLTFLoader als Abhängigkeiten importieren kann. Wie sollte das eingebaute globale Skript aussehen, wenn GLTFLoader von vier externen Dateien abhängt, von denen einige gemeinsam genutzt werden? Müssen Benutzer der erstellten globalen Skripte jetzt alle diese js-Beispieldateien einzeln einfügen? Oder werden einige Dateien gebündelt, was eine manuelle Pflege einer Liste von Dateien erfordern würde, die gebündelt werden können und welche nicht?

Ich denke, der einzige wirklich festgelegte und vergessene Fall besteht darin, alle js-Beispieldateien in einem einzigen monolithischen Blob zu bündeln, was ich nicht für vernünftig halte. Ich denke, bei jeder dieser Lösungen würde es auch einen anderen Freigabe- und Dokumentationsaufwand geben.

Vielleicht gibt es einen besseren Weg, aber als ich versuchte, einen Rollup-Build zu erstellen, der die Abwärtskompatibilität oder zumindest eine konsistente Struktur zu den vorhandenen js-Dateien beibehielt, sind dies die Probleme, auf die ich gestoßen bin.

Wenn ich das richtig verstehe, ist geplant, neben der "/build/three.module.js" noch eine "/build/three.js" einzufügen.

Jawohl. Ob dieser Ansatz jedoch sinnvoll ist, ist fraglich.
Wenn "examples/js" entfernt wird, bleiben nur noch wenige Anwendungsfälle übrig, in denen "three.js" und "three.min.js" noch nützlich sind.

@Mugen87 @mrdoob

Michael,
Tatsächlich ist es ein MUSS, "three.min.js" für mindestens 2 weitere Jahre zu behalten.
Nicht, weil alle meine Samples darauf basieren.
Sondern weil viele tausend Dateien und Google-Platzhirsche darauf basieren!
Beispiel: https://www.google.com/search?source=hp&q=webgl+benchmark

Andererseits bedeutet „three.min.js“ aus meiner Sicht schnelleres Entwickeln und Testen.
Ganz zu schweigen davon, dass es offline funktioniert und Sie keinen lokalen Host benötigen.
Legen Sie einfach alle Dateien irgendwo in einem Ordner ab, verwenden Sie Firefox und doppelklicken Sie auf die HTML-Datei.
Ich habe das immer für die Entwicklung geliebt!

An all das sollte auch Ricardo denken.
Prost

Die Entfernung von three.js und three.min.js kann diskutiert und geplant werden, wenn examples/js weg ist. Es war mir nur wichtig, den Bedeutungsverlust hervorzuheben, wenn man keine Dateien mehr von examples/js importieren kann.

Ich denke, die Komplexität der Aufrechterhaltung wird unterschätzt. Leider finde ich das mit der Art und Weise, wie Beispiele im Projekt aufgebaut werden, nicht so einfach.

Die Punkte, die Sie ansprechen, gefallen mir sehr gut. Es gibt absolut unvorhergesehene Komplexität beim Bündeln und das Beispiel von verschachtelten Modulen ist gut. Zu Ihrem Punkt denke ich, dass wir vernünftige Entscheidungen darüber treffen können, wie wir mit dem Bündeln verschachtelter Module umgehen, wenn diese Zeit gekommen ist. Ich sage nicht, dass ein Bundler-Skript ein Set-it-and-forget-it-Szenario sein wird, nur dass es weniger Wartung benötigt.

Wenn die Zeit kommt, in der es zu schwer zu warten ist, können wir es immer noch fallen lassen, aber ich denke, es ist dumm, den Versuch aufgrund von Problemen, die wir noch nicht haben, außer Acht zu lassen. Es ist jetzt am einfachsten zu implementieren, solange wir noch eine 1-zu-1-Parität zwischen /examples/jsm und example/js haben . Wir werden die Modulhierarchie /example/jsm wahrscheinlich nicht massiv neu organisieren, und ich denke, wir können inkrementelle Aktualisierungen am Bundler vornehmen, wenn wir dies tun. Ich werde weitermachen und anfangen, an einem Arbeitsnachweis dafür zu arbeiten (mit babel, weil es bereits hinzugefügt wurde?), um mein Geld dort einzusetzen, wo mein Mund ist, wie sie sagen.

Für Mugen würde dies dazu beitragen, eine gewisse Relevanz für three.js und three.min.js zu bewahren, während wir sie weiterhin pflegen. Es könnte auch Hunderten von Sites helfen, die nach einem Update suchen, das mit ihrer nicht modulbasierten THREE-Implementierung kompatibel ist. Das Refactoring eines DREI-Projekts zur Verwendung von Modulen kann ziemlich umfangreich sein, selbst wenn Sie wissen, was Sie tun.

Ich kann nicht für die anderen Mitarbeiter sprechen, aber ich werde meine Meinung zu diesem Thema nicht ändern. Ich stimme dafür, examples/js mit der Dezember-Veröffentlichung im Jahr 2020 zu löschen, wie hier besprochen und festgelegt #18749.

Ich stimme dafür, dass Beispiele/js mit der Dezember-Veröffentlichung im Jahr 2020 gelöscht werden, wie hier besprochen und festgelegt #18749.

Ich habe kein Problem damit.
Solange "three.min.js" noch ein paar Jahre verfügbar ist ...

Danke für den Input, Mugen, ich habe diesen Thread gelesen, aber es scheint eher eine Ankündigung als eine Erklärung für die Entscheidung zu sein. Meine Vermutung ist, dass diese vereinfachte Entwicklung der Hauptgrund dafür ist, in diese Richtung zu gehen, gibt es noch andere?

Ich denke, ein Transpilationsskript zu haben, das wir ausführen können, um /examples/js Style Includes zu generieren, sollte hier ein guter Kompromiss sein. Es sollte den hier erforderlichen Wartungs-/Komplikationsaufwand drastisch verringern. Ich wäre sogar in Ordnung, wenn es nur ein Befehl in der package.json wäre, den Sie selbst ausführen müssten und die Dateien nicht standardmäßig generiert würden. Es gibt Vorteile für einige Entwickler und andere, die sowieso transpilieren müssen. Ich würde es vorziehen, wenn wir nicht alle separat einen Transpilations-/Bündel-Workflow erstellen müssten, wenn etwas im Hauptrepo aufbewahrt werden könnte, um uns eine bessere Zusammenarbeit zu ermöglichen. :)

Ich habe diesen Thread gelesen, aber es scheint eher eine Ankündigung als eine Erklärung für die Entscheidung zu sein.

Leider können wir nicht immer alle stichhaltigen Argumente einem einzigen Thread zuordnen, entweder weil die Umsetzung einer Designänderung in mehreren Diskussionen im Laufe der Jahre langsam voranschreitet oder einfach weil immer wieder mehrere Threads zum selben Thema erstellt werden (wie dieser ). Mitarbeiter versuchen, Rauschen und Segmentierung zu minimieren, aber das ist nicht immer möglich.

Meine Vermutung ist, dass diese vereinfachte Entwicklung der Hauptgrund dafür ist, in diese Richtung zu gehen, gibt es noch andere?

Das größte Problem, das ich sehe, ist die Möglichkeit, Untermodule zu verwenden und zu importieren, die redundanten Code minimieren und wiederverwendbare Implementierungen ermöglichen.

Zum Beispiel müssen die meisten Loader eine Art Datenparsing-Struktur/Klasse erstellen, weil jeder Loader autark sein muss, damit example/js -Dateien wiederverwendbar sind. Wenn wir jedoch die nicht-modulare Einschränkung vollständig aufheben, könnten wir eine einzelne Instanz einer DataParser -Klasse erstellen und diese Standardimplementierung auf allen Loadern importieren, was die Entwicklung sofort vereinfacht und auch redundanten Code entfernt alle Lader.

Ja, guter Punkt. Wir müssen bereits schmutzige Hacks wie das Einbetten der Klasse Pass (der Basisklasse aller FX-Pässe) in EffectComposer machen, nur um sicherzustellen, dass der alte Code nicht beschädigt wird.

sehr gute Punkte rundum gemacht.

Leute auf Kurs/auf dem Laufenden zu halten und auf dem Laufenden zu halten, klingt (und aus meiner eigenen Erfahrung) nach einer schwierigen Angelegenheit. werde versuchen, darüber nachzudenken.

Tatsächlich ist es ein MUSS, "three.min.js" für mindestens 2 weitere Jahre zu behalten.

Es wird immer möglich sein, einen ES5-Build mit Babel zu generieren. Die Frage, die wir dabei beantworten müssen, ist, ob die Verantwortung dafür bei uns liegt oder beim Entwickler, der three.js verwendet.

Wir haben bereits entschieden, dass es Sache des Entwicklers ist, ES5-Versionen der Beispieldateien zu erstellen, daher ist es wahrscheinlich sinnvoll, dasselbe für Build-Dateien zu tun. Meiner Meinung nach ist es auch sinnvoll, dies über die gesamte Bibliothek in einer Version zu tun, anstatt es zu verteilen, aber es ist auch in Ordnung, three.min.js etwas länger herumzuhalten.

Sondern weil viele tausend Dateien und Google-Platzhirsche darauf basieren!
Beispiel: google.com/search?source=hp&q=webgl+benchmark

Dies ist die Top-Site, die mir bei dieser Suche angezeigt wird, und sie verwenden R53, daher glaube ich nicht, dass diese Änderung sie allzu sehr beeinträchtigen wird: https://www.wirple.com/bmark/

Wie Sie sehen können, funktionieren alte Versionen von three.js immer noch einwandfrei. Nachdem wir den Übergang zu Modulen vollzogen haben, können wir jeden, der einen ES5-Build ohne Babel haben möchte, anweisen, die letzte Version zu verwenden, bevor wir die ES5-Dateien entfernt haben. Sie können das gesamte Repo dieser Version auschecken und auch die Dokumente dieser Version verwenden.

@looeee Du sprichst einige gute Punkte an. Wie oben erwähnt, stimme ich zu, dass es sinnvoll ist, den ES5 three.min.js und three.js gleichzeitig hier abzulehnen. Vielleicht sollte das eine eigene separate Diskussion sein?

So oder so würde ich gerne einen Konsens darüber erzielen, ein Babel-Skript in das Haupt-Repo aufzunehmen, das verwendet werden kann, um /js/example -Dateien im ES5-Stil der alten Schule zu generieren. Hier geht es in keiner Weise darum, ob jemand für die Bereitstellung dieser Unterstützung verantwortlich ist. Es gibt Mitwirkende wie mich, die diese Funktion benötigen werden. Es gibt Vorteile für einige Entwickler und andere, die sowieso transpilieren müssen. Ich würde es vorziehen, wenn wir nicht alle separat einen Transpilations-/Bündel-Workflow erstellen müssten, wenn etwas im Hauptrepo aufbewahrt werden könnte, um uns eine bessere Zusammenarbeit zu ermöglichen.

Ich denke, es ist ein fairer Kompromiss, uns eine Datei im Hauptrepo zu erlauben, damit wir gemeinsam am Transpiler-Skript von babel ES6 zu ES5 arbeiten können. Gibt es da wirklich ein Problem? Mitwirkenden erlauben, gemeinsam an einem Feature zu arbeiten, das sie im Hauptrepo benötigen?

Ich bitte Mitarbeiter nicht um Hilfe oder Ressourcen, um dies zu tun, ich bitte Sie lediglich darum, dass Personen, die dies benötigen, im Hauptrepo gemeinsam daran arbeiten können. Wenn ich eine PR dafür mache und es funktioniert, würden Sie wirklich dafür stimmen, es abzulehnen?

Wenn ich eine PR dafür mache und es funktioniert

Ich meine, ich freue mich, dass das losgeht

Würden Sie wirklich dafür stimmen, es abzulehnen?

Alle Wetten sind ungültig, wenn der Linting Pass fehlschlägt 😂

Gibt es da wirklich ein Problem?

Ja, da das Repository veraltete Codierungsmuster nicht fördern sollte.

Ja, da das Repository veraltete Codierungsmuster nicht fördern sollte.

Es ist noch nicht offiziell veraltet, wenn wir three.js + three.min.js nicht entlassen (anerkannter ITT-Konsens, dass wir diese auch entlassen sollten) und ein Babel-Skript haben, das Sie manuell selbst ausführen müssen kaum eine glühende Bestätigung. Ich stimme zu, dass wir die Leute auf jeden Fall ermutigen sollten, stattdessen Module zu verwenden, und eine Warnung im babel-Skript und den generierten Dateien darüber haben sollten. Ich bin dagegen, dass es Mitwirkenden erlaubt wird, gemeinsam an einem babel-Skript für Leute in Situationen zu arbeiten, in denen Module aus irgendeinem Grund nicht verwendet werden können, was ein veraltetes Codierungsmuster fördert. Hauptsächlich, weil es immer noch Situationen gibt, in denen die Verwendung von Modulen nicht möglich/unpraktisch ist. Die Dokumente erkennen diese Notwendigkeit an. Ich denke, wir können sicher eine Datei für die Leute hinzufügen, die sie brauchen, um gemeinsam daran zu arbeiten.

Ich stimme zu, dass es sinnvoll ist, den ES5 three.min.js und three.js hier gleichzeitig abzulehnen.

Ich meinte, wir sollten example/js, three.min.js und three.js gleichzeitig verwerfen, dh den gesamten ES5-Code in einer Version entfernen, anstatt ihn auf mehrere Versionen zu verteilen.

@Mugen87

Ja, da das Repository veraltete Codierungsmuster nicht fördern sollte.

Sie können weiterhin DOS-Spiele in Windows 10 ausführen.
Und das bedeutet nicht, dass Microsoft „veraltete Codierungsmuster“ fördert.

Nur um die js-Beispielmodule, wie sie in diesem Projekt verwaltet werden, zu verdeutlichen, benötigen Sie keinen Knoten, npm oder ein Build-Framework.

Vergessen wir nicht, dass das Erstellen einer produktionsreifen Anwendung das Bündeln Ihres Codes bedeutet :)

Ich schätze die verfügbaren Bündelungstools wie Rollup, denke aber, dass wir uns ein paar Fragen stellen sollten:

  • Ist es fair anzunehmen, dass Entwickler, wenn sie THREE in der Produktion verwenden möchten, auch eines dieser Bündelungstools verwenden müssen?
  • Ist es fair, die Unterstützung für andere Bibliotheken einzustellen, die auf Updates für ES5/UMD-Module im Beispielordner angewiesen sind?

Meine persönliche Meinung dazu:

Diese Bibliothek ist ein Jahrzehnt alt. Es gibt ein riesiges Ökosystem da draußen, das sich auf die Module im Beispielordner stützt, die in ES5/UMD geschrieben wurden. Ich denke nicht, dass es fair ist, die Unterstützung für ein ganzes Ökosystem einzustellen.

Ich denke, die Leute vergessen, dass Sie ES6 immer noch ohne Modulbündelungsmuster verwenden können. Ich verwende ES6 jeden Tag, verwende aber keine Modulbündelungsmuster in meinen Frontend-Anwendungen. Ich habe in Enterprise-Shops gearbeitet, in denen Build-Tools zwangsläufig sehr benutzerdefiniert wurden und kein Modulbündelungsmuster integrieren konnten.

Was sollen wir machen?

Lassen Sie uns die ES6-Module nach jeder Veröffentlichung in ES5/UMD-Module für eine bestimmte Distribution kompilieren.

Ja, da das Repository veraltete Codierungsmuster nicht fördern sollte.

Für fast alles im Leben kann eine Lösung mit älteren Mustern, Techniken und Werkzeugen immer noch von großer Qualität sein.

Als Analogie - In meiner Freizeit schnitze ich gerne Stein mit Spitzmeißeln. Die Werkzeuge und Techniken unterscheiden sich von Elektrowerkzeugen, aber am Ende wird die Skulptur immer noch von hoher Qualität sein. Ich habe eine persönliche Vorliebe für die Verwendung von Spitzmeißeln ausgeübt, weil ich sie gerne verwende und über die erforderlichen Fähigkeiten verfüge, um etwas herzustellen, mit dem ich selbst oder andere zufrieden sind.

Das Gleiche sehe ich bei ES5/UMD-Modulen. Ich konnte Muster, Techniken und Tools finden, die wirklich hochwertige Codebasen aufrechterhalten, und möchte diese persönliche Präferenz weiterhin ausüben.

Lassen Sie uns die ES6-Module nach jeder Veröffentlichung in ES5/UMD-Module für eine bestimmte Distribution kompilieren.

Ich stimme dem zu, was Loeee gesagt hat.

Ist es fair anzunehmen, [...]

was? Wir sprechen darüber, welchen Ansatz wir bevorzugen würden, die „Annahme“ kommt danach. Die Präferenz scheint darin zu liegen, andere zu ermutigen, Module zu verwenden, aber (vorausgesetzt, einige Leute werden immer noch die alten DREI wollen) einen Weg für diejenigen anzubieten, die es wirklich wollen.

Lassen Sie uns die ES6-Module nach jeder Veröffentlichung in ES5/UMD-Module für eine bestimmte Distribution kompilieren.

Dies kann von jedem durchgeführt werden; diese Kosten müssen nicht von den Betreuern von three.js getragen werden. Ich möchte wiederholen, was @gkjohnson oben gesagt hat, die Kosten für die Verwaltung der Verzeichnisse examples/js und examples/jsm sind hoch. Wir können dies nicht unbegrenzt tun, und es ist klar, dass ES6-Module der modernere der beiden Ansätze sind. Berücksichtigen Sie die folgenden Kosten:

  • Erstellen und Pflegen der Automatisierung
  • Debuggen von Release-Fehlern, wenn die Automatisierung unterbrochen wird
  • Sicherstellen, dass alle Pull-Requests die Quelldatei aktualisieren, nicht die generierte
  • Pflegen der Dokumentation, die erklärt, wie beide Workflows verwendet werden
  • Beantwortung von Fehlerberichten und Supportfragen von Benutzern, die versuchen, sowohl CJS- als auch ES6-Workflows zu verwenden

Das letzte Element ist wahrscheinlich das größte. Solange zwei Kopien von allem in diesem Repository verfügbar sind, werden beide als vollständig unterstützt angesehen. Wir verbringen regelmäßig Zeit damit, Benutzern zu helfen, die die beiden Workflows verwechseln oder versuchen, einen ES6-Modullader mit der CJS-Kernbibliothek zu verwenden, was auf komplizierte Weise fehlschlägt.

Wir können das Problem einfach umformulieren: Alle unsere Beispiele – die wichtige, aber optionale Teile der Bibliothek three.js sind – verwenden derzeit überhaupt keine Modulsyntax. Nicht UMD, nicht CommonJS, nicht ES6-Module. Sie patchen einfach einen globalen Namensraum THREE . Wir würden das gerne aktualisieren und stattdessen die ES6-Import/Export-Syntax verwenden, und es gab viele Frühwarnungen, dass diese Änderung geplant war.

Es gibt ein riesiges Ökosystem da draußen, das sich auf die Module im Beispielordner stützt, die in ES5/UMD geschrieben wurden. Ich denke nicht, dass es fair ist, die Unterstützung für ein ganzes Ökosystem einzustellen.

Ich denke nicht, dass es fair ist zu sagen, dass irgendetwas im three.js-Ökosystem so abhängig von globalen THREE.* -Namespaces ist, dass es nicht aktualisiert werden könnte, um die Import/Export-Syntax zu verwenden oder auf ES5 zu transpilieren, oder einen Bundler zu verwenden. Hier gibt es eine Reihe von Problemumgehungen, und wir würden uns freuen, mit Benutzern zusammenzuarbeiten, um ihnen zu helfen, eine geeignete Option für sie zu finden.

Die Kosten für die Pflege der Verzeichnisse "examples/js" und "examples/jsm" sind hoch.

Darauf möchte ich noch etwas eingehen. Ich habe viele benutzerdefinierte Tools geschrieben und Automatisierungsskripte für Front-End-Anwendungen erstellt und würde mich freuen, Ihnen auf jede erdenkliche Weise zu helfen.

Erstellen und Pflegen der Automatisierung
Debuggen von Release-Fehlern, wenn die Automatisierung unterbrochen wird

Helfen Sie mir, die Wartungssteuer etwas besser zu verstehen. Ist dies etwas Einzigartiges für die Codebasis THREE? Meiner Erfahrung nach ist diese Art von Code normalerweise am langlebigsten und benötigt am wenigsten Wartung. Dies sind Skripte, die Sie einmal schreiben und die Sie sich lange Zeit nicht mehr ansehen.

Sicherstellen, dass alle Pull-Requests die Quelldatei aktualisieren, nicht die generierte

Vielleicht könnte ein kleines Skript oder ein Test im Release-Workflow dabei helfen.

Pflegen der Dokumentation, die erklärt, wie beide Workflows verwendet werden

Ich würde auch dafür stimmen, die Dokumentation für globale Namespaces fallen zu lassen. Ich finde es albern, die Dokumentation für zwei Workflows zu unterstützen. Das ist keine schlechte Sache. Die meisten Bibliotheken, die ihren Code für verschiedene Kontexte bündeln, UMD/ES6-Module haben nur einen Satz von Dokumenten.

Beantwortung von Fehlerberichten und Supportfragen von Benutzern, die versuchen, sowohl CJS- als auch ES6-Workflows zu verwenden.

Ich denke, die Anzahl der Probleme im Zusammenhang mit so etwas hängt von der Größe der Popularität von THREE ab. Sie und ich sehen diese Art von Problemen ständig bei Stack Overflow. Ein Benutzer, der nicht zwischen den beiden Workflows unterscheiden kann, ist wahrscheinlich ein neuer Programmierer, der von der Bibliothek inspiriert wurde, und versucht nur, die Grundlagen der Programmierung im Allgemeinen zu erlernen.

Wenn das Ziel darin besteht, die Anzahl der Probleme zu reduzieren, die speziell mit der Verwechslung zwischen den beiden Workflows zusammenhängen, würde das Entfernen des ES5-Codes wahrscheinlich dazu beitragen - aber ich bezweifle, dass sich die Anzahl der Probleme insgesamt ändern wird. Ein neuer Programmierer wird immer bei der nächsten Frage stecken bleiben, die sich auf die Bibliothek beziehen kann oder auch nicht.

Wie kann man das Problemvolumen insgesamt reduzieren?

Wenn das eigentliche Ziel darin besteht, das Volumen der Issues insgesamt zu reduzieren, können strengere Issue-Richtlinien dabei helfen. Ich sehe, dass ihr großartige Arbeit leistet, indem ihr bereits Tags wie Help (please use the forum) verwendet, aber vielleicht muss es mehr von diesen Dingen geben.

Im Allgemeinen ist es vielleicht am besten, nur einige Arten von Themen herauszufiltern, die die DREI Mitwirkenden bereit sind zu diskutieren und zu untersuchen, wenn sie sich derzeit von der Gesamtmenge überwältigt fühlen.

Paar Ideen:

  • Zum Zeitpunkt des Verfassens dieses Artikels haben suggestions und enhancements (271) offene Probleme. Diese Etiketten scheinen viel Lärm zu erzeugen. Vielleicht nur PR bereit nehmen/überprüft als eigentlichen Vorschlag bestanden. Schließen Sie alles andere sofort und markieren Sie es als Discussion (please use the forum) .
  • Zum Zeitpunkt des Verfassens dieses Artikels haben loaders (61) offene Probleme. Dieses Etikett scheint auch viel Lärm zu erzeugen. Ich sehe viele Probleme mit diesem Label im Zusammenhang mit suggestions und enhancements oder schlecht formulierten Fehlerberichten. Nehmen Sie vielleicht nur gut formulierte Fehlerberichte und PR bereit / Überprüfungen auf Vorschläge bestanden. Alles andere sofort schließen und entsprechend markieren.

Ich denke nicht, dass es fair ist zu sagen, dass irgendetwas im three.js-Ökosystem so abhängig von globalen THREE.*-Namespaces ist, dass es nicht aktualisiert werden könnte, um die Import/Export-Syntax zu verwenden, auf ES5 zu transpilieren oder a Bündler.

Ich stimme zu, dass alles aktualisiert werden kann, aber wenn wir einen Weg finden können, ein wenig Arbeit zu leisten, um diese Benutzer weiterhin nachhaltig zu unterstützen, stimme ich @Bug-Reaper zu, wenn ich sage:

Ich würde es vorziehen, wenn wir nicht alle separat einen Transpilations-/Bündel-Workflow erstellen müssten, wenn etwas im Hauptrepo aufbewahrt werden könnte, um uns eine bessere Zusammenarbeit zu ermöglichen.

Wir würden diesen Benutzern gemeinsam eine enorme Zeitersparnis beim Aktualisieren ihrer Anwendungen/Bibliotheken, Build-Systeme und Dokumentationen ersparen.

Darauf möchte ich noch etwas eingehen. Ich habe viele benutzerdefinierte Tools geschrieben und Automatisierungsskripte für Front-End-Anwendungen erstellt und würde mich freuen, Ihnen auf jede erdenkliche Weise zu helfen.

gut.

Wie kann man das Problemvolumen insgesamt reduzieren?

Lassen Sie uns das bitte auf dem Laufenden halten. Gerne in einem anderen Thread weiter diskutieren. Es bezieht sich etwas auf meinen früheren Kommentar .

Ich stimme @Bug-Reaper zu, wenn ich sage:

Mir wäre es lieber, wir alle hätten keinen Transpilations-/Bündel-Workflow [...]

Ich denke, da sind wir uns alle einig.

Vielen Dank an alle für das Teilen der Vor- und Nachteile. Es ist immer gut, diese zu teilen, um sicherzustellen, dass wir fundierte Entscheidungen treffen.

Das ist etwas, wofür ich dieses Jahr einige Gehirnzyklen aufgewendet habe, und ich habe sogar Browser-Anbieter nach ihren Prioritäten gefragt, damit ich vorausplanen konnte.

Ich stimme zu, dass ES6-Module die Zukunft sind, aber die Entwicklung mit ihnen ohne Importkarten kann große Kopfschmerzen verursachen und Ihren Fluss vollständig unterbrechen. Als wir uns entschieden haben, examples/js , hatte ich gehofft, dass Import Maps mehr Zugkraft haben würde, aber es scheint, dass es derzeit keine Priorität für Browser hat.

Aus diesem Grund habe ich mich entschieden, die Einstellung des examples/js -Ordners auszusetzen, bis Browser Import-Maps implementieren. Ich würde es hassen, Neulinge dazu zu zwingen, etwas über Polyfills oder Bundler zu lernen, um ihren ersten Cube zu rendern.

Ich bin zum gleichen Schluss gekommen wie @Bug-Reaper. Heute schaue ich mir an, wie man ein Skript erstellt, das examples/js aus examples/jsm -Dateien erstellt.

@mrdoob

Ich habe mich entschieden, die Einstellung des Ordners "examples/js" auszusetzen, bis die Browser Import-Maps implementieren.
Ich bin zum gleichen Schluss gekommen wie @Bug-Reaper. Heute schaue ich mir an, wie man ein Skript erstellt, das Beispiele/Js aus Beispielen/JSM-Dateien erstellt.

Eine weise Entscheidung.
👍

@mrdoob Ich akzeptiere natürlich deine Entscheidung, aber ich denke, es ist eine verpasste Gelegenheit. Früher oder später werden sich Entwickler von globalen Skripten verabschieden müssen. Und ich glaube nicht, dass Import Maps hier einen großen Unterschied machen wird. Anstatt Benutzer zu besseren und zukunftssicheren Arbeitsabläufen zu „zwingen“, erlauben wir ihnen, weiterhin globale Skripte zu verwenden. Im Jahr 2020.

Und ich glaube nicht, dass Import Maps hier einen großen Unterschied machen wird.

Neulich sah ich jemanden, der dies tat:

<script src="js/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/GLTFLoader.js"></script>
<script type="module" src="js/main.js"></script>

Und innerhalb main.js taten sie Folgendes:

import {OrbitControls} from "https://threejsfundamentals.org/threejs/resources/threejs/r119/examples/jsm/controls/OrbitControls.js";

Und das Ding hat tatsächlich funktioniert... 😐

Wir können nicht einfach erwarten, dass Benutzer das Richtige tun, sie lernen und probieren Dinge aus, bis etwas funktioniert. Die Herausforderung besteht darin, ein Design zu finden, das ihnen hilft, das Richtige zu tun, ohne dass sie es merken.

Das Problem mit ES6-Modulen ohne Importzuordnungen besteht darin, dass der Benutzer nicht einfach OrbitControls.js in einen /js -Ordner in seinem eigenen Projekt kopieren und wie gewohnt importieren kann. Es funktioniert nicht, weil OrbitControls.js nach ../../build/three.module.js $ sucht.

Beim Importieren von Karten würde OrbitControls.js nur aus three importieren. Der Benutzer kann die Datei kopieren, wo immer er möchte, und dann den Pfad in der Importkarte anpassen.

Karten importieren bringt uns näher an die Leichtigkeit des Importierens von Dateien wie in den "alten" Tagen. Es wird nicht mehr so ​​einfach wie bisher, aber zumindest muss sich der Benutzer beim Importieren von Dateien nicht mehr um die Reihenfolge kümmern. Etwas gewinnen, etwas verlieren.

Einverstanden, dass der Import von Karten den Import konfigurierbar und damit flexibler macht. Allerdings muss der Benutzer die Importkarte noch anpassen (und damit verstehen, was sie eigentlich ist).

Ich denke nur, dass das ganze "Kopieren von JS-Dateien in einen Ordner" ein böses Anti-Pattern ist, und ich hatte gehofft, wir könnten dies verhindern, indem wir neuen Benutzern / Anfängern empfehlen, mit CDN-Importen zu arbeiten (was auch eine Option für Entwickler ist, die nicht Build aus welchen Gründen auch immer nicht verwenden möchten). Richtige Apps (sollten) sowieso Build-Tools verwenden.

Ich sehe es nicht wirklich als Anti-Pattern.

So habe ich gelernt, Websites zu erstellen. Man würde die .css Dateien in den /css Ordner legen, dann die Bilder in /img und die .js Dateien in /js .

In den letzten Monaten habe ich einige Experimente mit dem ES6-Module/CDN-Ansatz durchgeführt, und es fühlt sich für mich nicht gut an, dass die Bibliotheken aus einer anderen Domäne stammen als meinem Projekt.

Eine große Sache, die wir verlieren, wenn wir keine Dateien kopieren, ist die Möglichkeit, sie zu bearbeiten. Die Dateien in examples/js sollten immer Beispiele sein, auf denen man aufbauen kann. Wenn ich OrbitControls.js in mein Projekt kopiert habe und es nicht genau das tat, was ich brauchte, konnte ich es einfach ändern, weil es nur eine lokale Datei war.

So habe ich meine Projekte eingerichtet:

<script src="js/libs/three.js"></script>
<script src="js/libs/three/OBJLoader.js"></script>
<script src="js/libs/three/OrbitControls.js"></script>
<script>
    console.log( THREE, THREE.OBJLoader, THREE.OrbitControls );
</script>

Mit Importkarten würde es so aussehen:

<script type="importmap">
{
  "imports": {
    "three": "js/libs/three.module.js",
    "OBJLoader": "js/libs/three/OBJLoader.js",
    "OrbitControls": "js/libs/three/OrbitControls.js"
  }
}
</script>
<script type="module">
    import * as THREE from 'three';
    import { OBJLoader } from 'OBJLoader';
    import { OrbitControls } from 'OrbitControls';

    console.log( THREE, OBJLoader, OrbitControls );
</script>

Nicht so hübsch wie vorher, kümmert sich aber um Importabhängigkeiten/-reihenfolge und benötigt keinen Bundler.

Dennoch funktioniert es immer noch für Leute, die Bundle-basierte Entwicklung betreiben. Tatsächlich macht es es für sie besser, weil die Addons jetzt von three statt von ../../build/three.module.js importieren.

Und das Ding hat tatsächlich funktioniert... 😐

FWIW scheint dies nur in wenigen Fällen tatsächlich zu funktionieren. Wenn es nicht funktioniert, schlägt es auf äußerst verwirrende Weise fehl, und wir haben mehrere diesbezügliche Probleme gemeldet, die zugegebenermaßen auch bei Build-Prozessen auftreten. Wenn Sie sich Sorgen darüber machen, dass der Neuling ihm mehrere Möglichkeiten zur Verwendung derselben Dateien bietet, ist dies wohl fehleranfälliger und verwirrender.

Vielleicht tangential, aber es könnte sich lohnen, die Leute darüber zu informieren, dass sie zwei Kopien von three.js in der Seite über eine Warnung in der Konsole enthalten haben (auch wenn es sich um dieselbe Version handelt), was zu Problemen führen kann, wenn nicht darauf geachtet wird, sie nicht zu mischen. ~Ich glaube, React tut dies aus ähnlichen Gründen~ React kann tatsächlich nur darauf als mögliche Fehlerquelle hinweisen. Das könnte am wenigsten dazu beitragen, Menschen davon abzuhalten, diese Modalitäten beim Lernen zu mischen.

Ich bin zum gleichen Schluss gekommen wie @Bug-Reaper. Heute schaue ich mir an, wie man ein Skript erstellt, das Beispiele/Js aus Beispielen/JSM-Dateien erstellt.

Wenn dies der neue Plan ist, würde ich gerne helfen, # 15526 / # 15543 (die jetzt aus dem Projekt gelöscht wurden) wiederzubeleben, die jede Moduldatei zu einer ES6-Datei erstellen. Angesichts der Tatsache, dass einige Beispiele auf so viele Dateien verteilt sind (z. B. Shader-Knoten) und wir möglicherweise daran interessiert sind, einige der Module in mehrere Dateien aufzuteilen, lohnt es sich wahrscheinlich, das Rollup-Skript zu aktualisieren, um eine explizite Liste von Dateien zu erstellen, die wir konvertieren möchten und Ausgabe. Wir sollten auch in der Lage sein, automatisch Abhängigkeiten zwischen den ausgegebenen Dateien zu erstellen.

Eine große Sache, die wir verlieren, wenn wir keine Dateien kopieren, ist die Möglichkeit, sie zu bearbeiten

Ich stimme zu, obwohl ich, wenn wir überall zum Unterricht kommen können, auf etwas hoffen würde wie:

import orbitalcontrols from  orbitalcontrolsURL

class mycontrols extends orbitalcontrols {
// do the edits I care about
}

und dann später

let controls = new myorbitalcontrols

Eine große Sache, die wir verlieren, wenn wir keine Dateien kopieren, ist die Möglichkeit, sie zu bearbeiten

Ich stimme zu, obwohl ich, wenn wir überall zum Unterricht kommen können, auf etwas hoffen würde wie:

orbitalcontrols aus orbitalcontrolsURL importieren

Klasse mycontrols orbitalcontrols erweitern {
// mache die Bearbeitungen, die mir wichtig sind
}

und dann später

Steuerelemente lassen = neue myorbitale Steuerelemente

Sie können das bereits tun ... auch wenn die übergeordnete "Klasse" eine einfache js-Funktion ist!

Code funktioniert tatsächlich (in einem Debugger-Schnelltest):

Promise.all([
    import('https://unpkg.com/three/build/three.module.js')
        .then( mod=> [mod.Camera, mod.WebGLRenderer] ),
    import('https://unpkg.com/three/examples/jsm/controls/OrbitControls.js')
        .then( mod=> mod.OrbitControls )
])
.then( ([
    [ Camera, WebGLRenderer ],
    OrbitControls
])=> new ( class extends OrbitControls {} )( new Camera, (new WebGLRenderer).domElement )
)
.then( console.log )

... oder einfachere Syntax:

(async function() {

let { Camera, WebGLRenderer } = await import('https://unpkg.com/three/build/three.module.js')
,   { OrbitControls } = await import('https://unpkg.com/three/examples/jsm/controls/OrbitControls.js')

class Con extends OrbitControls { }

let my = new Con( new Camera, (new WebGLRenderer).domElement )
console.log( my )

})()

Abgesehen von dieser Aynom-Funktion und der Sorge um async/await-Versprechen, cool

class mycontrols extend orbitalcontrols {
 // do the edits I care about
 }

Idealerweise ist dies das Muster, das wir fördern sollten, anstatt den Benutzern zu sagen, dass sie die Originaldateien bearbeiten sollen, wenn sie Änderungen vornehmen. Die Beispiele wurden jedoch nicht im Hinblick auf Erweiterbarkeit geschrieben, sodass dem, was Sie erreichen können, starke Grenzen gesetzt sind. Meiner Erfahrung nach müssen Sie am Ende das gesamte ursprüngliche Beispiel in den Konstruktor der erweiterten Klasse kopieren, damit es funktioniert, sodass es keinen Sinn macht, extend zu verwenden.

Die am häufigsten angeforderte Änderung für OrbitControls ist beispielsweise die Begrenzung des Schwenkbereichs . Dies ist leicht zu bewerkstelligen, wie in der Geige von @ Mugen87 aus diesem Thread gezeigt wird.

Kurz gesagt, Sie fügen die Vektoren minPan und maxPan hinzu und klemmen controls.target in die Methode controls.update .

Ich habe das versucht, indem ich OrbitControls verlängert habe. Sie können eine erweiterte Klasse erstellen, und es funktioniert gut. Probleme werden jedoch offensichtlich, wenn Sie beginnen, Änderungen vorzunehmen. Sie können die Methode update nicht einfach erweitern:

class OrbitControlsPanLimit extends OrbitControls {
    constructor(object, domElement) {
        super(object, domElement);
    }

    update() {
        super.update();
        console.log('Custom update function');
    }
}

Diese erweiterte Klasse funktioniert ( Glitch ), aber diese neue OrbitControlsPanLimit.update Methode wird ignoriert. Die ursprüngliche Methode OrbitControls.update wird weiterhin verwendet.

Sie können es überschreiben, indem Sie es im Konstruktor neu definieren:

class OrbitControlsPanLimit extends OrbitControls {
    constructor(object, domElement) {
        super(object, domElement);

        this.update = () => {
            console.log('Custom update function');
        }
    }
}

Sie können hier nicht super.update() verwenden, daher besteht die einzige Möglichkeit darin, die gesamte ursprüngliche Aktualisierungsmethode zu kopieren. Diese Methode stützt sich jedoch auf viele dieser Dinge aus OrbitControls , die von allen Methoden gemeinsam genutzt werden.

    //
    // internals
    //

    var scope = this;

    var changeEvent = { type: 'change' };
    var startEvent = { type: 'start' };
    var endEvent = { type: 'end' };

    var STATE = {
        NONE: - 1,
        ROTATE: 0,
        DOLLY: 1,
        PAN: 2,
        TOUCH_ROTATE: 3,
        TOUCH_PAN: 4,
        TOUCH_DOLLY_PAN: 5,
        TOUCH_DOLLY_ROTATE: 6
    };

    var state = STATE.NONE;

    var EPS = 0.000001;

    // current position in spherical coordinates
    var spherical = new THREE.Spherical();
    var sphericalDelta = new THREE.Spherical();

    var scale = 1;
    var panOffset = new THREE.Vector3();
    var zoomChanged = false;

    var rotateStart = new THREE.Vector2();
    var rotateEnd = new THREE.Vector2();
    var rotateDelta = new THREE.Vector2();

    var panStart = new THREE.Vector2();
    var panEnd = new THREE.Vector2();
    var panDelta = new THREE.Vector2();

    var dollyStart = new THREE.Vector2();
    var dollyEnd = new THREE.Vector2();
    var dollyDelta = new THREE.Vector2();

Das Endergebnis ist, dass Sie fast das gesamte ursprüngliche OrbitControls in den OrbitControlsPanLimit -Konstruktor kopieren müssen, was den Zweck der Erweiterung der Klasse zunichte macht. Wenn wir die Steuerelemente nicht als Klasse mit Blick auf die Erweiterbarkeit schreiben, halte ich eine Erweiterung für nicht praktikabel.

danke @looeee , dass du dich da eingemischt hast. Ich dachte, ich hätte bei meinen eigenen Bemühungen vielleicht eine einfache Lösung verpasst, aber jetzt, wo Sie es erwähnen, bin ich so ziemlich zu mir selbst gekommen.

Idealerweise ist dies das Muster, das wir fördern sollten, anstatt den Benutzern zu sagen, dass sie die Originaldateien bearbeiten sollen, wenn sie Änderungen vornehmen.

Vorsicht, das nähert sich einem Argument zwischen Vererbung und Komposition.

Idealerweise sollte eine Bibliothek keine Muster fördern. Es sollte seine Funktionen fördern und wie es darauf abzielt, Ihre Probleme zu lösen.

Es sollte auch nicht von einem Workflow, Stack, Build-System oder Anwendungsfall eines Entwicklers ausgehen. Eine großartige Bibliothek ist den vielen komplexen Bedürfnissen ihrer Gemeinschaft so entgegenkommend wie möglich.

Was heute neu ist, ist morgen alt, Muster kommen und gehen. Die einzige Konstante wäre dann eine Software, die die vielen Anwendungsfälle auf dem Weg dorthin großartig unterstützt, um so viel Abwärtskompatibilität wie möglich zu erhalten.

Sie können weiterhin DOS-Spiele in Windows 10 ausführen.

Vererbung vs Kompositionsargument

bitte nicht. Die Lösung für dieses „Argument“ besteht darin, das beste Werkzeug für die jeweilige Aufgabe zu verwenden. es gibt einen Platz für Vererbung, Komposition, Funktion, Test-Driven... was auch immer.

Da wir darüber sprechen, wie andere Entwickler three.js verwenden (verwenden, wiederverwenden, modifizieren), ist es gültig, ein Muster zu fördern, das leicht verständlich und verwendbar ist, ohne die Funktionen des js-Browsers zu verlassen.

Förderung bedeutet nicht, dass man nicht einen anderen Stil verwenden kann.

so viel Abwärtskompatibilität wie möglich

Ja und nein.

Es sollte seine Funktionen fördern und wie es darauf abzielt, Ihre Probleme zu lösen

Vielleicht, damit wir klar sind, was ist das Problem/Feature-Set für Sie?

Es sollte auch nicht von einem Workflow, Stack, Build-System oder Anwendungsfall eines Entwicklers ausgehen

Ich stimme größtenteils zu. Der Anwendungsfall von threejs ist derzeit der Browser. Der Vorbehalt ist, dass einige unserer Lader für einige Knotenanwendungen nützlich sind, wie ich gehört habe.

Die einzige Konstante wäre dann eine Software, die die vielen Anwendungsfälle auf dem Weg dorthin großartig unterstützt

Veränderung ist die einzige Konstante. Entwickler verwenden das Tool, das sie mögen, und manchmal probieren wir andere Dinge aus.

nebenbei:

Es sollte seine Funktionen fördern und wie es darauf abzielt, Ihre Probleme zu lösen

was war zuerst da? das Merkmal, das Muster oder das Problem?
sicherlich hat das Muster geholfen, das Problem zu lösen, und wurde dann zu einem Feature
...oder war es das Feature, das das Problem verursachte und wir ein Muster gefunden haben, um es zu lösen?

was war zuerst da? das Merkmal, das Muster oder das Problem?

Was war zuerst da? Die Henne oder das Ei?
Manche Leute sagen, der Hahn ...

Tolle Diskussion rundherum, vielen Dank an alle für den Input.

Ich wäre gespannt, was ihr darüber denkt, welcher Bundler ( Rollup, Babel, Paket, Webpack usw. ) am besten für die Aufgabe geeignet ist, unsere ES6-Beispielmodule zu transpilieren. Ich glaube, @gigablox hat erwähnt, hier Erfahrung zu haben, und ich bin mir sicher, dass andere dies auch tun.

Das aktuelle Repo enthält bereits babel, rollup und ein paar verwandte Plugins. Ich habe heute Abend angefangen, daran herumzuhacken, und ich habe ein extrem grobes Rollup-Konfigurationsskript zum Teilen:

// jsm-transpiler.js
export default [
  {
    input: './examples/jsm/controls/OrbitControls.js',
    output: {
      banner:"//warning this file was generated automatically",
      file: './examples/js/controls/OrbitControls.js',
      name:'OC',
      footer:'THREE["OrbitControls"]=OC.OrbitControls',
      format: 'umd'
    }
  }
];

Dieses Rollup-Konfigurationsskript konvertiert tatsächlich das OrbitControls -Modul in eine .js -Datei, die kein Modul ist, und weist THREE.OribitControls den entsprechenden Konstruktor zu. Es hat funktioniert, was cool ist :) ! Es hat auch die 40.000 Zeilen von THREE.js in die Ausgabedatei gebündelt, nicht so cool, haha. Ich verschmutze auch faul den globalen Variablenraum, indem ich eine zwischengeschaltete globale Variable namens OC deklariere, um den Transport des OrbitControls-Konstruktors auf DREI zu unterstützen.

Rollup scheint einige wirklich coole Funktionen zu haben, von denen ich denke, dass sie viele unserer Probleme lösen können. Insbesondere Mapping und andere Steuerelemente, um sicherzustellen, dass die richtigen verschachtelten Module eingeschlossen/ausgeschlossen werden. Die Möglichkeit, Code vor und nach der transpilierten Nutzlast über Header-/Footer-/Intro-/Output-Eigenschaften einzufügen.

Ich bin vorsichtig optimistisch, dass wir mit einem ausgeklügelten Rollup-Konfigurationsskript erreichen können, was wir brauchen. Aber es wäre großartig, wenn jemand, der die Unterschiede zwischen den vielen Bundlern recherchiert hat / versteht, sich hier einbringen könnte. Wir brauchen etwas ziemlich Robustes, um mit Modulen umzugehen, wenn sie fantastischer werden, und ich würde darauf wetten, dass einige Transpile-Codes besser sind als andere.

Hier ist meine Meinung dazu:
https://github.com/mrdoob/three.js/pull/20529

Dies ist ein benutzerdefiniertes Build-Skript von poc, das alle JSM-Module in etwa 30 Sekunden in globale JS-Namespace-Module konvertiert. Hatte mit dieser Methode recht gute Erfolge. Benötigt mehr Tests, habe aber einige der komplexeren Module wie den GLTFLoader in einer Hallo-Welt ausprobiert und es war in Ordnung.

Könnte Hilfe von erfahrenen RegExp-Zauberern gebrauchen :), um einige Randfälle zu klären, über die Sie in der PR mehr lesen können.

Auslieferungsabsicht von Chrome Import Maps:
https://groups.google.com/a/chromium.org/g/blink-dev/c/rVX_dJAJ-eI

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen