Three.js: Wechsel zu ES6-Klassen

Erstellt am 2. Aug. 2020  ·  88Kommentare  ·  Quelle: mrdoob/three.js

Hallo zusammen,

Ich hielt es für angebracht, eine neue Ausgabe zu erstellen (anstatt #11552 fortzusetzen), um allen dabei zu helfen, den Überblick zu behalten und über die Probleme und Fortschritte im Zusammenhang mit der Umstellung auf ES6-Klassen auf dem Laufenden zu bleiben. Dies sollte auch für die Release-Dokumentation nützlich sein.

Wenn Sie helfen möchten, sehen Sie sich die Liste unten an und teilen Sie uns mit, woran Sie arbeiten möchten. Ein PR pro Klasse wird bevorzugt, jedoch können einige Ordner auf einmal bearbeitet werden . Wenn eine bestimmte Datei nicht konvertiert werden kann, machen Sie eine Notiz oben in der Datei oder pingen Sie mich von Ihrem PR aus und ich werde es unten notieren.

Anmerkungen:

  • für Class.prototype.is** verwenden Object.defineProperty( this, 'is**', { value: true } );
  • Klassenfelder sind ggf. auch verfügbar #20395
  • new this.contructor() != new Foo() ... verwandte Diskussion .
  • Wird nach dem Zusammenführen und Vervollständigen ankreuzen.

Teil 1: src

  • [ ] quelle

    • [ ] Animation ( #19964, #20014, #20016 )

    • [ ] Titel ( #20013 )

    • [x] Ton ( #19975, #20003 )

    • [ ] Kameras ( #20102 )

    • [ ] Kern ( #19976, #19977, #19978, #19984, #20008 )

    • [x] Extras ( #19979 )

    • [ ] Kern ( #20656 )



      • Kurve in den Beispielen als verlängert weglassen



    • [ ] Kurven ( #20140 )

    • [ ] Objekte ( )



      • Wird in examples/objects/MarchingCubes.js verwendet, muss warten. Ref #20030



    • [x] Geometrien ( #19994 )

    • [x] Helfer ( #19996 )

    • [ ] Lichter ( #20018 )

    • [ ] Lader ( #19985 )

    • Baseloader kann noch nicht ausgeführt werden

    • [ ] Materialien ( #20100 )

    • [x] Mathematik ( #19980, #19997, #20076, #20089)

    • Interpolanten werden warten, bis wir examples/js in Angriff nehmen

    • [ ] Objekte (#20658 )

    • [ ] Renderer ( #20101 )

    • [ ] webgl ( #20070 )

    • [ ] webxr ( #20038 )

    • [x] Szenen ( #20007 )

    • [ ] Texturen ( #20009 )

Wir sind noch nicht bereit für Teil 2. Diskussion ist erforderlich.

Teil 2: Beispiele

  • [ ] Beispiele

    • [ ] Animation

    • [ ] Kameras

    • [ ] steuert

    • [ ] Kurven

    • [ ] Auswirkungen

    • [ ] Exporteure

    • [ ] Geometrien

    • [ ] interaktiv

    • [ ] Beleuchtung

    • [ ] Linien

    • [ ] Lader

    • [ ] Mathematik

    • [] versch

    • [ ] Modifikatoren

    • [ ] Objekte

    • [ ] Nachbearbeitung

    • [ ] Renderer

    • [ ] Shader

Teil 3: Lose Enden und aufräumen

  • [] src/core/Object3D
    ...

Hilfreichster Kommentar

@ianpurvis großartig! verwendest du rollup, oder? könntest du deine config teilen?

@mrdoob Ich bin endlich dazu gekommen, ein paar Tests durchzuführen. Ich persönlich benutze Webpack, also habe ich einige Tests damit gemacht, meine Konfiguration ist diese, falls es jemanden interessiert .

Ich habe diesen Code getestet

import * as THREE from 'three'

console.log(THREE.WebGLRenderer)

0.119.1

0 119 1

0.120.1

0 120 1

Es wird also etwas an den Bäumen geschüttelt, großartig!

Wenn man sich das genauer ansieht, sieht es so aus, als ob die Klasse AudioListener nicht im Bundle enthalten ist, tolle Neuigkeiten!

Screenshot 2020-09-01 at 16 49 22

Screenshot 2020-09-01 at 16 50 07

Webpack entfernt auch automatisch die nicht verwendeten Variablen, auf die @ianpurvis hinweist.


Danach habe ich mich entschieden, außerhalb der Klasse definierte statische Methoden zu testen

Screenshot 2020-09-01 at 16 50 37

und leider macht dies die Klasse nicht baumerschütterbar

Screenshot 2020-09-01 at 16 51 04


Nachdem ich weiter gegraben hatte, bemerkte ich, dass Geometrieklassen wie DodecahedronGeometry , die nirgendwo verwendet wurden, immer noch im Paket waren

Screenshot 2020-09-01 at 16 51 29

Screenshot 2020-09-01 at 16 52 08

Später stellte ich fest, dass dies an diesem Geometries -Objekt im three.module.js -Bundle lag

Screenshot 2020-09-01 at 17 18 32

Wird automatisch generiert, wenn Muster wie dieses im ObjectLoader verwendet werden . Dies wird wahrscheinlich verschwinden, wenn wir ObjectLoader zu einer Klasse machen, und src/geometries wird Tree-Shakeable sein.

Alle 88 Kommentare

Den Rest des Audioordners nenne ich dibs 🔈

Hey @mrdoob , könnten Sie bitte klarstellen, wie wir mit den Skripten im Beispielordner umgehen sollen?

Ich mag #19989, wenn ich direkt zur Konvertierung gehe, aber ich merke dabei, dass utils/modularize.js nicht mehr für den Ordner examples/js verwendet werden kann, ohne diese Arbeit zu überschreiben. Bedeutet dies das Ende unserer Aufrechterhaltung der examples/js und der Beginn von nur examples/jsm ?

edit: siehe kommentar

Kann ich den Rest des Mathe-Ordners bearbeiten?

Kann ich den Rest des Mathe-Ordners bearbeiten?

Ich bin dafür, dass Sie es versuchen. Ich erinnere mich, dass ich es vor einer Weile versucht habe, aber @Mugen87 hat mich schließlich dafür abgewiesen. Eine kurze Zusammenfassung davon war ein Test, da Sie den gesamten Ordner auf einmal konvertieren könnten, um sich auf eine harte Fahrt einzustellen. Ein Teil, oder sogar Datei für Datei, wäre sicherlich willkommen.

@DefinitelyMaybe Ich werde sehen, was sonst noch unter src/animation/ migriert werden kann

nett. Ich denke, dass der Ordner fast fertig ist. Sind vielleicht nur src/core/Object3D.js und src/core/BufferGeometry.js übrig?

Sind vielleicht nur src/core/Object3D.js und src/core/BufferGeometry.js übrig?

Ja, es gibt viele ES5-Klassen, die von Object3D und BufferGeometry abhängen.

Schießen Sie, es gab einige erstaunliche Fortschritte dabei 🎉

Ich werde dibs auf src/lights anrufen. Wenn Sie src/extras und src/renderers in der obigen Auflistung geöffnet haben, stellt sich heraus, dass es in jedem ein paar Ordner gibt, die Sie durcharbeiten müssen.

Hey alle zusammen,

Was haben wir in Bezug auf dieses Muster gemacht?

foo.prototype = Object.assign( Object.create( bar.prototype ), {
    ...
    isDirectionalLight: true,
    ...
} );

Ist es jetzt:

class foo extends bar {
  static isDirectionalLight = true;
  constructor(  ) {
    ...
  }
}

oder

class foo extends bar {
  constructor(  ) {
    this.isDirectionalLight = true;
  }
}

Derzeit mache ich das zweite, aber wenn ich es mir ansehe, würde ich sagen, dass die Absicht dahinter vielleicht näher an der ersten lag.

Weiß jemand, was diese Variablen überhaupt verwendet hat?

class foo extends bar {
  constructor(  ) {
    this.isDirectionalLight = true;
  }
}

☝️ Das stimmt. isDirectionalLight ist ein gutes Beispiel, es wird so verwendet:

$ git grep 'isDirectionalLight\b' src/ examples/js ':!*.ts'
examples/js/exporters/GLTFExporter.js:                  if ( light.isDirectionalLight ) {
examples/js/exporters/GLTFExporter.js:                  } else if ( object.isDirectionalLight || object.isPointLight || object.isSpotLight ) {
examples/js/renderers/SVGRenderer.js:                   } else if ( light.isDirectionalLight ) {
examples/js/renderers/SVGRenderer.js:                   if ( light.isDirectionalLight ) {
src/lights/DirectionalLight.js: isDirectionalLight: true,
src/renderers/webgl/WebGLLights.js:                     } else if ( light.isDirectionalLight ) {

Allerdings könnte es Leistungssteigerungen geben, wenn einige Prototyp-Eigenschaften beibehalten werden ...

class foo extends bar {
}
foo.prototype.baz = heavyThing;

Vielleicht können wir die in der PR von Fall zu Fall überprüfen.

Ich nehme eine Chance auf src/renderers/webgl 👍 👍

viel Glück und viel Spass. dass da einiges los ist

Hallo zusammen, ich habe src/renderers/webgl umgewandelt. Es war verrückt. Ich werde alles weiter überprüfen und auf #20039 warten, bevor ich anfange, die PRs zu pushen.

👍
sich auf etwas freuen

Mir ist aufgefallen, dass @yomotsu schreibgeschützte Getter für is* -Eigenschaften in der mathematischen PR verwendet hat ... Vielleicht ist das das Beste!

class foo extends bar {
  get isDirectionalLight() {
    return true;
  }
}

hm könnte sein. Ich weiß, dass andere stellenweise versucht haben, Variablen unveränderbar zu machen. Das sieht für mich nach einem ziemlich anständigen Muster aus.

schneller jsfiddle schaukasten

Scheint so zu gehen:

foo.prototype.isDirectionalLight = true;

Ich werde mir src/objects ansehen. Mal sehen wie weit ich komme ohne was kaputt zu machen.

Der Matheordner wurde gerade fertiggestellt.
( Interpolationsklassen sind ausgeschlossen. )

Hey alle zusammen,
Ich werde mich mit der Bearbeitung von src/objects zurückziehen, jemand anderes kann sich in der Zwischenzeit gerne darum kümmern.

Hey, gute Arbeit mit diesen Jungs! 💪

Nur ein Problem, foo.prototype.isDirectionalLight = true; erlaubt immer noch kein Tree-Shaking, da die Klasse an Ort und Stelle modifiziert wird.
Auch an dieser Stelle würde ich dringend empfehlen, den Prototyp nicht mehr anzufassen, da wir jetzt Klassen verwenden und der Prototyp abstrahiert werden kann.

Was ist mit diesem Muster? Es sieht für mich am deutlichsten aus.

constructor( x = 0, y = 0, z = 0 ) {

  Object.defineProperty( this, 'isVector3', {
    value: true,
    enumerable: false,
    writable: false,
    configurable: false,
  } );

Es gibt auch die Kurzversion, die dasselbe tut, aber etwas impliziter ist.

constructor( x = 0, y = 0, z = 0 ) {

  Object.defineProperty( this, 'isVector3', { value: true } );

@marcofugaro die Kurzfassung gefällt mir gut 👍

Ok, PR gemacht.

Außerdem ist mir gerade aufgefallen, dass wir keine Klassenfelder verwenden können, weil wir von diesem PR blockiert werden.

Ich kann die Build-Pipeline aktualisieren, um das beliebtere @rollup/plugin-babel zu verwenden

Ich kann die Build-Pipeline aktualisieren, um das beliebtere @rollup/plugin-babel zu verwenden
und beheben Sie dieses Problem, wenn Sie wollen.

Ja, es wäre toll, wenn du eine PR machen könntest 🙏

@marcofugaro , @mrdoob yay! ja bitte

Hallo zusammen, kurze Warnung, dass ich #20014 mit Object.defineProperty aktualisiert und auch die Unterklassen von AnimationClip habe. Wenn jemand Zeit hat, es zu überprüfen, würde ich mich über das Extra freuen 👀 🙇 🙇

Okay. Jetzt, da r120 draußen ist... könnte jemand überprüfen, ob die Dinge richtig geschüttelt werden?

Scheint, es funktioniert irgendwie für mich, aber geringfügig.
Ich sehe ArrowHelper nicht mehr in meiner Bundle-Datei mit Webpack. aber viele unnötige Codes sind immer noch vorhanden😢

Wie sieht es mit der Bündelgröße aus? vorher und nachher

Hallo zusammen, ich hatte eine Idee und habe ein Tool namens shakediff gespiked . Sie können es so ausführen:

$ shakediff builds/three.module.js Color

Dadurch wird ein kleines Modul generiert, das Color importiert, es mit drei bündelt und dann einen Diff von drei aus den Metadaten des Rollups erstellt. Sie können entweder mit dem detaillierten Diff arbeiten oder es einfach an diffstat , um das hohe Niveau zu erhalten:

$ shakediff build/three.module.js Color | diffstat 
 three.module.js | 2878 --------------------------------------------------------
 1 file changed, 1 insertion(+), 2877 deletions(-)

Im Moment gibt es kein Paket, aber Sie können es von meinem Repo installieren, wenn Sie es ausprobieren möchten. Feedback erwünscht! ✌️

npm -g i ianpurvis/shakediff.git

Hey @mrdoob , könnten Sie bitte klarstellen, wie wir mit den Skripten im Beispielordner umgehen sollen?
Mir gefällt, dass #19989 direkt zur Konvertierung geht, aber ich merke dabei, dass die utils/modularize.js nicht mehr im Ordner "examples/js" verwendet werden können, ohne diese Arbeit zu überschreiben. Bedeutet dies das Ende unserer Aufrechterhaltung der Beispiele/js und den Beginn von nur example/jsm?

Wie lautet das Urteil zu diesem @mrdoob? Wäre es sinnvoll, jsm zur Quelle der Wahrheit zu machen, damit wir Beispiele in ES6-Klassen konvertieren können? Vielleicht können wir utils/demodularize.js erstellen, um die Konvertierung in die andere Richtung zu unterstützen?

Der Ordner examples/js wird im Dezember 2020 entfernt. Bis dahin sollten wir den Ordner so belassen, wie er ist, ohne seinen Inhalt – oder die aus seinem Inhalt generierten examples/jsm -Dateien – auf ES6-Klassen zu aktualisieren. Nach diesem Datum werden die examples/jsm -Dateien zur Quelle der Wahrheit und können auf ES6-Klassen aktualisiert werden.

Mir ist aufgefallen, dass Modulbereichsvariablen während des Schüttelns nicht entfernt werden. Sie können das Verhalten mit diesen vier Variablen sehen, build/three.module.js:43059

const _position$3 = new Vector3();
const _quaternion$4 = new Quaternion();
const _scale$2 = new Vector3();
const _orientation$1 = new Vector3();

Sieht so aus, als sollten wir diese rein mit dem speziellen Kommentar markieren -

const _position = /*@__PURE__*/ new Vector3();

Funktioniert das bei allen?

Klingt gut für mich 👌

Schön, das löscht weitere 144 Zeilen beim Baumschütteln mit Color 🥳

Bitte geben Sie Ihren offenen PRs die /*@__PURE__*/ -Behandlung, wenn Sie Zeit haben!

@ianpurvis großartig! verwendest du rollup, oder? könntest du deine config teilen?

@mrdoob Ich bin endlich dazu gekommen, ein paar Tests durchzuführen. Ich persönlich benutze Webpack, also habe ich einige Tests damit gemacht, meine Konfiguration ist diese, falls es jemanden interessiert .

Ich habe diesen Code getestet

import * as THREE from 'three'

console.log(THREE.WebGLRenderer)

0.119.1

0 119 1

0.120.1

0 120 1

Es wird also etwas an den Bäumen geschüttelt, großartig!

Wenn man sich das genauer ansieht, sieht es so aus, als ob die Klasse AudioListener nicht im Bundle enthalten ist, tolle Neuigkeiten!

Screenshot 2020-09-01 at 16 49 22

Screenshot 2020-09-01 at 16 50 07

Webpack entfernt auch automatisch die nicht verwendeten Variablen, auf die @ianpurvis hinweist.


Danach habe ich mich entschieden, außerhalb der Klasse definierte statische Methoden zu testen

Screenshot 2020-09-01 at 16 50 37

und leider macht dies die Klasse nicht baumerschütterbar

Screenshot 2020-09-01 at 16 51 04


Nachdem ich weiter gegraben hatte, bemerkte ich, dass Geometrieklassen wie DodecahedronGeometry , die nirgendwo verwendet wurden, immer noch im Paket waren

Screenshot 2020-09-01 at 16 51 29

Screenshot 2020-09-01 at 16 52 08

Später stellte ich fest, dass dies an diesem Geometries -Objekt im three.module.js -Bundle lag

Screenshot 2020-09-01 at 17 18 32

Wird automatisch generiert, wenn Muster wie dieses im ObjectLoader verwendet werden . Dies wird wahrscheinlich verschwinden, wenn wir ObjectLoader zu einer Klasse machen, und src/geometries wird Tree-Shakeable sein.

@marcofugaro Kein Problem, hier ist die Rollup- Konfiguration

@marcofugaro Hallo, ich habe shakediff Webpack-Unterstützung hinzugefügt ... scheint Ihnen diese Webpack-Konfiguration in Ordnung zu sein? Da terser für die Eliminierung von totem Code im Tree-Shaking von Webpack verantwortlich ist, ist es schwierig, einige Transformationsartefakte in diesen Ausgaben zu verhindern. Wenn Sie jedoch einen Histogrammalgorithmus mit deaktiviertem Leerzeichen verwenden, ist dies überschaubar. Nach einem kurzen Test heute Abend scheint webpack sowohl /*@__PURE__*/ als auch /*#__PURE__*/ zu akzeptieren. Ich denke, wir können uns auf das eine oder andere standardisieren. Morgen mehr...

@ianpurvis Ich glaube nicht, dass ich shakediff auf meinem Rechner installieren darf...

Screen Shot 2020-09-22 at 9 59 04 AM

Trotzdem habe ich einen einfachen Test gemacht:

import { WebGLRenderer } from './src/renderers/WebGLRenderer.js';
console.log( new WebGLRenderer() );

Und bemerkte, dass Geometry nicht am Baum geschüttelt wurde. https://github.com/mrdoob/three.js/pull/20394 behebt es.

Ich habe dann versucht, Folgendes zu tun:

import { Vector3 } from './src/math/Vector3.js';
console.log( new Vector3() );

Und bemerkt, dass Rollup ungenutzte Methoden nicht erschüttert ... 😕

@mrdoob Leider werden Klassenmethoden in absehbarer Zeit von keinem Tool baumerschütterbar sein. Verdammt, sie können nicht einmal minimiert werden!

Dies liegt daran, dass Sie in Javascript auf Methoden wie this['I am a string'] zugreifen können, genau wie Sie auf dynamische Objekteigenschaften zugreifen können. Aus diesem Grund wissen Tools nicht im Voraus, ob und wie Sie eine Methode aufrufen (könnte this[variable] sein).

Dies gilt sowohl für ES6-Klassen als auch für Funktionsklassen. In three.min.js beispielsweise bleiben die Methoden unverändert, genau wie jede Objekteigenschaft 🙂

Und niemand hat einen "strikten" Builder-Modus vorgeschlagen, in dem Sie Methoden wie this['I am a string'] nicht aufrufen sollen?

Keine Ahnung 🤷‍♂️

Hier ist eine Diskussion zu diesem Thema bezüglich Rollups: https://github.com/rollup/rollup/issues/349

Klassenmethoden werden von keinem Tool baumerschütterbar sein. Verdammt, sie können nicht einmal minimiert werden!

Tut mir leid, dass ich vom Thema abkomme, aber Sie können die Minimierung zum Laufen bringen, wenn Sie dem Compiler einen Hinweis darauf geben, was "öffentlich" und "privat" ist. In der Vergangenheit habe ich dafür "_"-Präfixe für Methoden verwendet. Siehe https://github.com/developit/microbundle/wiki/mangle.json. Aber leider habe ich auch keine Ahnung, ob etwas Ähnliches für Treeshaking möglich ist. 😕

Wow! #20395 zusammengeführt! Gute Sachen @marcofugaro

Großartige Neuigkeiten über Babel und Geometrie!

@ianpurvis Ich glaube nicht, dass ich Shakediff auf meinem Rechner installieren darf ...

@mrdoob Hm, sieht so aus, als hätte Parcel eine Abhängigkeit von dieser Version von fsevents ... vielleicht kann ich das an etwas Höheres anheften.

Fyi, gute Informationen hier über Tree-Shaking-Verbesserungen in Webpack 5 ...

Fyi, gute Informationen hier über Tree-Shaking-Verbesserungen in Webpack 5 ...

Fortschritt ... Ich hoffe, Rollup implementiert dies auch ...

Hallo zusammen,

Was genau sind die Ziele von .is**Classname** Property und this.type = **Classname** ?
Ist es nicht ein Rest des alten Pseudoklassenmusters?
Warum werden Sie es nicht vollständig los und ersetzen Sie diese Verwendung durch die normale Art der Typprüfung?

obj instanceof Vector3  // prefer this one for inheritance
// or
obj.constructor === Vector3  // prefer this for no inheritance

Ich meine, als Teil der Umstellung auf ES-Klassen werden Objekte bereits überprüfbare korrekte Typen haben ...

Die Bibliothek verwendete zuvor obj instanceof Vector3 .
Aber Rich Harris hat alle Checks implementiert und auf is* geändert, um Tree-Shaking zu ermöglichen: #9310

Die Bibliothek verwendete zuvor obj instanceof Vector3 .
Aber Rich Harris hat alle Checks implementiert und auf is* geändert, um Tree-Shaking zu ermöglichen: #9310

Danke für die Antwort, ich hatte den Thread gelesen, übrigens verstehe ich nicht, warum eine Klasse vermieden werden muss, um in der Ausgabe zu sein, wenn eine andere Klasse sie typisieren muss ... Ich meine, wenn gebündelte Klasse X benötigt sich bewusst sein, dass ein Objekt eine Klasse B ist, dann wird Klasse B verwendet (zumindest um das besagte Objekt irgendwie zu erstellen) und muss gebündelt werden, nicht wahr?

Zum Beispiel muss WebGLRenderer prüfen, ob eine Geometrie, die es rendert, BufferGeometry oder Geometry ist, aber es erstellt nie Geometry-Instanzen. Die meisten Three.js-Anwendungen sollten nur BufferGeometry verwenden, und deshalb möchten wir, dass Tree-Shaking Geometry (und seine Unterklassen) nach Möglichkeit aus dem Bundle eliminiert.

Optisch gesehen...

Dieses Muster bewirkt, dass WebGLRenderer Geometry enthält:

import { Geometry } from '../core/Geometry.js';
import { BufferGeometry } from '../core/BufferGeometry.js';

if ( geometry instanceof Geometry ) {
} else if ( geometry instanceof BufferGeometry ) {
}

Dieses Muster nicht:

if ( geometry.isGeometry === true ) {
} else if ( geometry.isBufferGeometry === true ) {
}

Hey alle zusammen,

Angesichts dessen, was sind unsere Gedanken, um von hier aus voranzukommen?

Ich glaube nicht, dass sich noch etwas geändert hat. Alles, was (1) nicht in examples/js ist und (2) nicht durch etwas in examples/js erweitert ist, kann in ES6-Klassen konvertiert werden. Wenn dieser Prozess abgeschlossen ist, sollten wir entscheiden, wann wir mit der Umstellung examples/js auf Klassen beginnen.

Aus dem Gedächtnis, und nach einem kurzen Blick haben wir einiges getan und es warten noch einige PR's darauf.

Ich könnte versuchen, meine Liste der Abhängigkeiten/erweiterten Beispiele neu zu kompilieren.

@Auf jeden FallVielleicht Hey! Das hört sich toll an, deine Liste war super hilfreich. Und die Strategie von @donmccurdy macht für mich Sinn. 👍 Ich denke, es wäre am besten, die Arbeit, die wir bereits erledigt haben, abzuschließen. #20070 wäre ein großartiger PR-Angriff, da es eine Strategie für die Migration privater/versteckter Variablen auf ES6 bieten kann (wir brauchen dies für die Migration von renderers/webgl auf ES6). Wenn jeder die Benchmarks ausführen oder sich dort an der Diskussion beteiligen kann, würde ich es begrüßen. Ich denke, wir haben einige anständige Optionen, müssen nur sicherstellen, dass die Leistung gut ist.

Okay,
Ich kann einige PR für Beispiele starten, die in ES-Klassen umgeschrieben werden ...
@mrdoob ist es ein Problem für Sie, das jsm to js-Skript auszuführen oder nicht? (Ich denke nicht, aber sag mir, ob du es vorziehst, dass wir warten)

Bevor Sie den Beispielcode in Klassen umwandeln, sollten zuerst #20527, #20529 oder eine andere Lösung gemergt werden. Mit Ausnahme des Codes, der die in https://github.com/mrdoob/three.js/issues/19986#issuecomment -718308451 genannten Bedingungen erfüllt.

@DefinitelyMaybe Du sagtest im ersten Kommentar :

  • Klassenfelder verwenden

1) Bedeutet das, dass wir Klassenfelder für alles verwenden können?
So etwa:

class Light extends Object3D {

    type = 'Light';
    isLight = true;

    color = new Color;
    intensity = 1;

    constructor(color, intensity = 1) {

        super();

        this.color = new Color(color);
        this.intensity = intensity;

    }

    copy() {
        ...
    }
}

... oder es ist nur für .is* Eigentum?

Also, 2) was ist mit leeren Konstruktoren? Die ES2015-Spezifikation besagt, dass Konstruktoren mit nur einem super() -Aufruf implizit sind, wenn sie nicht bereitgestellt werden, sodass einige untergeordnete Klassen wirklich einfacher definiert werden können:

class MapControls extends OrbitControls {

    screenSpacePanning = false; // pan orthogonal to world-space direction camera.up

    mouseButtons = { LEFT: MOUSE.PAN, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.ROTATE };

    touches = { ONE: TOUCH.PAN, TWO: TOUCH.DOLLY_ROTATE };

}

Und 3) was ist mit privaten Klassenfeldern?

class OrbitControls extends EventDispatcher {
    ...

    #offset = new Vector3();

    // so camera.up is the orbit axis
    #quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) ); <= this will go in constructor because of object.up
    #quatInverse = this.#quat.clone().inverse();

    #lastPosition = new Vector3();
    #lastQuaternion = new Quaternion();

    #twoPI = 2 * Math.PI;

    update() {
        ... ( no more closure and return function here )
    }

}

Das neueste Chrome unterstützt jetzt nativ sowohl öffentliche als auch private Klassenfelder ...

20395

Der erste Schlüssel ist, alle Tests zu bestehen.

Sie werden anfangs weniger Probleme haben, wenn Sie weniger ändern.

@marcofugaro Ich glaube, es gibt noch einige Variablen, die in Klassenfelder geändert werden können, oder?
Ich betrachte Dinge wie:

class EdgesGeometry extends BufferGeometry {

    constructor( geometry, thresholdAngle ) {

        super();

        this.type = 'EdgesGeometry';

gewechselt zu:

class EdgesGeometry extends BufferGeometry {

    type = 'EdgesGeometry';

    constructor( geometry, thresholdAngle ) {

        super();

Es ist wahrscheinlich, dass wir in der Gegend auf einige andere Vorbehalte stoßen werden, wie zum Beispiel, wie ich auf " new this.contructor() != new Foo() " gestoßen bin.

private Klassenfelder

dies ist eine laufende Diskussion. Es wird eine Weile dauern, bis wir es verwenden, wenn wir es verwenden. Ich kenne kein Problem oder PR, auf das ich Sie hinweisen kann.

@marcofugaro Ich glaube, es gibt noch einige Variablen, die in Klassenfelder geändert werden können, oder?
Ich betrachte Dinge wie:

Ja das kann man jetzt machen. Allerdings können wir das nicht für .is* Eigenschaften tun, da sie nicht aufzählbar und nicht beschreibbar sein müssen, für diese müssen wir Object.defineProperty(this, ... verwenden.

wie wird das nochmal geprüft? Wäre es möglich, das Schlüsselwort static anstelle von Object.defineProperty(this, ... zu verwenden?

wie wird das nochmal geprüft? Wäre es möglich, das Schlüsselwort static anstelle von Object.defineProperty(this, ... zu verwenden?

Ich glaube nicht, weil obj.is* auf Instanzen sein müssen, nicht auf der Klasse selbst ...

Ich bin mir nicht sicher, was babel in der aktuellen Konfiguration genau transpiliert, aber wir können Dekoratoren verwenden, um ein Klassenfeld als nicht aufzählbar/nicht beschreibbar festzulegen:

import { unwrittable, unenumerable } from 'some/decorator/helpers.js'

class Foo {
    @unwrittable<strong i="12">@unenumerable</strong>
    isFoo = true;
}

@DefinitelyMaybe static Eigenschaften sind anders, sie sind nicht von der Instanz aus zugänglich, sondern von der Klasse selbst.

class Test {
  static staticProp = true

  constructor() {
    Object.defineProperty(this, 'definedProp', { value: true })
  }
}
const test = new Test()

console.log(test.staticProp, test.definedProp)

Ergebnis:

undefined true


Edit: egal was ich gesagt habe...
Ja ja.

Mein Hauptpunkt ist, dass wir, wenn wir den Code anpassen würden, der diese Eigenschaft überprüft, von Folgendem ausgehen könnten:

class Test {
  constructor() {
    Object.defineProperty(this, 'definedProp', { value: true })
  }
}

zu

class Test {
  static definedProp = true
  constructor() {
  }
}

Ich habe mich also gefragt, wo und warum diese Überprüfung stattfindet und ob wir sie ändern könnten oder nicht.

@DefinitelyMaybe Das Problem besteht darin, die Informationen eines Instanztyps abzurufen. Wenn Sie also auf die Klasse der Instanz zugreifen könnten, um ihre statische Stütze zu erhalten, warum sollten Sie dann eine statische Stütze haben? Sie haben bereits den Namen der Klasse ...

obj.constructor.isFoo == true
obj.constructor.name == 'Foo'

Bearbeiten: Wenn ich dies schreibe, könnte ich herausfinden, dass es nützlich sein kann, mehrere .is * zu haben, um schließlich jede Vererbungskette zu testen, verglichen mit nur dem einzelnen endgültigen Klassennamen ...

obj.constructor.isFoo || obj.constructor.isBar || obj.constructor.isBaz

Edit2: Ja, auch das gleiche kann endlich mit Klassennamen erreicht werden, aber komplizierter zu testen ...

let types = getInheritanceNames(obj) // looping each .constructor.prototype.constructor.name
types.contains( 'Foo' ) || types.contains( 'Bar' ) || types.contains( 'Baz' ) 

aus der Instanz

Hoppla. lies das nochmal. Jup, egal was ich gesagt habe.

if ( scope.object.isPerspectiveCamera ) {
...
}
if ( geometry.isBufferGeometry ) {
...
}
if ( material.isShaderMaterial ) {
...
}

Rechts. Zwei Dinge.

  • Was bleibt uns?

wir sollten entscheiden, wann wir mit der Umstellung examples/js auf Klassen beginnen.

  • Ich nähere mich der Notwendigkeit, dies zu diskutieren, um voranzukommen.

Ich weiß nicht, ob wir auf #20527 oder #20529 warten sollten, da beide versuchen werden, examples/js in seiner aktuellen Form neu zu erstellen, was nicht unser Ziel ist. Mein erster Vorschlag ist, examples/js unverändert umzuwandeln. Die Frage ist, in welche Schwierigkeiten wir geraten ...

Ich wollte auch etwas wiederholen, was @mrdoob kürzlich gesagt hat

Ich würde es hassen, Neulinge dazu zu zwingen, etwas über Polyfills oder Bundler zu lernen, um ihren ersten Cube zu rendern.

Als jemand, der seit kurzem mit Modulen arbeitet, ist der Workflow klar und ich verstehe die verschiedenen Konzepte, die erforderlich sind, um etwas zum Laufen zu bringen. Wir brauchen keine Bundler und Polyfills, aber wir müssen anpassen, wie Three.js anfänglich beschrieben wird .

Vielleicht könnte auch das Hinzufügen eines REPL , das aber auf Three.js ausgerichtet ist, in diesem Bereich helfen? Ein Beispiel dafür ist Svelte

Wir müssen auch klären, wie einige Nicht-Klassen-Muster ersetzt werden können, wie zum Beispiel:

function Foo() {

    this.update = function () {

        var priv = 'foo'

        return function update() {
            ...
        };

    }();

}

IMHO könnten wir private Klassenfelder verwenden und das Rollup/Babel-Transpile zu einem alten Muster für bestimmte alte Browser machen, die dies nicht nativ implementieren ...

IMHO könnten wir private Klassenfelder verwenden und das Rollup/Babel-Transpile zu einem alten Muster für bestimmte alte Browser machen, die dies nicht nativ implementieren ...

Ich stimme dieser Strategie zu, aber die Entscheidung hängt natürlich von den Hauptbetreuern ab, die diesen Code pflegen müssen.

cool. Es könnte eine Idee sein, dies zuerst in src zu zeigen, dh ein ähnlich seltsames Muster zu dem zu finden, was @devingfx in src beschrieben hat, eine PR zu erstellen, die stattdessen private Variablen verwendet, und zu zeigen, was babel tut damit.

Irgendwelche Vorschläge für welches Skript?

Suchen: internal , private , readonly 👀

Moment mal, waren alle _* Variablen als privat gedacht?

...

Ein Elefant in diesem Raum könnte src/renderers/WebGLRenderer.js sein

Wie wäre es mit WebGLAnimation, es ist eine nette kleine Klasse ... https://github.com/mrdoob/three.js/pull/20070

Irgendwelche Vorschläge für welches Skript?

Ich konzentriere mich auf exemples/js und habe das auf OrbitControls gefunden ...

zeigen was babel damit macht.

Ich bin mir ziemlich sicher, dass es nichts ausgeben wird, was dem Syntaxgedanken von mrDoob entspricht 😅

nach rechts.

und oops. Wo ist mein Gehirn? Wir brauchen einen von #20527 oder #20529 (oder einen anderen) zum Zusammenführen, um mit der Umwandlung des Ordners examples zu beginnen. examples/js bleibt auf absehbare Zeit hier, was bedeutet, dass das Berühren des Ordners examples/js mit Kursen ein absolutes No-Go ist. das würde die Kompatibilität mit IE brechen ... seufz.

Machen Sie das Rollup / Babel nach altem Muster transpilieren

Schätzen Sie, dass es diese JSM zu JS PRs durchdenkt und unterstützt. Wir können auf die examples/jsm zielen, sobald eine Entscheidung getroffen ist.

Das Hinzufügen privater Variablen in src ist immer noch eine gute Idee, da es eine gute Lösung für das seit langem bestehende Problem wäre: "Spielen Sie bitte nicht mit diesen Variablen, sie haben einen bestimmten Zweck."

Den Ordner examples/js mit Kursen zu berühren, ist ein absolutes No-Go.

Ooops, mein Fehler, ich habe darüber gesprochen, in exemples/jsm zu graben, natürlich wird exemples/js in naher Zukunft die "gebaute" Version sein ...

das würde die Kompatibilität mit IE brechen ... seufz.

Was??? Reden wir im Jahr 2020 noch über Internet Explorer? Sprechen wir über die Kompatibilität einer WebGL-Bibliothek mit diesem 7 Jahre alten Dinosaurier? Ernsthaft !! 1,4 % ...
_(wir sollten einen Statistik-Sammler in die Bibliothek einfügen, um zu erfassen, ob DREI Benutzer eine Verwendung unter IE planen)_

😞 Übrigens, dafür gibt es babel...

Die Build-Dateien three.js und three.min.js sowie alle Dateien in examples/js sollten noch ältere Browser wie IE 11 unterstützen.

Es gab letztes Jahr eine PR, die die Unterstützung für IE 11 (#18091) stoppen sollte, aber es stellte sich heraus, dass es immer noch Benutzer gibt, die sich auf diesen Browser verlassen. Und die aktuelle Richtlinie des Projekts besteht darin, den Benutzern entsprechende Dateien bereitzustellen, damit sie die Konvertierung von ES6 nach ES5 nicht selbst durchführen müssen. Dies wurde auch in #20455 diskutiert.

Die aktuelle Richtlinie des Projekts besteht darin, den Benutzern entsprechende Dateien bereitzustellen, damit sie die ES6-zu-ES5-Konvertierung nicht selbst durchführen müssen.

Okay, keine Probleme mit dieser Richtlinie, wenn die Quelle auf moderne Weise entwickelt werden kann und wenn die resultierenden Builds nicht lesbar sein sollen, sondern nur funktionieren ...
Weil Transpiler solch hässlichen Code ausgeben!
Ich sehe also keine Probleme, wenn src in ESnext geschrieben wird und Builds hässlich sind, ABER es ist ein potenzielles Problem mit exemples/js , wenn diese Dateien lesbar, kommentiert und wohlgeformt sein sollen ...

Übrigens frage ich mich schon seit einiger Zeit, warum einige Beispiele Beispiele und keine Hauptkernquellen sind!?
Beispiel: Steuerelemente werden normalerweise unverändert verwendet, wie optionale Addons kopiert und nicht als echtes Beispiel verwendet, das Sie lesen und von dem Sie sich inspirieren lassen, um Ihre Projekte zu schreiben, wie zum Beispiel ein rotierendes Würfelbeispiel ...

_(Ich begann meine Reise mit THREE mit einer Suche: "webgl rotierender Würfel" und ein Beispiel davon führte zu einem 1-Nacht-Code-Marathon, der ein kleines Spiel mit einem Würfel entwickelte, der sich auf Plattformen bewegt ^^)_

Wenn Sie einen richtigen Build verwenden, spielt es keine Rolle, welche Dateien sich im Kern befinden und welche im Beispielverzeichnis. Solange Tree Shaking richtig funktioniert, haben Sie nur die Quelldateien in Ihrem Build, die tatsächlich benötigt werden.

Die Unterscheidung von Kern und Beispielen stammt für mich aus einer Zeit, in der es diese Art von Workflow noch nicht gab. Der Kern sollte klein und kompakt sein, da Sie ihn komplett als einzelne Komponente importieren mussten. Nur die _wichtigsten_ Dateien sollten enthalten sein. Welche Dateien im Core landeten, war in gewisser Weise eine Einzelfallentscheidung.

Wenn Sie einen richtigen Build verwenden, spielt es keine Rolle, welche Dateien sich im Kern befinden und welche im Beispielverzeichnis. Solange Tree Shaking richtig funktioniert, haben Sie nur die Quelldateien in Ihrem Build, die tatsächlich benötigt werden.

Dies gilt nur für Benutzer von ES-Modulen ;)

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

seep picture seep  ·  3Kommentare

ghost picture ghost  ·  3Kommentare

jack-jun picture jack-jun  ·  3Kommentare

akshaysrin picture akshaysrin  ·  3Kommentare

fuzihaofzh picture fuzihaofzh  ·  3Kommentare