Three.js: Wechsel zu einer modularen Architektur

Erstellt am 6. Mai 2014  ·  153Kommentare  ·  Quelle: mrdoob/three.js

Browserify
Der Wechsel zu dieser Architektur hat Vor- und Nachteile. Bitte fügen Sie Ihre Gedanken hinzu.

Hinweis: Dies erfordert nicht, dass Three.js-Konsumenten browserify verwenden.

Suggestion

Hilfreichster Kommentar

Richtig, es wird also ein bisschen Refactoring erfordern...

Ich habe dich! Da dieser Thread in den letzten Tagen lebhaft geworden ist, habe ich ein bisschen mehr an three-jsnext gearbeitet . Es ist ein Projekt, das die vorhandene Three.js-Codebasis verwendet und sie automatisch in ES-Module umwandelt. Ich kämpfe nur mit ein paar kniffligen zyklischen Abhängigkeiten (insbesondere um KeyframeTrack ), sollte aber bald etwas zu teilen haben. Soweit ich das beurteilen kann, funktionieren alle Beispiele weiterhin und der minimierte Build ist kleiner als der aktuelle (mit Rollup zum Generieren einer UMD-Datei), also alles gute Nachrichten.

Alle 153 Kommentare

Ein Vorteil ist, dass dies eine modulare Architektur für die Weiterentwicklung von three.js erzwingen würde.

Der übliche Stil in node/browserify lässt jede Datei ihre Abhängigkeiten oben deklarieren und betrachtet globale Variablen als Anti-Muster.

Hier ist ein Beispiel-Schnipsel:

// src/geometry/BoxGeometry.js
var Geometry = require('./Geometry.js');
var Vector3 = require('../core/Vector3.js');
module.exports = BoxGeometry;

function BoxGeometry() {
  // ...
}

BoxGeometry.prototype = Geometry.prototype;

Ein weiterer Vorteil ist, dass Verbraucher von three.js , die browserify verwenden, in der Lage sind, die gewünschten Teile auszuwählen. Sie könnten einfach Scene , BoxGeometry , PerspectiveCamera und WebGLRenderer importieren und die Abhängigkeiten für all diese automatisch abrufen ( Object3D etc ), und haben ein kleines Bündel von Javascript, das nur die gewünschten Funktionen unterstützt.

Dies könnte auf eine Weise erfolgen, die keine grundlegenden Änderungen auferlegt. Auf der obersten Ebene würden wir alle Klassen exportieren, die wir als Teil des Standardpakets betrachten

// src/three.js
var THREE = { rev: 101 }
module.exports = THREE

THREE.Geometry = require('./geometry/Geometry.js')
THREE.BoxGeometry = require('./geometry/BoxGeometry.js')
// ...

Hinweis: Ich benötige die Abhängigkeiten oben in diesem Beispiel nicht genau, da diese Datei fast ausschließlich aus require-Anweisungen besteht.

Schließlich würden wir das in eine universelle Moduldefinition einschließen, die erkennt, ob ein Modulsystem (Node/Browserify, AMD) verwendet wird, und wenn ja, exportiert oder anderweitig an das globale Objekt anhängt ( window ).

Lassen Sie uns überprüfen:

  • erzwingt einen guten modularen Stil
  • ermöglicht three.js Verbrauchern, die browserify verwenden, die Funktionalität auszuwählen
  • keine Breaking Changes

Dies würde einen Austausch des Build-Systems erfordern, aber das neue wäre ziemlich einfach.

Einige weitere Vorteile:

  • Sie können Ihren Code strukturieren
  • Sie können Module erstellen / wiederverwenden, ohne den globalen Namensraum zu verschmutzen
  • Sie können für die Produktion bauen
  • Sie können einfacher debuggen, da jedes Modul eine eigene Datei hat, Sie müssen nicht in einer großen Three.js-Datei nach dem entsprechenden Modul suchen

@shi-314 Ich glaube, ich bin ein wenig verwirrt, ich habe das Gefühl, dass You can structure your code und You can build for production Dinge sind, die Sie ohne die architektonische Verschiebung tun können? Sprechen Sie über Three.js-Quelle oder Dinge, die mit Three.js erstellt wurden?

Eine Methode, die Three.js verwendet, die die Verwendung in Commonjs-Umgebungen schwierig macht, ist die Verwendung von instanceof : https://github.com/mrdoob/three.js/blob/master/src/core/Geometry .js#L82

Dies liegt daran, dass Sie in einer Anwendung oft unterschiedliche Versionen derselben Bibliothek in Ihrem Quellbaum haben, sodass das Überprüfen von instanceof zwischen verschiedenen Versionen derselben Bibliothek nicht funktioniert. Als Vorbereitung für einen Wechsel zu einem Commonjs-Modulsystem wäre es gut, diese Instanzüberprüfungen durch die Funktionsüberprüfung hinter einer Schnittstelle im Stil von Geometry.isGeometry(geom) zu ersetzen.

@kumavis Ich spreche von Dingen, die in Three.js gebaut wurden. Nehmen wir an, Sie möchten Ihr eigenes Material mit Ihren Shadern usw. erstellen. Im Moment müssen Sie das globale THREE-Objekt erweitern, um mit dem Rest des Three.js-Codes konsistent zu bleiben:

THREE.MeshMyCoolMaterial = function (...) { ... }

Aber wenn wir Browserify hätten, als Sie könnten:

var MeshLambertMaterial = require('./../MeshLambertMaterial');
var MeshMyCoolMaterial = function (...) {...}

So bleibt Ihr Namespace konsistent und Sie müssen nicht THREE.MeshLambertMaterial und MeshMyCoolMaterial in Ihrem Code verwenden.

Und mit You can build for production meinte ich im Grunde dasselbe, was du erwähnt hast: allows three.js consumers using browserify to pick and choose functionality .

@shi-314 danke, das ist klarer. Das wirkt sich auf meine vorgeschlagene allgemeine Lösung zur Deserialisierung von verbraucherdefinierten Klassen aus:

// given that `data` is a hash of a serialized object
var ObjectClass = THREE[ data.type ]
new ObjectClass.fromJSON( data )

Dies ist von meinem vorgeschlagenen Serialisierungs- / Deserialisierungs-Refactor
https://github.com/mrdoob/three.js/pull/4621

Die Leistung sollte durch eine solche Änderung nicht beeinträchtigt werden.

Das ist eine ziemlich große Veränderung, aber ich bin auch dafür.

Einige andere große Vorteile:

  • Sie können die Option standalone browserify verwenden, um einen UMD-Build für Sie zu generieren. Sie müssen nicht manuell an UMD-Wrappern herumbasteln.
  • Das Paket kann problemlos von Benutzern von browserify/NPM . konsumiert werden
  • Das Einbinden von Abhängigkeiten für Threejs (wie poly2tri, color-string usw.) wird viel einfacher
  • Module, die "nicht wirklich in eine Rendering-Bibliothek gehören" (wie Vektor-/Mathematik-Bibliotheken) können als separate NPM-Module herausgezogen und für viele andere Arten von Projekten wiederverwendet werden. Ein großer Vorteil davon ist, dass die einzelnen Module ihr eigenes Repository für Bugs/Issues, PRs usw. (Bereinigung von ThreeJS-Problemen) haben.
  • NPM übernimmt für uns die semantische Versionierung. zB können wir einen Breaking Change im threejs-vecmath ohne uns Sorgen machen zu müssen, dass jeder Code kaputt geht. Und auf der anderen Seite, wenn wir einen Patch oder eine Nebenversion in einem bestimmten Modul erstellen, können die Leute, die diese Module konsumieren, die Änderungen automatisch erhalten.
  • Es macht "Extras" wie EffectComposer und verschiedene Shader einfach zu verpacken und zu konsumieren (stellen Sie sich npm install threejs-shader-bloom ).
  • Wenn Module herausgezogen werden, wird die endgültige Verteilungsgröße kleiner und anwendungsspezifischer. Es wird schließlich keine Notwendigkeit für verschiedene "Build-Typen" geben, da wir nur die Module require() die unsere App tatsächlich verwendet.

An @mrdoob und die anderen Autoren; Wenn Sie nicht viel Erfahrung mit NPM/Browserify haben, würde ich vorschlagen, ein paar kleine Projekte damit zu machen und ein Gefühl für seine "Philosophie" zu bekommen. Es unterscheidet sich stark von der ThreeJS-Architektur; eher als große Frameworks ermutigt es viele kleine Dinge .

Ein weiterer Vorteil dieses Ansatzes besteht darin, dass es ein Ökosystem von Open-Source-Drittanbieter-Three.JS-Modulen geben kann, insbesondere Shader, Geometrien, Modelllader usw., die über NPM oder Github/Component veröffentlicht werden und auf die die Leute dann einfach verweisen und verwenden können. Im Moment wird Sachen geteilt, indem eine Demo gehostet wird, auf der die Leute dann "Quelle anzeigen" können. Three.JS verdient Besseres!

Ich denke, eines der Probleme, die ich mit Three.JS habe, ist, wie schnell Code mit der aktuellen Version von Three.JS inkompatibel wird. Ein weiterer Vorteil des Umstiegs auf so etwas ist die Möglichkeit, bestimmte Versionen von _bits_ von Three.JS angeben zu können, was sehr mächtig und praktisch wäre.

+1

+1 für eine CommonJS/browserify-Architektur würde den Kern leichter machen und Erweiterungen würden passen, selbst wenn sie von Drittanbietern kommen

Die Fragmentierung von Three.js in kleine Module ist ebenfalls mit hohen Kosten verbunden. Das aktuelle System erlaubt recht einfache Addons von Drittanbietern (wie zB die THREEx Module von Jetienne). Es gibt viel über die Einfachheit des aktuellen Setups zu sagen, solange die JS-Modulsysteme nur Wrapper für Build-Systeme sind.

Eine andere Möglichkeit, die Build-Größe zu minimieren, ist ClojureScript. Sie folgen einigen Konventionen, die es dem Closure-Compiler von Google ermöglichen, das gesamte Programm zu analysieren und toten Code zu beseitigen.

+1 für die nicht geschätzte und oft übersehene Eleganz der Einfachheit

+1

Die Fragmentierung von Three.js in kleine Module ist ebenfalls mit hohen Kosten verbunden. Das aktuelle System erlaubt recht einfache Addons von Drittanbietern (wie zB die THREEx Module von Jetienne).

Die Idee hier ist, dass ein UMD-Build immer noch für Nicht-Node-Umgebungen bereitgestellt wird. Plugins wie THREEx würden für diejenigen, die von ThreeJS abhängig sind, mit einfachen <script> Tags genauso funktionieren.

Die knifflige Sache wird sein: Wie können wir ein bestimmtes Plugin require() wenn wir uns in einer CommonJS-Umgebung befinden? Vielleicht könnte browserify-shim helfen.

Es gibt viel über die Einfachheit des aktuellen Setups zu sagen, solange die JS-Modulsysteme nur Wrapper für Build-Systeme sind.

Das aktuelle Plugin-/Erweiterungssystem von ThreeJS ist ziemlich schlecht zu handhaben und alles andere als "einfach" oder einfach. Die meisten ThreeJS-Projekte neigen dazu, irgendeine Form von Plugin oder Erweiterung zu verwenden, wie EffectComposer oder FirstPersonControls oder einen Model Loader oder eine der vielen anderen JS-Dateien, die im Ordner examples herumliegen. Im Moment die einzige Möglichkeit, sich auf diese Plugins zu verlassen:

  • Laden Sie die aktuelle Version von ThreeJS herunter
  • Kopieren Sie die erforderlichen Dateien und fügen Sie sie in Ihren vendor Ordner ein
  • Verdrahten Sie Schluck-/Grunt-Aufgaben, um alle benötigten Plugins zu verketten und zu minimieren; Stellen Sie sicher, dass Sie sie _in der richtigen Reihenfolge_ verketten, da sonst die Dinge kaputt gehen. Pflegen Sie diese Liste manuell, wenn Sie weitere Plugins hinzufügen.
  • Wiederholen Sie die Schritte 1 und 2 jedes Mal, wenn ThreeJS aktualisiert wird; und ziehe dir dann die Haare aus, wenn du merkst, dass der neue Code nicht abwärtskompatibel ist

Stellen Sie sich nun vor, Sie könnten mit browserify so etwas tun:

var FirstPersonControls = require('threejs-controls').FirstPersonControls;

//more granular, only requiring necessary files
var FirstPersonControls = require('threejs-controls/lib/FirstPersonControls');

Diese Plugins werden require('threejs') und alles andere, was sie benötigen (wie GLSL-Schnipsel oder Texttriangulation ). Die Abhängigkeits-/Versionsverwaltung ist für den Benutzer vollständig verborgen, und es besteht keine Notwendigkeit für manuell verwaltete Grunt-/Schluck-Concat-Aufgaben.

Die knifflige Sache wird sein: Wie benötigen wir () ein bestimmtes Plugin, wenn wir uns in einer CommonJS-Umgebung befinden?

Ich verwende CommonJS seit einiger Zeit für THREE.js-Projekte. Es ist ein bisschen ein manueller Prozess, Teile des Codes anderer Leute in Module zu konvertieren, und ich glaube nicht, dass es eine einfache Möglichkeit geben wird, dies für Legacy-Code zu vermeiden, der nicht von den Autoren oder Mitwirkenden konvertiert wird.

Wichtig ist, dass es ein Modul gibt, das das gesamte 'Standard'-DREI-Objekt exportiert, das dann von jedem angefordert werden kann, der es erweitern möchte.

var THREE = require('three');

THREE.EffectComposer = // ... etc, remembering to include copyright notices :)

Dies hat für mich ziemlich gut funktioniert, insbesondere da das Projekt wächst und ich beginne, meine eigenen Shader und Geometrien in ihre eigenen Module usw.

Solange es ein 'threejs-full' oder 'threejs-classic' npm-Paket gibt, ist dies eine ziemlich praktikable Art, mit altem Three.js-Zeug in einer CommonJS-Umgebung zu arbeiten, aber ich vermute, dies ist eine ziemliche Nische!

+1
Ich glaube, sobald fragmentierte Threejs-Module in npm verfügbar sind, Plugin
Entwickler werden es lieben, zu CommonJS env zu migrieren.
Am 5. Juni 2014 um 21:19 schrieb "Charlotte Gore" [email protected] :

Die knifflige Sache wird sein: Wie benötigen wir () ein bestimmtes Plugin, wenn wir
befinden sich in einer CommonJS-Umgebung?

Ich verwende CommonJS seit einiger Zeit für THREE.js-Projekte. Es ist ein bisschen
eines manuellen Prozesses, der Teile des Codes anderer Leute in Module umwandelt
und ich glaube nicht, dass es eine einfache Möglichkeit geben wird, dies für Legacy-Code zu vermeiden
die nicht von den Autoren oder Mitwirkenden konvertiert wird.

Wichtig ist, dass es ein Modul gibt, das den gesamten 'Standard' exportiert
DREI Objekte, die dann von allem benötigt werden können, was sich erweitern möchte
es.

var DREI = erfordern('drei');
THREE.EffectComposer = // ... usw. Denken Sie daran, Urheberrechtshinweise aufzunehmen :)

Das hat bei mir ziemlich gut funktioniert, zumal das Projekt wächst und ich
fange an, meine eigenen Shader und Geometrien in ihre eigenen Module usw.

Solange es dann ein 'threejs-full' oder 'threejs-classic' npm-Paket gibt
Dies wird eine ziemlich praktikable Art, mit alten Three.js-Sachen in a . zu arbeiten
CommonJS-Umgebung, aber ich vermute, das ist eine ziemliche Nische!


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an
https://github.com/mrdoob/three.js/issues/4776#issuecomment -45236911.

Es könnte auch die Shader modular machen, zB mit glslify . Selbst Dinge wie die Erstellung einer Express-Middleware, die Shader nach Bedarf generiert, werden dann einfacher.

Vor einigen Monaten habe ich frame.js in require.js verschoben und endlich verstanden, wie dieses AMD-Zeug funktioniert.

Ich muss aber noch lernen, wie man das "kompiliert". Was ist das Tool/Workflow zum Generieren eines three.min.js aus einer Liste von Modulen?

Ich bevorzuge gulp.js als Build-System mit dem gulp-browserify- Plugin. Es ist wirklich einfach zu verstehen und der Code sieht meiner Meinung nach sauberer aus als grunzen. Schau dir das an: http://travismaynard.com/writing/no-need-to-grunt-take-a-gulp-of-fresh-air :wink:

einige Gedanken: (basierend auf meiner begrenzten Erfahrung mit node, npm, browserify natürlich)

  1. Ich denke, node.js-Module sind großartig (das sind npm, modules und require()s)
  2. ich finde browserify auch super

Nach der Diskussion in diesem Thread bin ich mir jedoch nicht sicher, ob alle das gleiche Verständnis von browserify hatten (browserify, commonjs, requirejs, amd, umd sind etwas verwandt, obwohl sie möglicherweise nicht dasselbe sind).

Nun, wenn Sie meiner Gedankenkette ein wenig folgen dürfen.

  1. JS ist großartig, es läuft schnell in allen Browsern.
  2. wow, jetzt läuft JS auch serverseitig.
  3. das ist node.js, es ist cool, also lass uns Sachen in node.js programmieren
  4. aber ich will nicht schreiben/ kann nicht alles schreiben/ finde etwas zum gebrauchen.
  5. keine sorge, führe jetzt npm install modules aus
  6. benötigen jetzt diese coolen Module, damit wir sie verwenden können.
  7. funktioniert super!
  8. Jetzt warte, wir haben gerade eine ganze Reihe von Dingen in JS geschrieben, die auf node.js ausgeführt werden
  9. Ist js in Browsern nicht vorgesehen? Wie bringen wir diesen Code dort wieder zum Laufen?

Hier kommt Browserify ins Spiel. Nun, technisch kann man requireJS im Browser verwenden. Aber Sie möchten js-Dateien zusammenfassen, ohne zu viele Netzwerkaufrufe zu tätigen (im Gegensatz zu Dateisystem-Require()s, die schnell sind). Dort macht Browserify einige coole Sachen wie statische Analysen, um zu sehen, welche Module importiert werden müssen, und erstellt Builds, die für Ihre Anwendung optimiert sind. (Es gibt natürlich Einschränkungen, es kann wahrscheinlich nicht parsen require('bla' + Variable)) Es kann sogar Teile austauschen, die eine Emulationsschicht für node.js-abhängiges Zeug erfordern. Ja, es generiert einen js-Build, den ich jetzt in meinen Browser einbinden kann.

Hier sind einige der Dinge, die browserify tun kann https://github.com/substack/node-browserify#usage

Klingt so, als wäre bisher alles großartig ... aber es gibt ein paar Punkte, die ich in Betracht ziehen sollte, wenn wir zu einer "Architektur zum Durchsuchen" wechseln.

  • es muss ein Umdenken für Three.js-Entwickler stattfinden (das Modulsystem muss natürlich verwendet werden)
  • Es kann eine Kompatibilitätsschicht erstellt werden, damit Three.js-Benutzer immer noch Three.js auf die alte Weise verwenden können, ohne die modularen Vorteile zu nutzen
  • Um optimierte Builds erstellen zu können, müssten Three.js-Benutzer zum erforderlichen System wechseln
  • Der neue Build-Prozess würde wahrscheinlich die browserify-Toolchain (derzeit könnten wir Python, node.js oder einfaches Kopieren und Einfügen usw. verwenden) oder einige erforderliche JS-Tools beinhalten.
  • Wenn wir drei.js wirklich modularer machen möchten, mit Versionierung für jede Komponente, wie beispielsweise TrackballControls, müssten wir sie aufteilen, was zu Fragmentierung führen kann
  • das könnte auch zu Vielfalt führen, aber eine Stärke von Three.js scheint derzeit ein zentraler Punkt vieler Erweiterungen zu sein

Wenn wir also diese Vielfalt und das bequeme Laden von Modulen (hauptsächlich auf dem npm-Ökosystem) zusammen mit benutzerdefinierten Builds als großartige Sache ansehen, dann lohnt es sich vielleicht, einen Paradigmenwechsel vorzunehmen, Code zu refaktorisieren und unser aktuelles Build-System zu ändern.

@mrdoob einige Tools rund um browserify sind hier aufgelistet: https://github.com/substack/node-browserify/wiki/browserify-tools.

In Bezug auf three.min.js würden Sie den minimierten Code in Ihrem Projekt nicht verwenden. Alles, was Sie tun, ist var three = require('three') in Ihrem project.js und dann browserify project.js > bundle.js && uglifyjs bundle.js > bundle.min.js auszuführen. Hinweis: Sie können weiterhin minifizierten Code für <script src="min.js"> versenden.

Ich verpacke derzeit Three.js mit

if ('undefined' === typeof(window))
  var window = global && global.window ? global.window : this
var self = window

und

module.exports = THREE

dann wickle ich Erweiterungen mit ein

module.exports = function(THREE) { /* extension-code here */ }

also kann ich es so verlangen:

var three = require('./wrapped-three.js')
require('./three-extension')(three)

das ist also nicht optimal, aber ich persönlich kann damit leben und denke, dass es nicht so schlimm ist - obwohl @kumavis- Vorschlag ein _riesiger_ Vorteil wäre.

aber vielleicht wäre es sinnvoll, drei zu teilen und alle Dinge in separate Module zu legen, nur um zu sehen, wie es funktionieren würde.

Besuchen Sie auch http://modules.gl/, das stark auf browserify basiert (obwohl Sie jedes Modul ohne browserify alleine verwenden können).

@mrdoob @shi-314 gulp-browserify wurde auf die schwarze Liste gesetzt, um browserify nur direkt zu verwenden (dh über Vinyl-Source-Stream).

Tools wie Grunzen/Schlucken/etc sind ständig im Fluss und Sie werden viele unterschiedliche Meinungen finden. Am Ende spielt es keine Rolle, was Sie wählen oder ob Sie es einfach mit einem benutzerdefinierten Skript tun. Die wichtigeren Fragen sind: Wie werden Benutzer ThreeJS nutzen und wie viel Abwärtskompatibilität möchten Sie aufrechterhalten?

Nach einigem Nachdenken denke ich, dass es _wirklich_ schwierig sein wird, alles zu modularisieren, ohne das Framework und seine Architektur vollständig umzugestalten. Hier sind einige Probleme:

  • Der gesamte Namespace-Code muss in CommonJS exports/require geändert werden. Das ist ein ziemlich großes Unterfangen und es gäbe eine Menge hässlicher ../../../math/Vector2 usw.
  • In einer idealen Welt wäre die Bibliothek fragmentiert, also wäre three-scene von three-lights usw. entkoppelt. Dann können Sie jedes Paket separat versionieren. Diese Art der Fragmentierung scheint für ein Framework von der Größe ThreeJS unrealistisch und wäre sehr mühsam beizubehalten.
  • Wenn wir das Framework _nicht_ in winzige Komponenten fragmentieren, wird die semantische Versionierung ein Albtraum. Eine winzige Breaking Change irgendwo im Framework würde einen größeren Versions-Bump für das Ganze erfordern. Und die API zu konsumieren wäre ziemlich hässlich: require('three/src/math/Vector2')

Mein Vorschlag? Wir betrachten zwei Dinge, die vorankommen:

  1. Fangen Sie klein an; Ziehen Sie einige wichtige und wiederverwendbare Funktionen wie Vector/Quaternion, Farbkonvertierungen, Triangulation usw. heraus. Diese Dinge sind gute Kandidaten für NPM, da sie außerhalb des Anwendungsbereichs von ThreeJS nützlich sind. Sie können auch eine eigene Testsuite, Versionierung und Problemverfolgung haben.
  2. Wenn ThreeJS neuer Code hinzugefügt werden muss, wie ein neues Feature oder eine Abhängigkeit (zB poly2tri/Tess2), ziehen Sie es in Betracht, es als separates Modul herauszuziehen und über NPM davon abhängig zu sein.

Ich würde gerne alles modularisiert sehen, aber ich bin mir eines Ansatzes nicht sicher, der für ThreeJS realistisch ist. Vielleicht sollte jemand einige Experimente in einer Gabel machen, um zu sehen, wie machbar die Dinge sind.

Danke für die Erklärungen Jungs!

Was ich befürchte, ist, die Dinge für Leute zu komplizieren, die gerade erst anfangen. Sie zu zwingen, dieses Browserify/Module-Zeug zu lernen, ist möglicherweise keine gute Idee ...

Muss @mrdoob hier zustimmen. Ich und viele Kollegen sind keine Webprogrammierer (eher VFX/Animations-TDs). WebGL und Three in die Hand zu nehmen, war sicherlich genug Arbeit, wie auch zu unserer aktuellen Arbeitsbelastung (und in einigen Fällen mussten einige von uns js sofort lernen). Vieles von dem, was ich in diesem Thread gelesen habe, lässt mich manchmal schaudern, wenn ich daran denke, wie viel mehr Arbeit zu meiner Platte hinzugefügt würde, wenn Three in diese Struktur umziehen würde. Ich könnte mich irren, aber so liest es sich für mich.

Mit einem vorkompilierten UMD-Build ( browserify --umd ) im Repository ändert sich der Workflow für bestehende Entwickler nicht.

@mrdoob Die Idee eines Abhängigkeitsmanagementsystems ist Einfachheit. Das Lesen von Dutzenden von Beiträgen zu Optionen und Build-Systemen mag überwältigend sein, aber letztendlich ist das aktuelle System nicht nachhaltig. Jedes Mal, wenn eine Datei von einer anderen abhängt, ist dies eine Jagd- und- Suche, die jeder neue Entwickler durchführen muss, um eine Referenz zu finden. Bei browserify ist die Abhängigkeit explizit und es gibt einen Pfad zur Datei.

@repsac Ein Abhängigkeitssystem sollte Three für Benutzer anderer Sprachen zugänglicher machen, da es den globalen Geltungsbereich vermeidet, Albträume der Ladereihenfolge vermeidet und einem ähnlichen Paradigma wie bei anderen gängigen Sprachen folgt. var foo = require('./foo'); ist (lose) verwandt mit using foo; von C# oder import foo; Java

Ich würde gerne alles modularisiert sehen, aber ich bin mir eines Ansatzes nicht sicher, der für ThreeJS realistisch ist. Vielleicht sollte jemand in einer Gabel experimentieren, um zu sehen, wie machbar die Dinge sind

Ich denke, das ist wirklich der richtige Weg. Erledigen Sie die Arbeit, zeigen Sie, wie es funktioniert.

Und die API zu verbrauchen wäre ziemlich ugly: require('three/src/math/Vector2')

Als Experiment habe ich gerade die 'Erste Schritte' von den Three docs auf diesen neuen modularen Ansatz umgestellt. Ich kann mir vorstellen, dass es viele Referenzen gibt, es sei denn, die Leute sind ziemlich streng, ihren Code in winzige Module aufzuteilen.

Der Hauptvorteil dabei wäre, dass die resultierende Build-Größe nur einen winzigen Bruchteil der Größe des vollständigen Three.js ausmachen würde, da Sie nur die Dinge einschließen würden, auf die hier speziell verwiesen wird, und dann die Dinge, von denen diese Dinge abhängen.

Ich denke, es könnte sich in der Praxis als etwas zu schrecklich erweisen, auf alle benötigten Abhängigkeiten zu verweisen (und sie alle einzeln zu installieren).

Wenn Sie explizit auf mobile Geräte abzielen, wäre dieser hochgradig granulare Ansatz perfekt, aber in Wirklichkeit benötigen wir Pakete, die die gesamten DREI APIs exportieren, die wie gewohnt funktionieren, und dann kleinere Pakete, die die gesamte Bonusgeometrie kapseln, alle Renderer, die ganze Mathematik, alle Materialien usw., dann bis auf die einzelne Modulebene, damit die Entwickler selbst entscheiden können.

Und ja, das Programmieren für das Web ist mühsam.

Wie auch immer, weiter mit dem Experiment...

Installieren Sie unsere Abhängigkeiten..

npm install three-scene three-perspective-camera three-webgl-renderer three-cube-geometry three-mesh-basic-material three-mesh three-raf

Schreiben Sie unseren Code...

// import our dependencies..
var Scene = require('three-scene'),
  Camera = require('three-perspective-camera'),
  Renderer = require('three-webgl-renderer'),
  CubeGeometry = require('three-cube-geometry'),
  MeshBasicMaterial = require('three-mesh-basic-material'),
  Mesh = require('three-mesh'),
  requestAnimationFrame = require('three-raf');

// set up our scene...
var scene = new Scene();
var camera = new Camera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new Renderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// create the cube...
var geometry = new CubeGeometry(1, 1, 1);
var material = new MeshBasicMaterial({color: 0x00ff00});
var cube = new Mesh(geometry, material);
scene.add(cube);
// position the camera...
camera.position.z = 5;
// animate the cube..
var render = function () {
  requestAnimationFrame(render);
  cube.rotation.x += 0.1;
  cube.rotation.y += 0.1;
  renderer.render(scene, camera);
};
// begin!
render();

dann baue unsere Datei

browserify entry.js -o scripts/hello-world.js

dann füge es in unsere Seite ein

<script src="/scripts/hello-world.js" type="text/javascript"></script>

Ich denke, es könnte sich in der Praxis als etwas zu schrecklich erweisen, auf alle benötigten Abhängigkeiten zu verweisen (und sie alle einzeln zu installieren).

Der Endbenutzer muss in seinem Projekt nicht unbedingt browserify verwenden, damit Three browserify zur Verwaltung seiner Codebasis verwendet. Drei können als globales THREE wie es jetzt ist ... die Build-Datei einschließen und damit ausführen.

@repsac @mrdoob die Änderungen wären abwärtskompatibel, sodass aktuelle Benutzer nichts ändern müssen, wenn sie dies nicht möchten. Diese Vorschläge sollen die langfristige Wartbarkeit und Langlebigkeit der weitläufigen und monolithischen Codebasis von ThreeJS verbessern. Dinge wie Abhängigkeits- und Versionsverwaltung mögen für Uneingeweihte nach Kopfschmerzen klingen, aber sie sind großartig für diejenigen, die Tools, Frameworks, Plugins und große Websites zusätzlich zu ThreeJS entwickeln.

dh der Endbenutzercode kann immer noch gleich aussehen und die examples müssen überhaupt nicht geändert werden:

<script src="three.min.js"></script>

<script>
var renderer = new THREE.WebGLRenderer();
</script>

Für ambitionierte Entwickler, die nach einem modularen Build suchen, _oder_ für diejenigen, die langfristige Lösungen auf ThreeJS entwickeln möchten (dh die Versions-/Abhängigkeitsverwaltung nutzen), könnte es eher so aussehen:
npm install three-vecmath --save

Dann im Code:

var Vector2 = require('three-vecmath').Vector2;

//.. do something with Vector2

Darüber hinaus ermöglicht dies den Benutzern, Dinge wie die Vektormathematik von ThreeJS, Farbkonvertierungen, Triangulation usw. außerhalb des Anwendungsbereichs von ThreeJS zu verwenden.

Auch wenn ich denke, dass das Durcheinander von require() eine schlechte Idee und ein schlechter Kompromiss ist, wäre es eine noch schlimmere Idee, Benutzer zwei verschiedenen Arten von Three.js-Code auszusetzen und den Benutzern zu sagen, dass einer der ausgefallene Modulsystem-Geschmack und der andere der ist einfachere (aber zweitklassige) Modulsystem-Geschmack.

@erno Ich denke, Sie haben den Punkt übersehen, three.js würde intern durch eine Modulstruktur organisiert, aber das wird verwendet, um eine Build-Datei zu erstellen, die sich nicht vom aktuellen Setup unterscheidet.

Der Hauptgewinn besteht darin, die Erfahrung bei der Entwicklung und Wartung von three.js verbessern.

@kumavis - nein @erno hat das nicht wirklich übersehen, aber ich habe verstanden(*), dass er darauf three.js manchmal über require verwendet wird und manchmal nicht. Zum Beispiel schaut sich jemand sowohl die drei Quellen als auch einige Beispiele von Drittanbietern an und stößt auf Unterschiede in der Art und Weise, wie alles ist und funktioniert.

(*) Wir haben heute im IRC darüber gesprochen.

Ich denke, das ist eine Art gültiger Punkt, bin mir aber nicht sicher, ob / wie es am Ende funktioniert - ob es wirklich ein Problem mit der Modul- und Build-Ding-Verwendung ist. Scheint aber sicherlich eine Überlegung wert zu sein und insgesamt hat mir gut geschienen, dass die Gesamtangelegenheit hier sorgfältig bedacht wurde, danke für die bisherigen Infos und Ansichten meinerseits.

@antont Ich sehe. Die Leute haben hier eine Vielzahl von verschiedenen Ansätzen vorgeschlagen, ich ging davon aus, dass wir hauptsächlich Dokumentation für die Verwendung auf höchster Ebene bereitstellen würden (alles von THREE abziehen), aber andere könnten Beispiele erstellen, die diesem nicht folgen würden, und es kann sein zu einiger Verwirrung führen. Und das ist ein berechtigtes Anliegen.

Ich glaube, die Sprache hat mich etwas verwirrt.

und das andere ist das einfachere (aber zweitklassige) Modulsystem-Geschmack.

Dies bezieht sich nur auf die Build-Datei, ja?

Nach meinem Verständnis ja. Ich kann mir nicht vorstellen, was anderes, aber es kann etwas fehlen.

antont, kumavis: In den Vorschlägen hier ging es darum, den Code im Stil von require() auch Endbenutzern zur Verfügung zu stellen, siehe zB. Der neueste Kommentar von mattdesl.

"Für ambitionierte Entwickler, die nach einem modularen Build suchen, oder für diejenigen, die langfristige Lösungen auf der Grundlage von ThreeJS entwickeln möchten (dh die Versions-/Abhängigkeitsverwaltung nutzen) [...]"

Eine Möglichkeit zu optimierten Builds besteht darin, ein Skript zu verwenden, das Ihre Abhängigkeiten automatisch ermittelt und die erforderlichen Module ausgibt.

Im Moment verzichtet Bower & browserify auf require, aber das sind nicht die einzigen Lösungen. Ich weiß nicht, ob es andere Open-Source-Projekte von der Stange gibt, die dies tun (vielleicht wie ng-Abhängigkeiten), aber ich habe solche Tools schon früher geschrieben, von denen ich denke, dass es andere Ansätze zur Lösung dieser Probleme geben würde.

Der Closure-Compiler von Google könnte ein solches Tool sein?

Könnte dies auf der Benutzerseite eine Hilfe sein?
http://marcinwieprzkowicz.github.io/three.js-builder/

das ist ziemlich interessant @erichlof :) ich frage mich, ob @marcinwieprzkowicz das von Hand generiert hat ... https://github.com/marcinwieprzkowicz/three.js-builder/blob/gh-pages/threejs-src/r66/modules.json

Eine Methode, die Three.js verwendet, die die Verwendung in Commonjs-Umgebungen schwierig macht, ist die Verwendung von instanceof: https://github.com/mrdoob/three.js/blob/master/src/core/Geometry.js#L82

Dies liegt daran, dass Sie in einer Anwendung oft unterschiedliche Versionen derselben Bibliothek in Ihrem Quellbaum haben, sodass das Überprüfen von instanceof zwischen verschiedenen Versionen derselben Bibliothek nicht funktioniert. Als Vorbereitung für einen Wechsel zu einem Commonjs-Modulsystem wäre es gut, diese Instanzüberprüfungen durch die Merkmalsprüfung hinter einer Schnittstelle im Stil von Geometry.isGeometry(geom) zu ersetzen.

in git/three.js/src:

grep -r instanceof . | wc -l 
164

in git/three.js/examples:

grep -r instanceof . | wc -l 
216

es gibt also insgesamt 380 Verwendungen von instanceof in Three.js. Was wäre die beste Implementierung als Ersatz?

Ich habe kürzlich eine type Eigenschaft hinzugefügt, die verwendet werden kann, um die meisten davon zu ersetzen.

Ich habe vor kurzem eine type-Eigenschaft hinzugefügt, die verwendet werden kann, um die meisten davon zu ersetzen.

nett! Werde eine PR vorbereiten.

Ein Beispiel dafür, wie dies in einer anderen beliebten und großen JS-Bibliothek gehandhabt wird, finden Sie unter https://github.com/facebook/react . Die Codebasis ist mit dem Node-Style-basierten Modulsystem (das browserify implementiert) strukturiert, aber für die Veröffentlichung mit Grunt gebaut. Diese Lösung ist flexibel für 3 Anwendungsfälle.

  1. Reine Verbraucher von Three.js, die Vanilla JS schreiben, können immer noch die Build-Datei wie immer verwenden. Für diesen Anwendungsfall gibt es keine Änderung.
  2. Consumer von Three.js, die browserify verwenden, können Three.js als Abhängigkeit in einem Projekt und nur require spezifische Abhängigkeiten deklarieren. Die Vorteile eines geeigneten Abhängigkeitsmanagements sind gut dokumentiert.
  3. Der Beitrag zu Three.js sollte jetzt einfacher sein, da Abhängigkeiten zwischen Komponenten explizit dokumentiert sind.

Ich habe etwas recherchiert...

Gestern habe ich ein (eher dummes) Skript gehackt, das den Three.js-Quellcode so umwandelt, dass er CommonJS require() Anweisungen verwendet, um Abhängigkeiten zwischen Dateien zu deklarieren. Nur um zu sehen, was passiert... Das:

  1. Es endet mit ziemlich lächerlichen Anforderungsanweisungen wie dieser (von WebGLRenderer):

var THREE = require('../Three.js'); require('../math/Color.js'); require('../math/Frustum.js'); require('../math/Matrix4.js'); require('../math/Vector3.js'); require('./webgl/WebGLExtensions.js'); require('./webgl/plugins/ShadowMapPlugin.js'); require('./webgl/plugins/SpritePlugin.js'); require('./webgl/plugins/LensFlarePlugin.js'); require('../core/BufferGeometry.js'); require('./WebGLRenderTargetCube.js'); require('../materials/MeshFaceMaterial.js'); require('../objects/Mesh.js'); require('../objects/PointCloud.js'); require('../objects/Line.js'); require('../cameras/Camera.js'); require('../objects/SkinnedMesh.js'); require('../scenes/Scene.js'); require('../objects/Group.js'); require('../lights/Light.js'); require('../objects/Sprite.js'); require('../objects/LensFlare.js'); require('../math/Matrix3.js'); require('../core/Geometry.js'); require('../extras/objects/ImmediateRenderObject.js'); require('../materials/MeshDepthMaterial.js'); require('../materials/MeshNormalMaterial.js'); require('../materials/MeshBasicMaterial.js'); require('../materials/MeshLambertMaterial.js'); require('../materials/MeshPhongMaterial.js'); require('../materials/LineBasicMaterial.js'); require('../materials/LineDashedMaterial.js'); require('../materials/PointCloudMaterial.js'); require('./shaders/ShaderLib.js'); require('./shaders/UniformsUtils.js'); require('../scenes/FogExp2.js'); require('./webgl/WebGLProgram.js'); require('../materials/ShaderMaterial.js'); require('../scenes/Fog.js'); require('../lights/SpotLight.js'); require('../lights/DirectionalLight.js'); require('../textures/CubeTexture.js'); require('../lights/AmbientLight.js'); require('../lights/PointLight.js'); require('../lights/HemisphereLight.js'); require('../math/Math.js'); require('../textures/DataTexture.js'); require('../textures/CompressedTexture.js');

Wir würden einige große Umgestaltungen benötigen, vielleicht den WebGLRenderer (und dergleichen) in mehrere Module aufteilen (die Datei ist über 6000 Zeilen lang).

  1. Wir müssen eine Lösung für die GLSL-Blöcke finden. Atm werden diese Dateien zur Kompilierzeit in THREE.ShaderChunk kompiliert und dann zur Laufzeit in THREE.ShaderLib (Verknüpfung von Arrays von THREE.ShaderChunk s), was nur mit browserify ziemlich knifflig ist. Ich nehme an, es würde eine browserify-Transformation erfordern, die das gleiche tut.

React.js verwendet Commoner, um ihre Module zu suchen, ohne dass sie über den Dateipfad darauf verweisen müssen. Vielleicht könnten wir dasselbe tun und auch benutzerdefinierte Regeln definieren, die es uns ermöglichen, require GLSL-Dateien in die JS-Syntax umzuwandeln.

@rasteiner Sie können sehr glücklich sein , um zu erfahren , https://github.com/stackgl/glslify , es kommt aus der wachsenden http://stack.gl Familie

Ich habe in den letzten Monaten einiges an Erfahrung mit Modulen und dem "Unixy"-Ansatz gemacht und denke jetzt, dass es zu wenig zu spät ist und das Refactoring von Threejs für Modularität oder npm-Module ein unrealistisches Ziel wäre.

Folgendes tue ich derzeit, um das Problem der Modularität/Wiederverwendbarkeit anzugehen:

  • Ich setze einige wiederverwendbare Shader für Blur/fxaa/etc auf NPM ein. Sieh dir das an:
    https://www.npmjs.org/package/three-shader-fxaa (verwendet Engine-unabhängiges glsl-fxaa)
  • auch wiederverwendbare Komponenten wie OrbitController und EffectComposer werden nach Bedarf veröffentlicht. Z.B:
    https://www.npmjs.org/package/three-orbit-controls
  • anstatt von "drei" abhängig zu sein, exportieren diese Module eine Funktion, die DREI aufnimmt und die Dienstprogrammklasse zurückgibt. Auf diese Weise kann es mit globalen Threejs oder Commonjs verwendet werden.
  • Versionierung ist eine Qual. Ich versuche, meine Hauptversionen an den Releasenummern von Threejs auszurichten. Jede neue Version von Threejs bringt viele grundlegende Änderungen mit sich, daher muss sie sorgfältig behandelt werden.
  • Module, die sich mit Mathematik befassen, sollten nur auf Arrays arbeiten und modular gl-vec3, gl-mat4 usw. verwenden. Auf diese Weise sind sie generisch und außerhalb von Threejs nützlich. Dann müssen Threejs-Benutzer nur noch das Ein-/Auspacken in Arrays handhaben. Siehe Verlet-System, Simplify-Pfad usw.
  • Wenn ich eine wirklich modulare oder winzige webGL-Funktion benötige, verwende ich in Zukunft stackgl/glslify. Diese können auch innerhalb von ThreeJS funktionieren, solange Sie den GL-Status zurücksetzen. ZB: https://www.npmjs.org/package/gl-sprite-text

Meine neuen Projekte neigen dazu, "drei" auf npm zu verwenden, nur um zum Laufen zu kommen. Es wäre ziemlich großartig, wenn ThreeJS den Build offiziell für npm veröffentlichen würde, indem Versions-Tags verwendet werden, die mit den Release-Nummern übereinstimmen.

PS: an diejenigen, die daran interessiert sind, wiederverwendbare/modulare Shader in ihren Workflow zu integrieren:
https://gist.github.com/mattdesl/b04c90306ee0d2a412ab

von meinem Iphone gesendet

Am 20. November 2014 um 7:42 Uhr schrieb aaron [email protected] :

@rasteiner Sie können sehr glücklich sein , um zu erfahren , https://github.com/stackgl/glslify , es kommt aus der wachsenden http://stack.gl Familie


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an.

Im Fall hilft es , andere , die vielleicht suchen , wie Three.js mit browserify zu verwenden, und stolpert auf diesem Thread, so , wie ich es gerade eingerichtet habe ich verwenden browserify-Shim .

Nach dem README-Abschnitt zu _"Sie werden manchmal a) globale Variablen über global verfügbar machen"_ habe ich ein separates Skript-Tag für Three.js eingefügt und es so konfiguriert, dass es die globale Variable THREE verfügbar macht.

Und dann musste ich nur noch herausfinden, wie man Extras wie ColladaLoader, OrbitControls usw. einfügt. Ich habe das so gemacht:

Von package.json:

    "browser": {
        "three": "bower_components/threejs/build/three.js"
    },
    "browserify-shim": "browserify-shim-config.js",
    "browserify": {
        "transform": [ "browserify-shim" ]
    }

browserify-shim-config.js:

    module.exports = {
        "three": { exports: "global:THREE" },
        "./vendor/threejs-extras/ColladaLoader.js": { depends: {"three": null}, exports: "global:THREE.ColladaLoader" },
        "./vendor/threejs-extras/OrbitControls.js": { depends: {"three": null}, exports: "global:THREE.OrbitControls" }
    };

Dann in meinem eigenen Skript main.js:

    require('../vendor/threejs-extras/ColladaLoader.js');
    require('../vendor/threejs-extras/OrbitControls.js');

    var loader = new THREE.ColladaLoader(),
        controls = new THREE.OrbitControls(camera);
...

Browserify erfordert den Neuaufbau des gesamten Skripts, wenn Sie sogar Bytes ändern. Ich benutze browserify einmal, um ein Projekt zu packen, das THREE.js erfordert, dann dauert es mehr als zwei Sekunden, um ein Boundle zu bauen, und blockiert die Livereload jedes Mal, wenn ich eine Änderung vornehme. Das ist zu frustrierend.

Watchify wird normalerweise während der Entwicklung mit Livereload verwendet. Dieser baut das Bundle inkrementell auf.

Watchify funktioniert bei mir nicht. Wenn ich eine Datei ändere und speichere, liefern watchify und beefy's Livereload die ältere / zwischengespeicherte Version. Ich habe keine Ahnung, warum das passiert. Zum Glück funktioniert browserify bereits ziemlich gut.

@ChiChou Pass in --noparse=three zum Browserify. Dadurch wird der Browserify-Bundle-Schritt von 1000 ms auf 500 ms auf meinem Computer reduziert, was für ein sofortiges Feedback-Feeling anständig genug ist.

@rasteiner Ich möchte Ihnen noch einmal für Ihre informelle Recherche zu den wechselseitigen Abhängigkeiten von Three.js danken. Während diese riesige Liste von Deps ein hässlich aussehender Code ist, ist diese Hässlichkeit tatsächlich vorhanden, nur unsichtbar. Die Stärke von Browserify besteht darin, dass wir unsere schmutzige Wäsche lüften und weniger verworrene Systeme verfolgen müssen.

Es gibt viele Stellen in Three.js, an denen wir ein Objekt aufnehmen, seinen Typ wahrnehmen und basierend auf diesem Typ verschiedene Aufgaben ausführen. In den meisten Fällen könnte dieser typabhängige Code in den Typ selbst verschoben werden, und wir müssten nicht alle möglichen Typen kennen, mit denen wir arbeiten.

Das Folgende ist ein gekürztes Beispiel von WebGLRenderer :

if ( texture instanceof THREE.DataTexture ) {
  // ...
} else if ( texture instanceof THREE.CompressedTexture ) {
  // ...
} else { // regular Texture (image, video, canvas)
  // ...
}

sollte mehr von der form sein

texture.processTexImage( _gl, mipmaps, otherData )

Lassen Sie den Typ bestimmen, wie er sich selbst behandelt. Dies ermöglicht es dem Bibliotheksbenutzer auch, neuartige Texturtypen zu verwenden, an die wir nicht gedacht hatten. Diese Struktur soll Interdependenzen reduzieren.

Ich denke, der Wechsel zu einer browserbasierten Architektur ist definitiv der richtige Weg. Der UMD-Build erleichtert die Nutzung von THREE.js. Es wird uns auch ermöglichen, den WebGLRenderer in mehrere Dateien aufzuteilen, da er im Moment ziemlich monolithisch und beängstigend aussieht.

Ich habe einen Branch gestartet, in dem ich derzeit daran arbeite, ihn hierher zu verschieben: https://github.com/coballast/three.js/tree/browserify-build-system

Bitte sag mir was du denkst.

Hier sind die Änderungen von @coballast .

Es sieht so aus, als ob Sie mit Ihrer browserifyify.js Datei den automatisierten Konvertierungsansatz verfolgen, was meiner Meinung nach der richtige Weg ist.

Eine Sache, über die wir alle noch nicht viel gesprochen haben, ist, wie man diese große, sich ständig ändernde Bibliothek am besten auf browserify umstellt. Sie können die Änderungen vornehmen und dann eine PR öffnen, die jedoch sofort veraltet ist. Das ist das überzeugende an dem automatisierten Ansatz.

Wenn wir können:

  • Stellen Sie ein Three.js src-Konvertierungsskript bereit (wie Ihr browserifyify.js )
  • ein Dokument bereitstellen, das erklärt, wie der Konvertierungsprozess funktioniert
  • ein Dokument bereitstellen, das erklärt, wie das neue Build-System funktioniert
  • Führen Sie Tests nach der Konvertierung durch
  • keine Änderungen an bestehenden Dateien einschließen, die zu einem Zusammenführungskonflikt führen könnten

...dann können wir daraus einen Umbau auf Knopfdruck machen, der auf absehbare Zeit noch funktioniert. Diese Einfachheit ermöglicht es, diese verträumte Vorstellung einer grundlegenden Architekturverschiebung zu einem so großen Projekt zu verwirklichen, wenn die ideologischen Argumente gewinnen.

@coballast zu diesem Zweck würde ich die Änderungen an src/

Hinweis: Nicht nur rückgängig machen, sondern diese Änderungen über einen neuen Branch oder einen Force-Push aus dem Branch-Verlauf entfernen

@coballast Ich frage mich, ob es sinnvoller wäre, wenn das Konvertierungsdienstprogramm keine Abzweigung von three.js , sondern ein externes Dienstprogramm, das Sie auf das Entwicklungsverzeichnis von three.js , und es konvertiert die Quelle -Dateien, fügt ein Build-Skript hinzu und führt die Tests aus.

@kumavis Ich bin damit einverstanden, das src-Verzeichnis in Ruhe zu lassen. Ich denke, das Dienstprogramm muss ein doppeltes Verzeichnis mit dem Commonjs-Code schreiben, und wir können den browserify-Build von dort aus testen und ausführen, um sicherzustellen, dass die Beispiele alle funktionieren, bevor wir versuchen, etwas Wichtigeres zu tun.

Es gibt hier auch eine interessante Gelegenheit, statische Analysen zu schreiben, die automatisch einen konsistenten Stil in der gesamten Codebasis überprüfen und erzwingen.

@coballast hört sich gut an.
Es gibt eine Fülle von Tools für das automatisierte Umschreiben von Code, zB escodegen . Wir müssen sicherstellen, dass Kommentare usw. gepflegt werden.
Möchten Sie ein Threejs-Conversion-Utility-Repo starten?

@coballast Abgesehen davon ist es wichtig, einen scharfen Fokus auf dieses Dienstprogramm zu

@kumavis Betrachten Sie es als erledigt. Ich möchte wirklich, dass dies geschieht. Dies ist nur eines von zwei Projekten, an denen ich gerade arbeite.

@kumavis @mrdoob Ein Teil der Diskussion hier scheint sich um die Idee zu

Ich bin gespannt, was die Ausgabe dieses Dienstprogramms ist ^^

@coballast verlinkt ein Repo, das wir verfolgen können, auch wenn es an dieser Stelle nur leer ist. Von dort aus können wir bauen.

https://github.com/coballast/threejs-browserify-conversion-utility

Der Code ist ein Durcheinander, wird bald aufgeräumt.

Auf geht's! :Rakete:

Ich habe das Dienstprogramm jetzt in einem Zustand, in dem es browserify src generiert und es ohne Probleme erstellen wird. Ich werde das Repo mit Anweisungen aktualisieren, wie Sie dies selbst tun können. An dieser Stelle funktionieren die Beispiele nicht. Es gibt mehrere Probleme, die behandelt werden müssen, um das zu beheben. Ich werde sie dem Repo hinzufügen, wenn jemand die Ärmel hochkrempeln und helfen möchte.

@coballast ja, bitte

Es sind ernsthafte Probleme aufgetreten. Siehe #6241

Hier ist meine Analyse, was passieren müsste, damit dies funktioniert: https://github.com/coballast/threejs-browserify-conversion-utility/issues/9#issuecomment -83147463

browserify ist aufgrund seines Designs zumindest transportredundant (konjestiv). Dies macht die Nutzungskosten inflatorisch (Datentarif irgendjemand?) und langsam.

Eine einfache Abhilfe besteht darin, das Dokument vom Bibliothekscode zu trennen, was zwei Client-Dateien und nicht eine zur Folge hätte. Dies ist gängige Praxis für clientseitige js.

Wenn browserify am Anfang fehlerhaft ist und selbst behoben werden muss, kann ich kaum einsehen, warum es überhaupt in Betracht gezogen werden sollte, etwas zu verbessern, geschweige denn so etwas wie Threejs.

@spaesani Weil die Daten für Threejs sowieso heruntergeladen werden müssen. Wenn wir Threejs in kleinere Module aufteilen und einem automatisierten Build-System überlassen, was es für eine einzelne App benötigt, wären die meisten Threejs-Apps tatsächlich leichter.

Wenn Sie aus irgendeinem Grund immer noch "Dokument vom Bibliothekscode" trennen möchten, können Sie dies immer noch tun und eine vorgefertigte Version verwenden, wie wir es jetzt tun. Sie können Ihre von Browserify erstellte App sogar in separate Module aufteilen, indem Sie die Flags

Browserify ist nur eine Möglichkeit, eine kampferprobte Moduldefinitions-API (CommonJS) im Browser zu verwenden. Es würde die Entwicklung von Threejs-Plugins erheblich vereinfachen und die Code-Klarheit und damit die Produktivität verbessern. Es würde uns die Integration in ein größeres Ökosystem (npm) ermöglichen, in dem der Code von Natur aus von mehr Leuten gepflegt wird, während die Integrität durch das Versionierungssystem erhalten bleibt (denken Sie an die stackgl- Familie), und es würde die Leute nicht einmal zu CommonJS zwingen, wenn sie es nicht wollen.

Natürlich gibt es Nachteile, aber das sind nicht die, die Sie erwähnt haben.

Three.js und Three.min.js können zwischengespeichert werden, um Transport (Daten) zu sparen, sei es durch einen Proxy, die gängige mobile Lösung oder einen Caching-Browser.
In dem Moment, in dem Sie den Threejs-Code mit dokumentspezifischem Code auswählen und aggregieren, ist das Caching nicht machbar.
Wenn browserify es erlaubt,