Un avantage est que cela imposerait une architecture modulaire pour le développement continu de three.js.
Le style commun dans node/browserify fait que chaque fichier déclare ses dépendances en haut et considère les variables globales comme un anti-modèle.
Voici un exemple d'extrait :
// src/geometry/BoxGeometry.js
var Geometry = require('./Geometry.js');
var Vector3 = require('../core/Vector3.js');
module.exports = BoxGeometry;
function BoxGeometry() {
// ...
}
BoxGeometry.prototype = Geometry.prototype;
Un autre avantage est que les consommateurs de three.js
utilisant browserify seraient en mesure de choisir les pièces qu'ils souhaitent. Ils pourraient simplement importer Scene
, BoxGeometry
, PerspectiveCamera
, et WebGLRenderer
, obtenir les dépendances pour tous ceux-ci automatiquement ( Object3D
etc ), et ont un petit paquet de javascript qui prend en charge uniquement l'ensemble de fonctionnalités qu'ils souhaitent.
Cela pourrait être fait d'une manière qui n'impose aucun changement de rupture. Au niveau supérieur, nous exporterions toutes les classes que nous considérons comme faisant partie du package standard
// src/three.js
var THREE = { rev: 101 }
module.exports = THREE
THREE.Geometry = require('./geometry/Geometry.js')
THREE.BoxGeometry = require('./geometry/BoxGeometry.js')
// ...
note : je n'exige pas exactement les dépendances en haut dans cet exemple, car ce fichier serait presque exclusivement des instructions require.
Enfin, nous encapsulerions cela dans une définition de module universelle qui détecte si un système de module (nœud/navigateur, AMD) est en cours d'utilisation, et si c'est le cas, l'exporte ou l'ajoute à l'objet global ( window
).
Revoyons:
three.js
utilisant browserify de choisir des fonctionnalitésCela nécessiterait de remplacer le système de construction, mais le nouveau serait assez simple.
Quelques autres avantages :
@shi-314 Je suppose que je suis un peu confus, j'ai l'impression que You can structure your code
et You can build for production
sont des choses que vous pouvez faire sans le changement architectural ? Parlez-vous de la source de three.js ou de choses construites à l'aide de three.js ?
Une pratique que three.js utilise et qui la rend difficile à utiliser dans les environnements commonjs est l'utilisation de instanceof
: https://github.com/mrdoob/three.js/blob/master/src/core/Geometry .js#L82
En effet, dans une application, vous vous retrouvez souvent avec différentes versions de la même bibliothèque dans votre arborescence source, donc la vérification d'instanceof ne fonctionne pas entre différentes versions de la même bibliothèque. Il serait bon, en prévision d'un passage à un système de modules commonjs, de remplacer ces instances de vérification par une vérification des fonctionnalités derrière une interface de style Geometry.isGeometry(geom)
.
@kumavis Je parle de choses construites dans three.js. Supposons que vous souhaitiez créer votre propre matériel avec vos shaders, etc. Pour le moment, vous devez étendre l'objet global THREE pour rester cohérent avec le reste du code three.js :
THREE.MeshMyCoolMaterial = function (...) { ... }
Mais si nous avions Browserify que vous ne pourriez faire :
var MeshLambertMaterial = require('./../MeshLambertMaterial');
var MeshMyCoolMaterial = function (...) {...}
Ainsi, votre espace de noms reste cohérent et vous n'avez pas besoin d'utiliser THREE.MeshLambertMaterial
et MeshMyCoolMaterial
dans votre code.
Et avec You can build for production
je voulais dire en gros la même chose que vous avez mentionnée : allows three.js consumers using browserify to pick and choose functionality
.
@shi-314 merci, c'est plus clair. Cela a un impact sur ma solution générale proposée pour la désérialisation des classes définies par le consommateur :
// given that `data` is a hash of a serialized object
var ObjectClass = THREE[ data.type ]
new ObjectClass.fromJSON( data )
Ceci provient de mon refactor de sérialisation / désérialisation proposé
https://github.com/mrdoob/three.js/pull/4621
Les performances ne devraient pas être affectées par un changement comme celui-ci.
C'est un changement assez énorme, mais je suis également en faveur de cela.
Quelques autres avantages majeurs :
standalone
browserify pour générer une version UMD pour vous. Pas besoin de bricoler manuellement avec les wrappers UMD.threejs-vecmath
sans nous soucier de la rupture de code de tout le monde. Et d'un autre côté, si nous faisons un correctif ou une version mineure dans un module particulier, les personnes utilisant ces modules pourront obtenir les modifications automatiquement.npm install threejs-shader-bloom
)require()
les modules que notre application utilise réellement.À @mrdoob et aux autres auteurs ; si vous n'avez pas beaucoup d'expérience avec NPM/Browserify, je vous suggère de faire quelques petits projets avec et de vous faire une idée de sa "philosophie". C'est très différent de l'architecture ThreeJS ; plutôt que de grands frameworks, il encourage beaucoup de petites choses .
Un autre avantage de cette approche est qu'il peut y avoir un écosystème de modules tiers open source, Three.JS, en particulier des shaders, des géométries, des chargeurs de modèles, etc. Publié via NPM ou Github/Component que les gens peuvent ensuite facilement référencer et utiliser. Pour le moment, les choses sont partagées en hébergeant une démo sur laquelle les gens 'visualisent la source'. Three.JS mérite mieux !
Je pense que l'un des problèmes que j'ai avec Three.JS est la rapidité avec laquelle le code devient incompatible avec la version actuelle de Three.JS. Un autre avantage de passer à quelque chose comme ça est de pouvoir spécifier des versions spécifiques de _bits_ de Three.JS serait très puissant et pratique.
+1
+1 pour une architecture CommonJS/browserify, cela rendrait le noyau plus léger et les extensions s'adapteraient même si elles proviennent de tiers
La fragmentation de three.js en petits modules a également beaucoup de coûts. Le système actuel permet des addons tiers assez simples (témoin par exemple les modules THREEx de jetienne). Il y a beaucoup à dire sur la simplicité de la configuration actuelle, tant que les systèmes de modules JS ne sont que des enveloppes autour des systèmes de construction.
Une autre façon de minimiser la taille de la construction est ce que fait ClojureScript. Ils suivent certaines conventions pour permettre au compilateur Closure de Google d'effectuer une analyse de l'ensemble du programme et l'élimination du code mort.
+1 pour l'élégance de la simplicité méconnue et souvent négligée
+1
La fragmentation de three.js en petits modules a également beaucoup de coûts. Le système actuel permet des addons tiers assez simples (témoin par exemple les modules THREEx de jetienne).
L'idée ici est qu'une version UMD serait toujours fournie pour les environnements non-Node. Des plugins comme THREEx fonctionneraient de la même manière pour ceux qui dépendent de ThreeJS avec de simples balises <script>
.
Le plus délicat sera : comment require()
un plugin particulier si nous sommes dans un environnement CommonJS ? Peut-être que browserify-shim pourrait vous aider.
Il y a beaucoup à dire sur la simplicité de la configuration actuelle, tant que les systèmes de modules JS ne sont que des enveloppes autour des systèmes de construction.
Le système de plugin/extension actuel de ThreeJS est assez horrible à utiliser, et loin d'être "simple" ou facile. La plupart des projets ThreeJS ont tendance à utiliser une forme de plugin ou d'extension, comme EffectComposer, ou FirstPersonControls, ou un chargeur de modèle, ou l'un des nombreux autres fichiers JS flottant dans le dossier examples
. À l'heure actuelle, la seule façon de dépendre de ces plugins :
vendor
Maintenant, imaginez, avec browserify, vous pourriez faire quelque chose comme ceci :
var FirstPersonControls = require('threejs-controls').FirstPersonControls;
//more granular, only requiring necessary files
var FirstPersonControls = require('threejs-controls/lib/FirstPersonControls');
Ces plugins seront require('threejs')
et tout ce dont ils pourraient avoir besoin (comme les extraits de code GLSL ou la triangulation de texte ). La gestion des dépendances/versions est entièrement cachée à l'utilisateur, et il n'est pas nécessaire de gérer manuellement les tâches de concat de grunt/gulp.
Le plus délicat sera : comment exiger () un plugin particulier si nous sommes dans un environnement CommonJS ?
J'utilise CommonJS pour les projets THREE.js depuis un certain temps maintenant. C'est un peu un processus manuel, la conversion de morceaux de code d'autres personnes en modules et je ne pense pas qu'il y aura un moyen facile d'éviter cela pour le code hérité qui n'est pas converti par les auteurs ou les contributeurs.
Le point important est qu'il existe un module exportant l'intégralité de l'objet THREE « standard », qui peut ensuite être requis par tout ce qui souhaite l'étendre.
var THREE = require('three');
THREE.EffectComposer = // ... etc, remembering to include copyright notices :)
Cela a plutôt bien fonctionné pour moi, d'autant plus que le projet grandit et que je commence à ajouter mes propres shaders et géométries dans leurs propres modules, etc.
Tant qu'il existe un package npm 'threejs-full' ou 'threejs-classic', cela devient un moyen assez viable de travailler avec d'anciens éléments Three.js dans un environnement CommonJS, mais je soupçonne que c'est une niche!
+1
Je crois qu'une fois les modules threejs fragmentés sont disponibles dans npm, plugin
les développeurs adoreront migrer vers CommonJS env.
Le 5 juin 2014 à 21h19, "Charlotte Gore" [email protected] a écrit :
Le plus délicat sera : comment exiger () un plugin particulier si nous
sont dans un environnement CommonJS ?J'utilise CommonJS pour les projets THREE.js depuis un certain temps maintenant. C'est un peu
d'un processus manuel, convertissant des morceaux de code d'autres personnes en modules
et je ne pense pas qu'il y aura un moyen facile d'éviter cela pour le code hérité
qui n'est pas converti par les auteurs ou contributeurs.L'important est qu'il y ait un module exportant l'intégralité du "standard"
TROIS objet, qui peut alors être requis par tout ce qui souhaite étendre
ce.var TROIS = require('trois');
THREE.EffectComposer = // ... etc, en n'oubliant pas d'inclure les mentions de copyright :)Cela a plutôt bien fonctionné pour moi, d'autant plus que le projet grandit et que je
commencer à ajouter mes propres shaders et géométries dans leurs propres modules, etc.Tant qu'il y a un package npm 'threejs-full' ou 'threejs-classic' alors
cela devient un moyen assez viable de travailler avec d'anciens éléments Three.js dans un
Environnement CommonJS mais je soupçonne que c'est un joli créneau !-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -45236911.
Cela pourrait également rendre les shaders modulaires, par exemple en utilisant glslify . Même des choses comme la création d'un middleware Express qui génère des shaders à la demande deviennent alors plus faciles.
Il y a quelques mois, j'ai déplacé frame.js vers require.js et j'ai enfin compris comment fonctionnait ce matériel AMD.
J'ai encore besoin d'apprendre, cependant, comment "compiler" ceci. Quel est l'outil/workflow pour générer un three.min.js
partir d'une liste de modules ?
Je préfère gulp.js comme système de build avec le plugin gulp-browserify . C'est vraiment facile à comprendre et le code semble plus propre que grunt à mon avis. Vérifiez ceci : http://travismaynard.com/writing/no-need-to-grunt-take-a-gulp-of-fresh-air :wink:
quelques réflexions : (basé sur mon expérience limitée avec node, npm, browserify bien sûr)
cela dit, suite à la discussion sur ce fil, je ne sais pas si tout le monde avait la même compréhension de browserify (browserify, commonjs, requirejs, amd, umd sont quelque peu liés bien qu'ils ne soient pas nécessairement la même chose).
maintenant si vous pouvez suivre un peu ma chaîne de pensées.
C'est là que Browserify entre en jeu. Eh bien, techniquement, on peut utiliser requireJS dans le navigateur. Mais vous souhaitez regrouper les fichiers js sans faire trop d'appels réseau (contrairement aux exigences du système de fichiers () qui sont rapides). C'est là que Browserify fait des trucs sympas comme l'analyse statique pour voir quels modules doivent être importés et crée des builds qui sont plus optimisés pour votre application. (Il y a bien sûr des limitations, il ne peut probablement pas analyser require('bla' + variable)) il peut même échanger des parties qui nécessitent une couche d'émulation pour les éléments dépendants de node.js. oui, il génère une version js que je peux maintenant inclure dans mon navigateur.
Voici quelques-unes des choses que browserify peut faire https://github.com/substack/node-browserify#usage
On dirait que tout va bien jusqu'à présent... mais il y a quelques points que j'ai pensé qu'il valait la peine de considérer que nous passons à une "navigation architecturale"
Donc, si nous voyons que cette diversité et ce chargement de module pratique (principalement sur l'écosystème npm) ainsi que des versions personnalisées sont une bonne chose, alors cela pourrait valoir la peine d'avoir un changement de paradigme, de refactoriser le code et de changer notre système de construction actuel.
@mrdoob certains outils autour de browserify sont répertoriés ici : https://github.com/substack/node-browserify/wiki/browserify-tools.
concernant le three.min.js
, vous n'utiliseriez pas le code minifié dans votre projet. tout ce que vous faites est de var three = require('three')
dans votre project.js
, puis exécutez browserify project.js > bundle.js && uglifyjs bundle.js > bundle.min.js
. Remarque : vous pouvez toujours envoyer du code minifié pour <script src="min.js">
.
j'enveloppe actuellement three.js avec
if ('undefined' === typeof(window))
var window = global && global.window ? global.window : this
var self = window
et
module.exports = THREE
puis j'enveloppe les extensions avec
module.exports = function(THREE) { /* extension-code here */ }
donc je peux l'exiger comme ça:
var three = require('./wrapped-three.js')
require('./three-extension')(three)
ce n'est donc pas optimal, mais personnellement, je peux vivre avec et je pense que ce n'est pas si mal - bien que la proposition de
mais peut-être qu'il serait logique d'en diviser trois et de mettre toutes les choses dans des modules séparés juste pour voir comment cela fonctionnerait.
consultez également http://modules.gl/ qui est fortement basé sur browserify (bien que vous puissiez utiliser chaque module seul sans browserify).
@mrdoob @shi-314 gulp-browserify a été mis sur liste noire en faveur de l'utilisation directe de browserify (c'est-à-dire via vinyl-source-stream).
Des outils comme grunt/gulp/etc sont en constante évolution et vous trouverez de nombreuses opinions divergentes. En fin de compte, peu importe ce que vous choisissez, ou si vous le faites simplement avec un script personnalisé. Les questions les plus importantes sont les suivantes : comment les utilisateurs consommeront-ils ThreeJS et quel degré de compatibilité ascendante souhaitez-vous maintenir ?
Après réflexion, je pense qu'il sera _vraiment_ difficile de tout modulariser sans refactoriser complètement le framework et son architecture. Voici quelques problèmes :
../../../math/Vector2
laids, etc.three-scene
serait découplé de three-lights
etc. Ensuite, vous pouvez versionner chaque package séparément. Ce type de fragmentation semble irréaliste pour un framework aussi grand que ThreeJS, et serait un casse-tête à maintenir.require('three/src/math/Vector2')
Ma suggestion? Nous considérons deux choses pour l'avenir :
J'aimerais que tout soit modularisé, mais je ne suis pas sûr d'une approche réaliste pour ThreeJS. Peut-être que quelqu'un devrait faire des expériences dans une fourchette pour voir à quel point les choses sont réalisables.
Merci pour les explications les gars !
Ce que je crains, c'est de compliquer les choses pour les gens qui commencent tout juste. Les forcer à apprendre ce truc de browserify/modules n'est peut-être pas une bonne idée...
Je devrais être d'accord avec
Avec un UMD précompilé ( browserify --umd
) dans le référentiel, il n'y a aucun changement dans le flux de travail pour les développeurs existants.
@mrdoob L'idée d'un système de gestion des dépendances est la simplicité. Lire des dizaines de messages sur les options et les systèmes de construction peut être écrasant, mais en fin de compte, le système actuel n'est pas durable. Chaque fois qu'un fichier dépend d'un autre, c'est une chasse et une recherche que tout nouveau développeur doit effectuer pour trouver une référence. Avec browserify, la dépendance est explicite et il existe un chemin vers le fichier.
@repsac Un système de dépendances devrait rendre Three plus accessible aux utilisateurs d'autres langues car il évite la portée globale, les cauchemars d'ordre de chargement et suit un paradigme similaire à d'autres langues populaires. var foo = require('./foo');
est (loosly) semblable à C # 's using foo;
ou Java de import foo;
J'aimerais que tout soit modularisé, mais je ne suis pas sûr d'une approche réaliste pour ThreeJS. Peut-être que quelqu'un devrait faire des expériences dans une fourchette pour voir à quel point les choses sont réalisables
Je pense que c'est la voie à suivre, vraiment. Faites le travail, montrez comment cela fonctionne.
Et consommer l'API serait assez
ugly: require('three/src/math/Vector2')
À titre d'expérience, je viens de convertir le « démarrage » des trois documents à cette nouvelle approche modulaire. Je peux imaginer qu'il y ait beaucoup de références à moins que les gens ne soient assez stricts pour diviser leur code en modules minuscules.
Le principal avantage de cela serait que la taille de construction résultante serait une infime fraction de la taille du fichier Three.js complet, car vous n'incluriez que les éléments spécifiquement référencés ici, puis les éléments dont ces éléments dépendent.
Je suppose que référencer toutes les dépendances dont vous avez besoin (et les installer toutes individuellement) pourrait s'avérer un peu trop horrible dans la pratique.
Si vous ciblez explicitement les appareils mobiles, cette approche hautement granulaire serait parfaite, mais en réalité, je soupçonne que nous aurons besoin de packages qui exportent l'intégralité des TROIS API qui fonctionneront normalement, puis de packages plus petits qui encapsulent toute la géométrie bonus, tous les les moteurs de rendu, tous les calculs, tous les matériaux, etc., puis jusqu'au niveau du module individuel afin que les développeurs puissent décider eux-mêmes.
Et oui, coder pour le Web est pénible.
Quoi qu'il en soit, continuons l'expérience...
Installer nos dépendances..
npm install three-scene three-perspective-camera three-webgl-renderer three-cube-geometry three-mesh-basic-material three-mesh three-raf
Écrivez notre 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();
puis construisons notre fichier
browserify entry.js -o scripts/hello-world.js
alors incluez-le dans notre page
<script src="/scripts/hello-world.js" type="text/javascript"></script>
Je suppose que référencer toutes les dépendances dont vous avez besoin (et les installer toutes individuellement) pourrait s'avérer un peu trop horrible dans la pratique.
L'utilisateur final n'a pas nécessairement besoin d'utiliser browserify dans son projet pour que Three utilise browserify pour gérer sa base de code. Trois peuvent être exposés en tant que THREE
global tel qu'il est actuellement... incluez le fichier de construction et exécutez-le.
@repsac @mrdoob les modifications seraient rétrocompatibles, de sorte que les utilisateurs actuels n'aient pas besoin de modifier quoi que ce soit s'ils ne le souhaitent pas. Ces suggestions visent à améliorer la maintenabilité et la longévité à long terme de la base de code tentaculaire et monolithique de ThreeJS. Des choses comme la gestion des dépendances et des versions peuvent sembler un casse-tête pour les non-initiés, mais elles sont géniales pour ceux qui développent des outils, des frameworks, des plugins et des sites Web à grande échelle au-dessus de ThreeJS.
c'est-à-dire que le code de l'utilisateur final peut toujours avoir le même aspect, et le examples
n'a pas besoin de changer du tout :
<script src="three.min.js"></script>
<script>
var renderer = new THREE.WebGLRenderer();
</script>
Pour les développeurs plus ambitieux qui recherchent une version modulaire, _ou_ pour ceux qui cherchent à développer des solutions à long terme sur ThreeJS (c'est-à-dire à tirer parti de la gestion des versions/dépendances), cela pourrait ressembler davantage à ceci :
npm install three-vecmath --save
Ensuite, dans le code :
var Vector2 = require('three-vecmath').Vector2;
//.. do something with Vector2
Et, en outre, cela permet aux gens d'utiliser des choses comme les mathématiques vectorielles de ThreeJS, les conversions de couleurs, la triangulation, etc. en dehors de la portée de ThreeJS.
Même si je pense que le désordre require() est une mauvaise idée et un mauvais compromis, ce serait une idée encore pire d'exposer les utilisateurs à deux types différents de code three.js, en leur disant que l'un est la saveur du système de module de fantaisie et l'autre est le saveur de système de module plus simple (mais de seconde classe).
@erno Je pense que vous avez manqué le point, three.js
serait organisé par une structure de module en interne, mais qui est utilisé pour produire un fichier de construction qui n'est pas différent de la configuration actuelle.
Le principal gain est d'améliorer l'expérience de développement et de maintenance de three.js
.
@kumavis - non @erno n'a pas manqué cela, mais j'ai compris (*) qu'il fait remarquer que si three.js
est parfois utilisé via require et parfois non, cela peut être déroutant. Par exemple, quelqu'un regarde à la fois les trois sources, puis des exemples tiers et rencontre des différences dans la façon dont tout cela est et fonctionne.
(*) nous en avons parlé sur irc plus tôt dans la journée.
Je pense que c'est une sorte de point valable, mais je ne sais pas si / comment cela fonctionne à la fin - s'il s'agit vraiment d'un problème avec les utilisations du module et de la construction. Mais cela semble certainement mériter une réflexion et dans l'ensemble, il m'a semblé bon que la question globale ait été examinée attentivement ici, merci pour les informations et les points de vue si éloignés de ma part.
@antont je vois. Les gens ont suggéré une variété d'approches différentes ici, je supposais que nous fournirions principalement de la documentation pour une utilisation de haut niveau (en retirant tout de THREE
), mais d'autres peuvent créer des exemples qui ne suivraient pas cela et cela peut conduire à une certaine confusion. Et c'est une préoccupation valable.
Je pense que j'étais un peu confus par la langue.
et l'autre est la saveur du système de modules plus simple (mais de seconde classe).
Cela fait juste référence au fichier de construction, oui?
À ma connaissance, oui. Je ne peux pas imaginer quoi d'autre, mais il peut manquer quelque chose.
antont, kumavis : Les propositions ici ont parlé d'exposer le code de style require() aux utilisateurs finaux également, voir par exemple. le dernier commentaire de mattdesl.
"Pour les développeurs plus ambitieux qui recherchent une construction modulaire, ou pour ceux qui cherchent à développer des solutions à long terme sur ThreeJS (c'est-à-dire tirer parti de la gestion des versions/dépendances) [...]"
une façon d'avoir des versions plus optimisées est en fait d'avoir un script qui détermine automatiquement vos dépendances et génère les modules requis.
pour le moment, bower & browserify se débarrasse de require, mais ce ne sont pas les seules solutions. Je ne sais pas s'il existe d'autres projets open source prêts à l'emploi qui le font (peut-être comme les dépendances ng), mais j'ai déjà écrit de tels outils avant que je pense qu'il y aurait d'autres approches pour résoudre ces problèmes.
le compilateur de fermeture de google pourrait être un tel outil ?
Du côté de l'utilisateur, cela peut-il être utile ?
http://marcinwieprzkowicz.github.io/three.js-builder/
c'est assez intéressant @erichlof :) je me demande si @marcinwieprzkowicz a généré cela à la main... https://github.com/marcinwieprzkowicz/three.js-builder/blob/gh-pages/threejs-src/r66/modules.json
Une pratique que three.js utilise et qui la rend difficile à utiliser dans les environnements commonjs est l'utilisation d'instanceof : https://github.com/mrdoob/three.js/blob/master/src/core/Geometry.js#L82
En effet, dans une application, vous vous retrouvez souvent avec différentes versions de la même bibliothèque dans votre arborescence source, donc la vérification d'instanceof ne fonctionne pas entre différentes versions de la même bibliothèque. Il serait bon, en préparation d'un passage à un système de module commonjs, de remplacer ces instances de vérifications par une vérification des fonctionnalités derrière une interface de style Geometry.isGeometry(geom).
dans git/three.js/src :
grep -r instanceof . | wc -l
164
dans git/three.js/examples :
grep -r instanceof . | wc -l
216
il y a donc au total 380 utilisations de instanceof
dans three.js. Quelle serait la meilleure implémentation en remplacement ?
J'ai récemment ajouté une propriété type
qui peut être utilisée pour remplacer la plupart d'entre elles.
J'ai récemment ajouté une propriété de type qui peut être utilisée pour remplacer la plupart d'entre elles.
joli! Préparera un PR.
Pour un exemple de la façon dont cela est géré dans une autre bibliothèque JS populaire et importante, consultez https://github.com/facebook/react . La base de code est structurée à l'aide du système de module basé sur le style de nœud (que browserify implémente) mais est conçue pour être publiée à l'aide de grunt. Cette solution est flexible pour 3 cas d'utilisation.
require
dépendances spécifiques. Les avantages d'une bonne gestion de la dépendance ont été bien documentés.J'ai fait quelques recherches...
Hier, j'ai piraté un script (plutôt stupide) qui transforme le code source Three.js pour utiliser les instructions CommonJS require()
pour déclarer les dépendances entre les fichiers. Juste pour voir ce qui se passe... Ceci :
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');
Nous aurions besoin d'une refactorisation majeure, peut-être en divisant WebGLRenderer (et autres) en plusieurs modules (atm, le fichier fait plus de 6000 lignes).
THREE.ShaderChunk
au moment de la compilation, puis dans THREE.ShaderLib
au moment de l'exécution (rejoindre des tableaux de THREE.ShaderChunk
s), ce qui est assez difficile à faire avec uniquement browserify. Je suppose que cela nécessiterait une transformation browserify qui fait la même chose.React.js utilise commoner pour rechercher leurs modules sans avoir à s'y référer par chemin de fichier. Peut-être pourrions-nous faire de même et définir des règles personnalisées qui nous permettent de require
fichiers GLSL en les transformant en syntaxe JS.
@rasteiner, vous serez peut-être très heureux d'en savoir plus sur https://github.com/stackgl/glslify , cela vient de la famille grandissante http://stack.gl
J'ai eu pas mal d'expérience avec les modules et l'approche "unixy" au cours des deux derniers mois et je pense maintenant qu'il est trop peu trop tard, et refactoriser threejs pour la modularité ou les modules npm serait un objectif irréaliste.
Voici ce que je fais actuellement pour résoudre le problème de modularité/réutilisabilité :
Mes nouveaux projets ont tendance à utiliser "trois" sur npm juste pour être opérationnels. Ce serait vraiment génial si ThreeJS publiait officiellement la version sur npm en utilisant des balises de version qui s'alignent sur les numéros de version.
PS : à ceux qui souhaitent intégrer des shaders réutilisables/modulaires à leur flux de travail :
https://gist.github.com/mattdesl/b04c90306ee0d2a412ab
Envoyé de mon iPhone
Le 20 novembre 2014, à 7h42, aaron [email protected] a écrit :
@rasteiner, vous serez peut-être très heureux d'en savoir plus sur https://github.com/stackgl/glslify , cela vient de la famille grandissante http://stack.gl
-
Répondez directement à cet e-mail ou consultez-le sur GitHub.
Au cas où cela aiderait d'autres personnes qui pourraient chercher à utiliser Three.js avec browserify, et tomber sur ce fil, la façon dont je viens de le configurer moi-même est d'utiliser browserify-shim .
Suite à la section README sur _"Vous allez parfois a) Exposer des variables globales via global"_, j'ai inclus une balise de script distincte pour Three.js et l'ai configurée pour exposer la variable globale THREE.
Et puis le peu que j'ai dû travailler moi-même était de savoir comment inclure des extras comme ColladaLoader, OrbitControls, etc. J'ai fait comme ceci:
À partir de 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" }
};
Ensuite, dans mon propre script, 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 nécessite de reconstruire l'intégralité du script lorsque vous modifiez même sur des octets. Une fois, j'utilise browserify pour emballer un projet qui nécessite THREE.js, puis il faut plus de deux secondes pour créer une limite et bloquer le livereload à chaque fois que j'apporte une modification. C'est trop frustrant.
Vous utilisez normalement watchify pendant le développement avec livereload. Celui-là construit le bundle progressivement.
watchify ne fonctionne pas pour moi. Lorsque je modifie un fichier et que je l'enregistre, watchify et livereload de beefy servent l'ancienne version/mise en cache. Je ne sais pas pourquoi cela se produit. Heureusement, browserify fonctionne déjà assez bien.
@ChiChou Passez --noparse=three
pour naviguer. Cela fait passer l'étape du bundle de navigateur de 1000 ms à 500 ms sur ma machine, ce qui est assez décent pour une sensation de retour instantanée.
@rasteiner Je tiens à vous remercier à nouveau pour vos recherches informelles sur les interdépendances de three.js. Bien que cette liste massive de deps soit un code d'apparence moche, cette laideur est vraiment présente telle quelle, juste invisible. La force de Browserify est qu'il nous oblige à aérer notre linge sale et à rechercher des systèmes moins enchevêtrés.
Il y a beaucoup d'endroits dans Three.js où nous prenons un objet, percevons son type et effectuons différentes tâches en fonction de ce type. Dans la plupart de ces cas, ce code dépendant du type pourrait être déplacé vers le type lui-même, et nous n'aurions pas besoin de comprendre tous les types possibles sur lesquels nous opérons.
Ce qui suit est un exemple abrégé de WebGLRenderer :
if ( texture instanceof THREE.DataTexture ) {
// ...
} else if ( texture instanceof THREE.CompressedTexture ) {
// ...
} else { // regular Texture (image, video, canvas)
// ...
}
devrait être plus de la forme
texture.processTexImage( _gl, mipmaps, otherData )
Laissez le type déterminer comment se gérer lui-même. Cela permet également au consommateur de bibliothèque d'utiliser de nouveaux types de texture auxquels nous n'avions pas pensé. Cette structure devrait réduire l'interdépendance.
Je pense que passer à une architecture de navigateur est définitivement la voie à suivre. La version UMD facilitera la consommation de THREE.js. Cela nous permettra également de diviser le WebGLRenderer en plusieurs fichiers, car pour le moment, il semble plutôt monolithique et effrayant.
J'ai lancé une branche où je travaille actuellement à la déplacer ici : https://github.com/coballast/three.js/tree/browserify-build-system
S'il vous plait, faite moi part de votre avis.
Voici les changements de @coballast .
Il semble que vous adoptiez l'approche de conversion automatisée avec votre fichier browserifyify.js
, ce qui, je pense, est la bonne voie à suivre.
Une chose dont nous n'avons pas encore beaucoup discuté est la meilleure façon de faire la transition de cette grande bibliothèque en constante évolution vers browserify. Vous pouvez apporter les modifications, puis ouvrir un PR, mais il sera immédiatement obsolète. C'est ce qui est convaincant dans l'approche automatisée.
Si nous pouvons:
browserifyify.js
)... alors nous pouvons transformer cela en une conversion à bouton-poussoir qui fonctionnera toujours dans un avenir prévisible. cette simplicité permet d'accomplir cette notion onirique d'un changement d'architecture fondamentale vers un projet d'une telle envergure lorsque les arguments idéologiques l'emportent.
@coballast à cette fin, je supprimerais les modifications apportées à src/Three.js si cela fonctionne de la même manière.
Remarque : non seulement revenir en arrière, mais supprimer ces modifications de l'historique de la branche via une nouvelle branche ou une poussée forcée
@coballast Je me demande s'il serait plus logique que l'utilitaire de conversion ne soit pas un fork de three.js
, mais un utilitaire externe que vous pointez sur le dossier three.js
développement
@kumavis Je suis d'accord pour laisser le répertoire src seul. Je pense que la chose à faire est de demander à l'utilitaire d'écrire un répertoire en double avec le code commonjs, et nous pouvons tester et exécuter la version browserify à partir de là pour nous assurer que tous les exemples fonctionnent avant d'essayer de faire quoi que ce soit de majeur.
Il existe également une opportunité intéressante ici d'écrire des éléments d'analyse statique qui vérifieront et appliqueront automatiquement un style cohérent dans l'ensemble de la base de code.
@coballast sonne bien.
Il existe une multitude d'outils pour la réécriture de code automatisée, par exemple escodegen . Nous devons nous assurer que nous maintenons les commentaires, etc.
Vous voulez démarrer un dépôt threejs-conversion-utility ?
@coballast cela dit, il est important de rester concentré sur cet utilitaire
@kumavis Considérez que c'est fait. Je veux vraiment que cela se produise. Ce n'est qu'un des deux projets sur lesquels je travaille en ce moment.
@kumavis @mrdoob Une partie de la discussion ici semble
Je serai curieux de voir quel est le résultat de cet utilitaire ^^
@coballast lie un
https://github.com/coballast/threejs-browserify-conversion-utility
Le code est un gâchis, sera bientôt nettoyé.
nous y voilà! :fusée:
J'ai maintenant l'utilitaire dans un état où il génère browserify src et le construira sans problème. Je mettrai à jour le référentiel avec des instructions sur la façon de le faire vous-même. À ce stade, les exemples ne fonctionnent pas. Plusieurs problèmes doivent être résolus pour résoudre ce problème. Je les ajouterai au dépôt si quelqu'un veut retrousser ses manches et aider.
@coballast ouais, veuillez classer les problèmes en tant que TODO, et moi ou d'autres nous interviendrons autant que possible.
De sérieux problèmes sont apparus. Voir #6241
Voici mon analyse de ce qui devrait se passer pour que cela fonctionne : https://github.com/coballast/threejs-browserify-conversion-utility/issues/9#issuecomment -83147463
browserify est pour le moins redondant de transport (conjectif) en raison de sa conception. Cela rend son utilisation coûteuse (plan de données, n'importe qui ?) et lente.
Une solution simple consiste à séparer le document du code de la bibliothèque, ce qui impliquerait deux fichiers client et non un. C'est une pratique courante pour les js côté client.
Si, au départ, browserify est défectueux et qu'il doit lui-même être corrigé, je ne vois pas pourquoi il devrait même être envisagé d'améliorer quoi que ce soit, encore moins quelque chose comme threejs.
@spaesani Parce que les données de threejs doivent être téléchargées de toute façon. Si nous divisons threejs en modules plus petits et laissons un système de construction automatisé choisir ce dont il a besoin pour une seule application, en fait, la plupart des applications threejs seraient plus légères.
Si, pour une raison quelconque, vous souhaitez toujours séparer le "document du code de la bibliothèque", vous pouvez toujours le faire et utiliser une version pré-construite comme nous le faisons maintenant. Vous pouvez même diviser votre application construite par navigateur en modules séparés en utilisant les indicateurs --standalone et --exclude .
Browserify est juste un moyen d'utiliser une API de définition de module éprouvée (CommonJS) sur le navigateur. Cela simplifierait grandement le développement de plugins threejs et améliorerait la clarté du code et donc la productivité, cela nous permettrait de nous intégrer dans un plus grand écosystème (npm) où le code est intrinsèquement maintenu par plus de personnes tout en maintenant l'intégrité à travers le système de versioning (pensez à la famille stackgl ), et cela ne forcerait même pas les gens à utiliser CommonJS s'ils n'en veulent pas.
Bien sûr, il y a des inconvénients, mais ce ne sont pas ceux que vous avez mentionnés.
three.js et three.min.js peuvent être mis en cache pour économiser sur le transport (données) par un proxy, la solution mobile commune ou un navigateur de mise en cache.
Au moment où vous choisissez et agrégez le code threejs avec le code spécifique au document, la mise en cache n'est pas possible.
Si browserify permet de
sp
On Mar 28, 2015 1:06 PM, Roman Steiner notifications@github.com wrote:@spaesani Because the data for threejs has to be downloaded anyway. If we split threejs into smaller modules and let an automated build system cherry pick what it needs for a single app, actually most threejs apps out there would be lighter.
If for some reason you still want to separate "document from library code", you could still do this and use a pre-built version like we do now. You could even split your browserify-built app into separate modules by using the --standalone flag.
Browserify is just a way to use a battle proven module definition API (CommonJS) on the browser. It would greatly simplify the development of threejs plugins and enhance code clarity and therefore productivity, it would allow us to integrate into a bigger ecosystem (npm) where the code is inherently maintained by more people while still maintaining integrity through the versioning system, and it wouldn't even force people into CommonJS if they don't want it.
Of course there are downsides, but they're not the ones you've mentioned.
—Reply to this email directly or view it on GitHub.
@spaesani Il (naviguer) améliore les choses pour les humains. Mon propre bonheur psychologique et mon bien-être sont plus importants que la facilité avec laquelle une machine peut charger et exécuter des choses.
De nombreux problèmes de charge du réseau mobile seront quelque peu atténués par des choses comme http/2. De tels problèmes sont mieux résolus en modifiant les couches inférieures de la pile d'abstraction. Les problèmes de performances ne doivent pas nous empêcher de suivre les meilleures pratiques d'ingénierie logicielle telles que la modularité/la séparation des préoccupations, etc.
J'ai trouvé ce problème parce que mon équipe a récemment commencé à utiliser jspm. Nous sommes en mesure d'importer des threejs (je pense que c'est parce que le fichier principal a été exploré). Je cherchais à voir si quelqu'un avait créé threejs dans des modules es6, principalement à cause de la fonctionnalité de construction de jspm (regroupant toutes les dépendances dans un seul fichier, mais en saisissant uniquement les dépendances utilisées).
Bien qu'il soit formidable que mrdoob garde la taille de threejs sous 100 Ko, je trouve que la plupart de mes projets n'utilisent pas beaucoup de code de base (j'ai l'impression que c'est le plus, mais je n'ai pas essayé de comprendre cela). CubeCamera, OrthographicCamera, CanvasRenderer, divers Lights, Loaders, Curves, Geometries, Helpers, etc. De plus, je constate que la plupart de mes projets incluent quelques exemples de scripts.
J'espérais qu'il serait possible d'avoir un emplacement unique de tous ces modules (ceux normalement fournis avec threejs ainsi que ceux des exemples), et d'importer simplement ceux dont j'ai besoin, puis lorsque je regroupe le projet, il en résulte dans un fichier beaucoup plus petit que le threejs d'origine, même s'il contient de nombreuses parties qui n'étaient pas incluses à l'origine.
Je voulais également ajouter que si threejs était construit à l'aide de modules browserify, cela ajouterait une petite surcharge de taille de fichier (mais incomparable aux 403 Ko actuels à r70), mais supprimerait également l'utilisation de la variable globale THREE du code, ainsi permettant à des variables comme THREE.Geometry d'être minifiées par la fermeture.
J'ai fait un test rapide en effectuant une recherche-remplacer pour me débarrasser de l'objet TROIS (tous ses enfants ont donc pollué l'espace de noms) et en enveloppant l'ensemble du fichier dans un IIFE, puis j'ai exécuté le tout via la fermeture de Google. Le fichier résultant (non compressé) faisait 238 Ko, contre 777 Ko.
Bien que les résultats varient, je pense qu'il vaut vraiment la peine de s'assurer que cela peut se produire.
merci d'avoir dit - beaucoup de bons points là-bas, et nous sont familiers aussi. nous n'utilisons jamais non plus de nombreux moteurs de rendu dans un même projet, mais faisons des choses en quelque sorte à partir d'exemples.
Je ne savais pas qu'à propos de la minification - c'est une assez grande différence.
et les modules es6 ont certainement semblé prometteurs - il a également été bon d'entendre qu'il existe un chemin à partir du modèle de module AMD/CommonJS/tel et de l'utilisation de la bibliothèque.
@colin Je ne suis pas sûr de vous suivre sur la façon dont browserify
aide votre bonheur psychologique.
C'est dans la doc ?
browserify est une vache à lait porteur...
Mardi 31 mars 2015, 22:11 -04:00 de Colin Ballast notifications@github.com :
@spaesani Il (naviguer) améliore les choses pour les humains. Mon propre bonheur psychologique et mon bien-être sont plus importants que la facilité avec laquelle une machine peut charger et exécuter des choses.
De nombreux problèmes de charge du réseau mobile seront quelque peu atténués par des choses comme http/2. De tels problèmes sont mieux résolus en modifiant les couches inférieures de la pile d'abstraction. Les problèmes de performances ne doivent pas nous empêcher de suivre les meilleures pratiques d'ingénierie logicielle telles que la modularité/la séparation des préoccupations, etc.
-
Répondez directement à cet e-mail ou consultez-le sur GitHub .
Maintenant, si browserify déterminerait automatiquement les dépendances sans instruction require... hé, attendez...
@spaesani Je préfère en fait les dépendances explicites - vous aide à comprendre comment le code s'emboîte.
browserify est une vache à lait porteur...
La surcharge de
Mise à jour du statut:
J'ai une branche avec du code par navigateur :
https://github.com/coballast/three.js/tree/browserify
Veuillez garder à l'esprit qu'il s'agit d'un travail en cours. Ce code a été généré automatiquement et va donc avoir l'air assez horrible pendant un certain temps. J'essaie toujours de résoudre certains problèmes de construction. Voir coballast/threejs-browserify-conversion-utility#10 si vous pensez pouvoir le réparer. Il était en construction pendant un certain temps, mais ce n'est pas le cas maintenant.
@kumavis et moi avons travaillé sur la résolution de certains problèmes d'exécution (et sur l'amélioration de l'architecture logicielle). Je crois que je l'ai mentionné ci-dessus quelque part.
Désolé pour la longue réponse. TLDR : jspm/es6 s'exécute, mais présente des problèmes : 1) Exportation des objets avant de les définir ; 2) Exporter des objets contenant une seule classe, plutôt que simplement exporter une seule classe ; 3) IIFE utilisant des dépendances circulaires ; 4) Structure du fichier.
J'ai joué avec votre branche navigateur dans jspm ( @spinchristopher ci-dessus est moi) et j'ai quelques notes, mais tout d'abord: ne serait-il pas bon d'ouvrir des problèmes sur cette fourchette, donc ce fil n'en est pas plein et ils ne le sont pas pêle-mêle?
Bien qu'il s'exécute, il ne produit pas réellement le résultat correct. (en utilisant la démo simple sur la mise en route). Crée le canevas et le remplit de noir (à moins que je définisse la couleur claire sur transparent), mais ne rend pas réellement le cube. Je ne m'attends cependant pas à ce que cela fonctionne à ce stade, car c'est encore très tôt dans le processus.
J'ai rencontré 3 problèmes principaux :
Une. C'était le plus ennuyeux, et honnêtement, je ne sais pas comment vous pouvez même compiler quoi que ce soit avec cette erreur particulière, car cela ne devrait pas du tout fonctionner. La plupart des fichiers commencent comme ceci (c'est bien car les définitions de fonction sont hissées à l'heure et sont essentiellement exécutées avant la ligne module.exports, même si elle apparaît en premier) :
module.exports.Foo = Foo;
function Foo() {}
Le problème vient des nombreux fichiers qui ressemblent à celui-ci (le premier que j'ai vu était math/Math.js). L'initialisation de l'objet est hissée (c'est pourquoi il n'y a pas d'erreur indéfinie) mais la définition reste en place (donc l'export est indéfini).
module.exports.Foo = Foo;
var Foo = {};
Le seul correctif que j'ai trouvé ici est de déplacer la ligne d'exportation à la fin ou de la réécrire comme ceci (de préférence):
var Foo = module.exports.Foo = {};
Deux. Les données exportées. Lorsqu'il s'agit de fichiers modularisés, la norme est que chaque fichier exporte un seul objet. Bien que la plupart des fichiers fonctionnent ainsi (bien que certains exportent davantage), ils n'exportent pas le constructeur unique, ils exportent un objet contenant ce constructeur (c'est-à-dire : module.exports.Foo = Foo;
plutôt que module.exports = Foo;
. Ce dernier est la façon dont tous les exemples de browserify fonctionnent). Ainsi, lorsque vous utilisez les exigences, vous devez approfondir un niveau ( var Vector3 = require('../math/Vector3').Vector3;
). En plus d'être inutile, il n'y a aucun moyen de le faire lors de l'importation dans es6. ( import Vector3 from '../math/Vector3'; var vector = new Vector3.Vector3();
). Bien qu'il soit possible de récupérer une exportation particulière dans es6, cela s'applique lors de l'utilisation de modules par navigateur et aurait toujours la même redondance ( import { Vector3 } from '../math/Vector3';
). Il existe quelques fichiers qui collectent simplement d'autres objets (l'évident étant Three.js), mais ceux-ci doivent être réduits au minimum et ne doivent être utilisés que pour le processus de construction, pas comme un moyen de récupérer beaucoup de choses en production. .
Trois. Cela a à voir avec les dépendances circulaires. System.js (le chargeur de module utilisé par jspm) peut très bien gérer les dépendances circulaires, mais il y a un problème. Dans de nombreux endroits, le code se lit comme suit. Le problème est que, bien que Vector3 ait été transmis en tant que dépendance, à ce stade, il n'a pas été complètement chargé (comme Vector3 inclut également ce fichier, chacun ne peut pas être résolu tant que l'autre n'a pas été résolu) et ne peut pas être créé. J'ai ajouté un très mauvais correctif (illustré ci-dessous), bien que je ne sache pas comment cela serait mieux résolu. Il semble qu'il s'agisse d'un problème architectural qui n'a peut-être pas de solution simple. Cela arrive plusieurs fois. Cela semble être une optimisation pour empêcher la création d'un nouveau Vector3 à chaque fois que la fonction est appelée. S'il y a effectivement un impact significatif sur les performances qui ne peut pas être corrigé en optimisant Vector3, alors peut-être ajouter une fonction à Vector3 pour renvoyer un vector3 inutilisé qui sera publié plus tard ?
Foo.prototype.bar = function() {
var vector = new Vector3();
return function() {
// some data which reuses vector repeatedly.
};
}();
Le correctif :
Foo.prototype.bar = function() {
var vector;
return function() {
if(!vector) vector = new Vector3();
// some data which reuses vector repeatedly.
};
}();
Enfin, je voulais ajouter un peu sur l'organisation des fichiers. C'est évidemment quelque chose à aborder après la construction de l'ensemble actuel, mais je voulais en parler maintenant. Bien que la structure de fichier actuelle fonctionne, certaines parties sont plutôt étranges ou même maladroites. Les principaux groupes (caméras, matériaux, géométries, etc.) semblent bien l'avoir, même si j'apporterais quelques modifications, comme indiqué ci-dessous. Je déplacerais également les globals dans ThreeGlobals chacun vers la chose pour laquelle ils sont un global. IE : FrontSide, BackSide, DoubleSide appartiennent tous à Material (avec NoShading, FlatShading et SmoothShading. En fait, il semble que la plupart d'entre eux le fassent...).
Mes principales confusions sont venues du noyau et des extras. core/Geometry.js doit se trouver dans le dossier geometries, tout comme Material est dans le dossier des matériaux. Mais il n'y a pas de dossier de géométries, il est dans les extras. Incidemment, les extras ont également un noyau et une géométrie, mais la géométrie de base n'est pas dans ce dossier. Il y a cette grande collection d'assistants, mais chaque assistant ne devrait-il pas être avec la chose qu'il aide ? Les processus de construction peuvent facilement être configurés pour ne prendre que les fichiers que vous voulez, il n'y a donc aucune excuse pour mettre les fichiers non importants ailleurs.
J'ai actuellement une ligne dans mon code indiquant import BoxGeometry from 'threejs/extras/geometries/BoxGeometry';
et var geometry = new BoxGeometry.BoxGeometry( 1, 1, 1 );
Étant habitué à utiliser `new THREE.BoxGeometry()```, il a fallu un certain temps pour trouver le fichier. Lorsque vous l'utilisez de manière modulaire, l'emplacement du fichier est tout aussi important que quelque chose comme les signatures de fonction.
Modifications générales que j'apporterais à la structure du fichier. Celles-ci s'appliquent à de nombreux endroits, mais je ne montre qu'un exemple. (Pour mémoire, j'ai toujours préféré un modèle consistant à nommer le fichier d'après la classe unique qu'il exporte et à placer le fichier dans un dossier du même nom. Tous les descendants directs iront généralement dans ce dossier, mais encore une fois, dans un dossier avec le même nom qu'eux. Cependant, si l'on n'aime pas ce modèle, la même structure ci-dessous s'applique, en supprimant simplement ce niveau supplémentaire. De plus, n'importe quel chargeur de fichiers peut être facilement modifié [les crochets sont généralement fournis directement, en fait] pour automatiser la superposition et simplifier les instructions require].) (Je préfère également tous les fichiers en minuscules, avec des traits de soulignement si nécessaire.)
Three.js - This is _only_ used in the build process, so it should actually be with the build files, but run as if it is in this location.
geometry/geometry.js - Currently at core/Geometry.js
geometry/face3/face3.js - from core/Face3.js
geometry/box_geometry/box_geometry.js - Currently at extras/geometries/BoxGeometry.js
geometry/circle_geometry/circle_geometry.js - Similar to above.
geometry/utils/utils.js - from extras/GeometryUtils.js
camera/camera.js
camera/cube_camera/cube_camera.js
camera/perspective_camera/perspective_camera.js
camera/helper/helper.js - or camera/camera_helper/camera_helper.js
scene/scene.js
scene/fog/fog.js
scene/fog_exp2/fog_exp2.js
Je renommerais également probablement les mathématiques en utilitaires (chaque catégorie peut également avoir un utilitaire, comme la géométrie ci-dessus) afin qu'il puisse contenir plus que des mathématiques (beaucoup de choses du noyau).
@HMUDesign @spinchristopher merci pour l'excellente analyse ! Il est préférable de mettre ce genre de problèmes dans le référentiel coballast/threejs-browserify-conversion-utility à l'avenir.
ok permettez-moi de lire correctement votre commentaire maintenant.
J'ai en quelque sorte manqué le lien vers ce référentiel ci-dessus. Je déplacerai volontiers mes problèmes
à ce dépôt demain, en divisant ensuite si nécessaire (j'ai remarqué qu'au moins
une partie est déjà là)
Le 9 avril 2015 à 00h09, "kumavis" notifications@github.com a écrit :
@HMUDesign https://github.com/HMUDesign @spinchristopher
https://github.com/spinchristopher merci pour l'excellente analyse ! Meilleur
mettre ce genre de problèmes dans le
coballast/threejs-browserify-conversion-utility repo à l'avenir.ok permettez-moi de lire correctement votre commentaire maintenant.
-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment-91132413 .
Oui, et je le fais pour mes propres bibliothèques de types util (les fichiers *Util sont les
la seule fois où je n'ai pas d'export par défaut, bien que j'ajoute parfois un
expert en plus de la syntaxe par défaut), cependant cette syntaxe ne fonctionne que lorsque vous
exporter plusieurs variables nommées. Le chargeur pour les modules js communs traite
modules.exports comme export par défaut, qui ne peut pas être déstructuré dans le
importer =(
Le 9 avril 2015 à 00h12, "kumavis" notifications@github.com a écrit :
dans es6, vous pouvez importer des propriétés à partir des objets d'exportation via
déstructuration.importer { Vector3 } de '../math/Vector3';
cela dit, je suis d'accord qu'une exportation par module est préférée.
-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment-91132982 .
@HMUDesign merci encore pour votre énergie et votre analyse - ici, nous construisons une liste de tâches, n'hésitez pas à vous lancer et tout. https://github.com/coballast/threejs-browserify-conversion-utility/issues/17
+1 pour la navigation.
Également +1 pour déplacer les shaders dans des fichiers séparés à l'aide de glslify.
Également +1 pour l'adoption de certaines fonctionnalités ES6 - comme les classes et les modules. La nouvelle pile de construction nous permettra de compiler à nouveau vers ES5 si nécessaire. Voir exemple :
import Object3D from '../core/Object3D';
import Geometry from '../core/Geometry';
import MeshBasicMaterial from '../materials/MeshBasicMaterial';
class Mesh extends Object3D {
constructor(
geometry = new Geometry(),
material = new MeshBasicMaterial({color: Math.random() * 0xffffff}
) {
super();
this.geometry = geometry;
this.material = material;
this.updateMorphTargets();
}
}
export default Mesh;
@lmcd Pendant que nous y sommes, nous pouvons utiliser les modules es6 et utiliser babeljs pour tout compiler.
@coballast Je serais intéressé à bifurquer votre branche browserify
et à faire en sorte que certaines de ces choses se produisent
@lmcd, ça ne me dérangerait pas. Je vais développer des outils automatisés pour déplacer automatiquement les éléments es5 vers es6. Cela a du sens, car il existe une énorme quantité de code es5 et la main-d'œuvre nécessaire pour tout déplacer à la main est astronomique.
@coballast Je pensais plutôt à exécuter un pass 5to6
: https://github.com/thomasloh/5to6
@lmcd oo belle trouvaille
mais tbh, il semble qu'il serait plus facile de réécrire three.js à partir de zéro : P
@lmcd, je suis si heureux que vous ayez trouvé cela. C'était l'une de ces choses que j'allais faire par simple nécessité, mais cela ne semblait clairement pas amusant.
@mrdoob que
@anvaka Pour le moment, je me concentre actuellement sur la refactorisation de WebGLRenderer
. Je n'ai plus de bande passante mentale 😅
J'ai récemment rencontré un projet qui utilisait avec bonheur les modules es6 avec le babel polyfill qui a déjà été mentionné ici aussi. Je ne pouvais pas me souvenir ni trouver encore maintenant ce que c'était, ça me paraissait bien de toute façon.
De plus, es6 semble être terminé maintenant sur le plan des normes : "Enfin, l'ECMA-262 Edition 6 a été officiellement approuvée et publiée en tant que norme le 17 juin 2015" déclare https://developer.mozilla.org/en-US/docs /Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
Juste une note qu'en ce qui concerne l'outillage et la stabilité de la spécification du module, la situation semble bonne sur ce front.
J'ai récemment rencontré un projet qui utilisait avec bonheur les modules es6 avec le babel polyfill qui a déjà été mentionné ici aussi. Je ne pouvais pas me souvenir ni trouver encore maintenant ce que c'était, ça me paraissait bien de toute façon.
Il contient également 47 Ko de js supplémentaires et lit et transpile votre javascript inclus en es5 dans le navigateur, donc pas idéal pour le démarrage.
Rien n'empêche quiconque utilise three.js d'utiliser es6 dans son propre code ; Cependant, son utilisation dans la bibliothèque introduirait des problèmes de compatibilité et de performances du navigateur dans tous les domaines.
Ah - debout corrigé ici, merci pour l'info. Je suppose que browserify et ceux qui fonctionnent dans le processus de construction sont encore meilleurs maintenant.
Ah - debout corrigé ici, merci pour l'info. Je suppose que browserify et ceux qui fonctionnent dans le processus de construction sont encore meilleurs maintenant.
L'un des principaux problèmes avec es6 est qu'il a des changements de syntaxe avec es5 ; par exemple, la grosse flèche => n'est pas valide es5 et entraînera l'échec de l'analyseur javascript et la tentative de compilation du code. Espérons que quelqu'un trouvera un moyen de contourner cela, mais ils ne l'ont pas encore fait.
En fait, je ne pensais qu'au système de modules, à la déclaration d'importation, etc.
Il contient également 47 Ko de js supplémentaires et lit et transpile votre javascript inclus en es5 dans le navigateur, donc pas idéal pour le démarrage.
par exemple, la grosse flèche => n'est pas valide es5 et entraînera l'échec de l'analyseur javascript et l'annulation de la tentative de compilation du code
Le code es6 peut être transpilé en es5 pendant _build_ sans pénalité d'exécution. Il s'agit simplement d'ajouter une étape babel au pipeline de construction.
Par exemple, la fonction flèche peut être transpilée en es5 pendant la construction sans polyfill ni pénalité d'exécution. Babel va transpiler cet extrait es6
function MyObj() {
this.step = 1;
this.increment = function ( arr ) {
return arr.map( v => v + this.step );
}
}
dans cette version portable :
function MyObj() {
this.step = 1;
this.increment = function (arr) {
var _this = this;
return arr.map(function (v) {
return v + _this.step;
});
};
}
Une autre fonctionnalité, comme les classes es6, générera un petit polyfill (vous pouvez le voir dans le babel repl http://babeljs.io/repl/).
@mrdoob a compris. Seriez-vous favorable à l'idée de diviser three.js en modules plus petits hébergés sur le npm ?
Le référentiel principal three.js restera inchangé : les consommateurs n'auront rien à construire. Les utilisateurs plus expérimentés seraient en mesure de sélectionner les bits requis de three.js.
Ça sonne bien. Je ne connais pas les détails par contre.
Le code es6 peut être transpilé en es5 pendant la construction sans pénalité d'exécution. Il s'agit simplement d'ajouter une étape babel au pipeline de construction.
Par exemple, la fonction flèche peut être transpilée en es5 pendant la construction sans polyfill ni pénalité d'exécution. Babel va transpiler cet extrait es6
Le transpilage ES6 s'accompagne toujours d'une pénalité d'exécution importante : http://www.incaseofstairs.com/2015/06/es6-feature-performance/ en particulier pour une bibliothèque haute performance.
modules/npm/browserfy etc est cependant probablement une bonne idée
+1 sur la modularisation appropriée à l'aide des modules ES6
+1 sur la modularisation appropriée en utilisant n'importe quel système de module sain (commonjs, amd, es6)
Je pense que commonjs et amd sont les choix préférés car ils ne nécessitent pas de transpilation
Ils nécessitent cependant une étape de construction, qui équivaut à la
étape de transpile.
Utiliser ES6, en plus d'être la prochaine version du langage, permettrait au
utiliser les fonctionnalités suivantes comme vous le souhaitez, mais sans casser le code natif existant.
Est-il vraiment sage de réintégrer la base de code dans un système qui est déjà
pas le dernier ?
Le 20 juillet 2015 à 12h05, "kumavis" notifications@github.com a écrit :
+1 sur la modularisation appropriée en utilisant n'importe quel système de module sain (commonjs, amd,
es6 )
Je pense que commonjs et amd sont les choix préférés car ils ne le sont pas
nécessiter un transpilage-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment-122990605 .
Ils nécessitent cependant une étape de construction, qui équivaut à la
étape de transpile.
la construction et le transpilage ne sont pas équivalents en termes de complexité qu'ils introduisent.
Est-il vraiment sage de réintégrer la base de code dans un système qui est déjà
pas le dernier ?
commonjs est simple et fonctionne très bien. Je ne suis pas convaincu par l'idée que « dernier » === « meilleur ».
L'utilisation d'ES6 [...] permettrait d'utiliser les fonctionnalités suivantes comme vous le souhaitez
donc cela vaut la peine d'être considéré. voulons-nous des fonctionnalités es6 ? si nous commençons à transpiler es6, les gens commenceront à PR'ing es6. comme @benaadams l'a suggéré, l'utilisation des fonctionnalités es6 a des impacts non intuitifs sur les performances.
De plus, nous n'avons pas besoin de confondre les problèmes de « système de module » et de « fonctionnalités es6 ». vous pouvez transpiler es6 et utiliser commonjs. et vous pouvez les présenter séparément.
+1 pour browserify / commonjs - il est simple de compiler avec browserify de manière à ce que les utilisateurs puissent toujours utiliser la bibliothèque de manière traditionnelle s'ils le souhaitent - c'est à cela que sert UMD, autoriser AMD (comme require.js), CommonJS nécessite (comme node + browserify) et une fenêtre globale (pour les balises de script) en fonction de l'environnement dans lequel nous opérons.
PIXI.js vient de passer à une architecture modulaire utilisant browserify et la bibliothèque a été configurée de manière très similaire - tout est attaché à un objet PIXI global. Leur configuration ressemble beaucoup à celle décrite par
Ni browserify ni commonjs ne répondent aux besoins spécifiques d'un moteur 3D, ce qui ne signifie pas qu'ils ne peuvent pas être utilisés, mais ils doivent être considérés comme une pièce d'un plus grand puzzle :
Les composants doivent exporter des méta-informations sur les propriétés de leurs instances, il peut donc y avoir un chargeur pour les objets arbitraires et les connexions de données en mémoire partagée. Avec une telle architecture, ce serait juste une question de bon sens de charger également du code de composant hors du cœur lors de la première utilisation. J'ai fait un brainstorming sur ces sujets dans les #6464 et #6557.
+1
+1
En tant que solution hybride, il est également possible d'ajouter les exigences sous forme de commentaires. Je sais que browserfy est déjà dans de nombreux écosystèmes, mais je voulais juste laisser cela ici comme une variante rapide à implémenter :) car vous n'auriez rien à changer. Il vous suffit d'ajouter un commentaire en haut de chaque fichier.
En tant que développeur, vous pouvez facilement créer vos propres fichiers min.js avec les informations @requires
et le plugin gulp.
Salut à tous, j'ai récemment eu un besoin similaire de charger des ressources arbitraires avec leurs propres dépendances de manière propre et structurée et j'ai trouvé la solution d'écrire des plugins require.js pour chaque type de ressource. De cette façon, je laisse la résolution des dépendances de require.js s'occuper du téléchargement et de la mise en cache corrects des ressources.
Si vous êtes intéressé, vous pouvez trouver le projet ici : https://github.com/wavesoft/three-bundles
(Un exemple utilisant cette bibliothèque sera bientôt disponible)
À l'avenir, je prévois d'inclure une phase d'optimisation dans ces plug-ins afin de permettre à l'optimiseur require.js de compiler les ressources dans un format encore plus compact.
En regardant cette conversation https://twitter.com/defunctzombie/status/682279526454329344, il ne semble pas que les modules es6 soient implémentés dans un proche avenir. Quelque chose à garder à l'esprit.
J'ai fait quelques prototypes avec les modules commonjs et browserify.
Mon groupe final avec navigateur comprend chaque fichier du dossier src
et donne une taille de fichier 962K
(par rapport à la version originale non explorée 885K
).
Exemple de build ciblé de cloth
:
580K
(~44% plus petit)431K
(~8% plus petit)Voici la répartition de la taille du paquet : http://output.jsbin.com/yogoxawozu. Les moteurs de rendu prennent 40% du bundle, et 10% de cela est pris par la bibliothèque de shaders.
Je pense que nous pourrions réduire la taille du paquet en :
instance of
- ils nécessitent un référencement explicite des modules même lorsqu'ils ne sont pas utilisés. Je vois que certaines classes ont déjà type
- nous pourrions l'utiliser dans toute la bibliothèque.glslify
été apporté quelques fois, et cela pourrait certainement aider. Idéalement, chaque composant nécessitant des shaders doit explicitement dépendre d'un shader.Vous pouvez vérifier les résultats et vérifier le code :
git clone --depth 1 --branch commonjs https://github.com/anvaka/three.js.git
cd three.js
npm i
# build backward compatible three.js library from commonjs modules.
# The output will be save into `build/three.min.js`. I'm using `.min.js` just
# to quickly verify examples. The actual file is not minified.
npm run build
# build cloth example
# the output is saved into ./examples/cjs/webgl_animation_cloth.bundle.js
npm run demo
il ne semble pas que les modules es6 soient implémentés dans un avenir proche. Quelque chose à garder à l'esprit.
C'est vrai, mais il est également important de réaliser que la prise en charge du module CommonJS ne sera _jamais_ implémentée dans les navigateurs, donc le choix est entre
Des bibliothèques comme D3 adoptent les modules ES6 car elles peuvent déjà faire tout ce que les modules CommonJS peuvent faire (sauf s'exécuter nativement dans Node.js, ce qui n'est pas vraiment un problème pour une bibliothèque comme Three.js), et se traduisent par des builds plus petits.
J'ai fait quelques expériences sur https://github.com/rollup/three-jsnext , et bien qu'il ne soit pas prêt pour la production (je dois passer un peu plus de temps à porter des exemples, etc.), la version UMD qu'il génère est en fait _smaller_ que la version actuelle.
Je suis d'accord avec la note sur les modules es6 par rapport aux autres systèmes. Que ce soit ou
ce n'est pas une norme es, c'est une norme communautaire. Et bien qu'ils
ne peut pas s'exécuter "nativement" dans le nœud, il peut sembler natif avec les crochets Babel.
Je ferai bientôt le suivi de votre repo.
De plus, le fait qu'il soit plus petit était quelque chose que j'avais évoqué plus tôt dans
cette conversation. « THREE.Geometry » devient « géométrie » qui peut être
minifié à "a" par exemple.
De plus, la solution à l'instance des contrôles est de les supprimer tous
ensemble. Un module ne doit pas être supplié d'avoir différemment selon ce que
il a été donné, mais plutôt de s'en remettre à la chose fournie pour faire ce dont il a besoin
à faire. Il n'y a alors aucune vérification d'instance ou de type.
Le 1er janvier 2016 à 20h23, "Rich Harris" notifications@github.com a écrit :
il ne semble pas que les modules es6 soient implémentés dans près
futur. Quelque chose à garder à l'esprit.C'est vrai, mais il est également important de réaliser que le module CommonJS
le support ne sera _jamais_ implémenté dans les navigateurs, le choix est donc entre
- continuer avec une architecture non modulaire et un build ad hoc
système, qui a bien servi Three.js jusqu'à présent mais agit comme un frein à la croissance
à long terme- en utilisant des modules CommonJS, ce qui implique une certaine ruse autour des cycles cycliques
dépendances et résultats dans une version plus importante, ou- en utilisant des modules ES6, qui sont bien adaptés à une base de code comme Three.js
qui a des dépendances cycliques, et qui se traduisent par le plus petit et le plus
construction minifiable possible. A terme, les navigateurs les supporteront nativement,
et les changements nécessaires pour s'adapter à toutes les bizarreries imprévues du chargeur
les spécifications seront probablement insignifiantes par rapport à l'effort impliqué dans
mise à niveau à partir d'une base de code CommonJS.Des bibliothèques comme D3 adoptent les modules ES6 car elles peuvent déjà faire
tout ce que les modules CommonJS peuvent faire (sauf s'exécuter nativement dans Node.js, qui
n'est pas vraiment un problème pour une bibliothèque comme Three.js), et se traduit par un plus petit
construit.J'ai fait des expériences à
https://github.com/rollup/three-jsnext , et bien que ce ne soit pas en production
prêt (j'ai besoin de passer un peu plus de temps à porter des exemples, etc.) la version UMD
qu'il génère est en fait _plus petit_ que la version actuelle.-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment-168363092 .
CommonJS aboutirait-il toujours à une version plus importante avec une base de code qui n'a pas de dépendances cycliques ?
@cecilemuller Oui – voir https://github.com/nolanlawson/rollup-comparison. Avec les modules CommonJS, vous payez un coût par module (chaque module doit être encapsulé dans une fonction et doit redéclarer les importations qui sont partagées dans l'ensemble du bundle, vous êtes donc pénalisé pour une base de code plus modulaire), un coût par bundle (il doit simuler un environnement Node.js) et d'autres coûts tels que les noms de propriétés d'objets non minimables qui seraient des noms de variables minimables dans les modules ES6. Les modules ES6 vous permettent de regrouper sans frais généraux.
Bien qu'il y aurait des frais généraux à transpiler ensuite vers es5. Maintenant,
J'utilise webpack avec babel qui ajoute très peu. Il y a un coût par module
car il est également enveloppé dans la fonction s. Les dépendances sont déclarées au final
code en appelant une fonction similaire à require avec un indice entier, de sorte qu'il obtient
minifié à quelque chose comme "var a=f(5)" à partir de ce qui était à l'origine 'import
Géométrie de "./geometry";'
L'utilisation de générateurs ajoute également un peu plus, mais je n'imagine pas la structure de
le code serait en train de changer beaucoup de temps bientôt.
Le 2 janvier 2016 à 5h53, "Rich Harris" notifications@github.com a écrit :
@cecilemuller https://github.com/cecilemuller Oui – voir
https://github.com/nolanlawson/rollup-comparison. Avec les modules CommonJS
vous payez un coût par module (chaque module doit être enveloppé dans une fonction,
et doit redéclarer les importations qui sont partagées dans l'ensemble du bundle, donc
vous êtes pénalisé pour une base de code plus modulaire), un coût par bundle (il faut
pour simuler un environnement Node.js), et d'autres coûts tels que
les noms de propriété d'objet qui seraient des noms de variables minimables dans ES6
modules. Les modules ES6 vous permettent de regrouper sans frais généraux.-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -168394376.
Bien qu'il y aurait des frais généraux dans la transpilation puis vers es5
Si vous utilisez uniquement la syntaxe import
et export
pour décrire la relation entre les modules, il n'est pas nécessaire de transpiler le code lui-même avec Babel ou quelque chose de similaire. Il est seulement quand vous commencez à ajouter d' autres fonctionnalités de ES6 (comme les classes et détermination de la portée de bloc et la flèche fonctions , etc.) que transpiling devient nécessaire, donc il y a les frais généraux zéro à l' aide de import
et export
. D3 et PouchDB sont deux exemples de bibliothèques qui utilisent import
et export
mais sont par ailleurs sans Babel ES5, et three-jsnext est fait de la même manière.
Ok, nous avons tous eu la même idée. Ce serait génial d'avoir une histoire comme lodash.
Je propose de créer un package _three-foo_ pour chaque composant _foo_ (par exemple three-vector2) qui peut être modularisé, avec presque aucun changement dans le code, afin qu'il puisse être importé dans ce repo sans impact.
Les personnes qui publient sur npm devraient bien jouer et collaborer avec @mrdoob puisqu'il est le créateur de ce super logiciel, donc s'il veut centraliser à nouveau tous les packages comme l'a fait _babel_ author (je veux dire tous les packages principaux dans le même dossier), l'éditeur doit lui donner le contrôle sur l'espace de noms npm pris.
Je vais essayer de le faire, pour les packages dont j'ai besoin. Voyons ce qui se passe.
Il n'y a qu'une seule grande communauté :)
Je n'ai remarqué personne suggérant de séparer complètement la bibliothèque comme
lodash. Lodash est une collection d'utilitaires sous un nom commun ; vous taxi
prenez-en un seul morceau et utilisez-le. Threejs ne l'est pas ; c'est un exhaustif
bibliothèque, dont la plupart est inutile sans le reste. Il y a quelques morceaux
qui peuvent être séparés, tels que les types de matériaux spécifiques nos spécifiques
générateurs de géométrie, mais ceux-ci seront forcément très proches
lié au noyau, nécessitant probablement des correspondances de version exactes. Compte tenu de leur
taille, cela créerait un casse-tête de maintenance sans gain mesurable.
Si M. Doob approuvait une scission de cette nature, je ne pense pas qu'il
approprié pour n'importe qui sauf un responsable officiel de réclamer threejs-*
paquets.
Indépendamment de ce qui précède, je pense qu'il est prudent de le faire fonctionner dans un module
environnement avant toute autre chose. Il y avait plusieurs projets avec ce
but, mais tous semblent avoir pataugé.
Le 6 mars 2016 à 11h39, "Gianluca Casati" notifications@github.com a écrit :
Ok, nous avons tous eu la même idée. Ce serait bien d'avoir une histoire comme
lodash.Je propose de créer un package _three-foo_ pour chaque composant _foo_ (pour
exemple trois-vecteur2) qui peut être modularisé, avec presque aucun changement dans
le code, il peut donc être importé dans ce référentiel sans impact.Les personnes qui publient sur npm devraient bien jouer et collaborer avec @mrdoob
https://github.com/mrdoob puisqu'il est le créateur de cette grande pièce
de logiciels, donc s'il veut centraliser à nouveau tous les packages comme dans
_babel_, l'éditeur devrait lui donner le contrôle sur l'espace de noms npm pris.Je vais essayer de le faire, pour les packages dont j'ai besoin. Voyons ce qui se passe.
Il n'y a qu'une seule grande communauté :)
-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment - 192970867.
@mattdesl : par exemple, votre three-shader-fxaa utilise THREE.Vector2 et THREE.Texture, mis à part le compositeur à trois effets que je n'ai pas vérifié, cela donnerait une construction vraiment légère en utilisant l'approche de modularité proposée ci-dessus.
@HMUDesign : Je comprends vos doutes, mais cela me semble quand même une bonne approche. Je veux essayer, mais j'écouterai vos conseils, en utilisant les packages npm des URL GitHub, sans les publier sur le registre sacré .
Je l'ai essayé, en commençant par TrackballControls qui dépend de Vector2, Vector3, Quaternion et ainsi de suite.
Il existe des deps circulaires (par exemple Matrix4 dépend de Vector3 et vice versa). Cela ne peut pas être fait si la lib (c'est-à-dire threejs) a été démarrée de manière monolithique.
Il est dommage que le modèle de module avec tous ses avantages ne puisse pas être appliqué facilement sur des projets importants comme celui-ci.
J'essaye aussi avec d'autres projets comme svg.js, vvvvjs, voire x3dom, mais si les auteurs ne sont pas totalement convaincus de ce choix radical cela ne peut pas être fait.
Désolé pour le spam, mais je voulais essayer de manière proactive : en passant, j'ai commencé avec le dépôt de trois trackballcontrols .
@fibo ES6 Le modèle de module ne devrait pas avoir de problèmes avec les dépendances circ. Les liaisons ne sont-elles pas configurées avant l'exécution du module, tout comme le levage en JS simple ?
Je suis sûr que vous avez vu ceci : https://github.com/kamicane/three-commonjsify Il l'a résolu en commonJS.
@drcmda vraiment intéressant, je vais essayer
+1 pour passer à une architecture modulaire.
+1
+1
@drcmda a raison. Les modules ES6 ont une étape d'initialisation et une étape d'exécution qui permettent des références circulaires. Cependant, dès que vous rencontrez des dépendances circulaires directement à partir du contexte d'exécution du module (dans la zone globale d'un module), le premier chargé pendant l'exécution connaîtra des valeurs indéfinies pour ses dépendances. Tant que les références sont utilisées dans un contexte différent où l'ordre d'exécution d'exécution est important, les dépendances circulaires ne posent aucun problème.
Je suggère d'envisager également webpack au lieu de browserify.
@gionkunz nous avons des références circulaires dans l'étape d'initialisation bc du motif où il y a une fermeture pour générer des variables de scratch
La version bêta de Webpack 2 vient de sortir (https://twitter.com/TheLarkInn/status/747955723003322368/photo/1), les modules es6 pourraient donc également bénéficier du tremblement des arbres lorsqu'ils sont regroupés.
@mrdoob
Y a-t-il eu une déclaration officielle plus récemment? Comme beaucoup, nous avons abandonné ES5 et les concats de colle il y a longtemps et c'est assez grave à quel point THREE sort de la ligne dans un système de construction moderne. Nous utilisons peut-être 10% de ce qu'il peut faire, mais c'est la plus grande dépendance que nous expédions.
C'est peut-être le projet le plus préféré sur Github pour moi personnellement - j'espère sincèrement que les priorités seront reconsidérées.
Hmm, j'aimerais en savoir plus sur la prise en charge du navigateur. Quels navigateurs le font et lesquels ne le font pas. Pour les navigateurs qui ne le font pas, quelles sont les solutions de contournement et quelles sont les pénalités de performance.
En fait, la prise en charge du navigateur devient un non-problème (peut-être encore moins qu'elle ne l'est maintenant). Les systèmes de construction prennent ce code ES6 et le transpilent en es5 (prenant parfois moins d'espace que l'ES5 d'origine). Certains types de choses transpilées finissent par être volumineuses (principalement : les générateurs et les fonctions asynchrones), mais si vous les évitez, vous n'aurez pas cette pénalité.
Comme @drcmda l'a mentionné, le système de construction produirait toujours une sortie monolithique (et serait très facile de personnaliser exactement ce qui est inclus dans cette sortie), mais les modules individuels pourraient également être inclus dans nos propres projets, n'utilisant ainsi que les pièces qui nous avons besoin. Pour profiter pleinement de
que les interdépendances doivent être ajustées, mais cela peut arriver avec le temps. Je pense que les principales fonctionnalités que nous voulons sont de le modulariser avec l'import/export. De votre point de vue, cela permettrait l'utilisation de classes sur des prototypes (ils utilisent toujours des prototypes sous le capot, vous pouvez donc toujours
jouer avec si nécessaire).
Il existe quelques systèmes de construction. Mon vote serait webpack (qui utilise babel pour le transpiling). Avec babel, vous pouvez définir des chargeurs personnalisés, de sorte que le système de segmentation que vous avez développé pour les shaders pourrait être réduit au code glsl réel avec une extension #include (je fais mes shaders de cette façon et je serais heureux de le contribuer au projet). Cela permet d'obtenir les mêmes avantages que votre système (pas de duplication de code), mais est très simple à utiliser.
J'adorerais faire partie du projet de modularisation, mais je sais que cela ne réussira en aucun cas sans votre soutien (et probablement votre assistance). Beaucoup d'entre nous savent comment utiliser la bibliothèque, mais aucun d'entre nous ne sait comment elle fonctionne en interne dans la mesure où vous le faites.
Certains types de choses transpilées finissent par être volumineuses (principalement : les générateurs et les fonctions asynchrones), mais si vous les évitez, vous n'aurez pas cette pénalité.
Large comment?
De plus, vous n'avez pas parlé de pénalité de performance. N'est-ce pas un problème alors?
Autant que je sache, les importations ES6 ne sont toujours prises en charge par aucun navigateur , donc ce refactor de module serait principalement destiné aux systèmes de construction, n'est-ce pas ?
N'oubliez pas les avantages que vous obtenez en utilisant des outils tels que rollupjs, cela exclurait automatiquement toutes les exportations qu'un utilisateur n'utilise pas. (Ce qui est par défaut avec JSPM)
Le package babel-polyfil, qui n'est nécessaire que si vous utilisez
générateurs (qui n'ont probablement même pas de sens dans ce projet) ou async
fonctions (que je ne pense pas vraiment changerait beaucoup dans le projet
soit), ajoute environ 50k à la version finale. Mais encore une fois, c'est facultatif.
En ce qui concerne les performances, cela dépend vraiment des fonctionnalités exactes que vous utilisez.
à l'aide de. Par exemple, les fonctions fléchées sont un peu plus lentes, en raison de la
liaison sous-jacente, les classes sont un peu plus lentes à créer, bien que le
le temps d'instanciation est le même. https://kpdecker.github.io/six-speed/
Les importations/exportations ES6 ne sont pas prises en charge par les navigateurs, mais depuis
via un système de construction, ce n'est pas un problème. La sortie du produit serait
utilisable exactement tel qu'il est actuellement (même en étant rétrocompatible), mais
lui permettrait d'être intégré dans nos systèmes de construction, et rendrait le
composants internes réutilisables pour nous.
Une autre chose à noter est la taille finale de la construction. Actuellement, des choses comme la géométrie,
Material, Mesh, etc. font partie de l'espace de noms TROIS. Une fois minifié,
les références à THREE.Geometry, THREE.Material, THREE.Mesh, etc.
code. Avec un système modulaire, chacun de ces fichiers obtiendrait quelque chose comme
var Geometry = require('./geometry');
ont alors des références au
variable Geometry
plus tard. Puis au minifaciton, Geometry
et require
sont tous deux basculés sur des caractères uniques, le './geometry' est remplacé par un
nombre, ce qui permet de réaliser pas mal d'économies. Serviette de table : le minifié
build fait 511 794 octets et contient 2942 références à
THREE\.[A-Z][a-zA-Z]+
. Remplacer tout cela par un seul caractère
entraîne une réduction de la taille du fichier de près de 10 % (jusqu'à 464 782). (Le gzip
les tailles sont respectivement de 117 278 et 110 460, soit une réduction de 6 %). La construction
pourrait probablement être ajusté pour réduire encore plus cela.
Le cumul (qui a éliminé le code inutilisé d'une version finale) est la valeur par défaut
avec jspm, sera la valeur par défaut avec webpack2 (et je pense qu'il peut être utilisé
avec webpack). Si les choses sont écrites de manière modulaire, je ne pense pas que ce sera
utile, cependant. Dans tous les cas, tant que le code peut être transpilé avec
babel, il peut être utilisé dans n'importe quel système de construction (le chargeur glsl que j'ai mentionné
avant peut également être fait pour fonctionner avec webpack).
Le jeu. 7 juillet 2016 à 13:28, Mr.doob notifications@github.com a écrit :
Certains types de choses transpilées finissent par être volumineuses (principalement :
générateurs et fonctions asynchrones), mais si vous les évitez, vous n'aurez pas
cette pénalité.Large comment?
-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -231197171,
ou couper le fil
https://github.com/notifications/unsubscribe/AA71cqAqmgxsUjpvamnI_xyL2wpzeWrdks5qTWGBgaJpZM4B4aA7
.
Je ne sais pas si cela est très utile, mais c'est le fil de discussion pour D3 concernant le même problème : https://github.com/d3/d3/issues/2220. D3 4.0 a adopté l'import/export ES6 pour gérer les modules, mais est toujours écrit en ES5 (https://github.com/d3/d3/issues/2220#issuecomment-111655235).
Très intéressant @jpweeks !
Alors... avec cette approche d'import/export... A quoi ressembleraient des trucs comme object instanceof THREE.Mesh
?
@mrdoob
import/export
est juste la façon dont les modules sont déclarés et requis. Cela n'affectera/changera pas du tout le code défini dans les modules :
src/Objects/Mesh.js
// Mesh class, stays the same as today (except the export part)
var Mesh = function ( geometry, material ) {
// ...
}
export default Mesh
src/Trois.js
// Library entry point, exports all files using som bundling tech
// In a "THREE" namespace for browsers
// As import three from 'three' in node
import Mesh from './objects/Mesh'
export {Mesh} // All three objects, such as Geometry, Material etc..
Application.js
// In node
import {Mesh} from 'three'
var mesh = new Mesh(geo, mat)
console.log(mesh instanceof Mesh) // true
Client.js
// In a browser
var mesh = new THREE.Mesh(geo, mat)
console.log(mesh instanceof THREE.Mesh) // true
C'est super utile @GGAlanSmithee ! Merci!
Je suis une personne visuelle donc les exemples de pseudo-code me convainquent plus que de gros morceaux de texte 😅
Bon, il faudra donc un peu de refactorisation...
Est-ce que quelqu'un sait si le compilateur de fermeture prévoit de prendre en charge cela?
Bon, il faudra donc un peu de refactorisation...
Je t'ai eu! Depuis que ce fil s'est animé ces derniers jours, j'ai travaillé un peu plus sur three-jsnext . C'est un projet qui prend la base de code Three.js existante et la transforme automatiquement en modules ES. Je me dispute juste avec quelques dépendances cycliques délicates (en particulier autour de KeyframeTrack
), mais devrait avoir quelque chose à partager très bientôt. Pour autant que je sache, tous les exemples continuent de fonctionner et la version minifiée est plus petite que la version actuelle (en utilisant Rollup pour générer un fichier UMD), donc c'est une bonne nouvelle.
Ok, j'ai ouvert une pull request pour ça : #9310
@mrdoob
Nous avons une bibliothèque en production qui est plus ou moins structurée comme TROIS. Il fonctionne dans les navigateurs et les environnements modulaires. La base de code est ES6 mais les navigateurs ne vous concernent pas du tout.
Vous l'enverriez sur npm _as is_, tous les modules inclus + un monolithe de navigateur d'espace de noms global compilé (three.js). Celui qui a besoin d'en utiliser des parties individuelles utilise des outils pour créer des bundles.
Considérons une structure comme celle-ci :
/src
classA.js
classB.js
classC.js
/index.js
/browser.js
index.js réexporte simplement tous les modules et fonctions dans un seul fichier :
export ClassA from './src/classA';
export ClassB from './src/classB';
export ClassC from './src/classC';
Ainsi, l'utilisateur final peut npm installer la bibliothèque et l'utiliser sans plus tarder :
// all exports from index.js will be under: mylib.ClassA, etc.
import * as mylib from 'libname':
// selected exports from index.js
import { ClassA, ClassC } from 'libname';
// or, specific modules
import ClassB from 'libname/src/classB'
browser.js serait la seule partie compilée du package. Habituellement transpilé vers ES5 via Babel et exporté dans un espace de noms global afin qu'il puisse être utilisé comme script include. Rollup, Webpack, etc. peuvent le créer facilement.
@mrdoob ça a été une balade merveilleuse
Commentaire le plus utile
Je t'ai eu! Depuis que ce fil s'est animé ces derniers jours, j'ai travaillé un peu plus sur three-jsnext . C'est un projet qui prend la base de code Three.js existante et la transforme automatiquement en modules ES. Je me dispute juste avec quelques dépendances cycliques délicates (en particulier autour de
KeyframeTrack
), mais devrait avoir quelque chose à partager très bientôt. Pour autant que je sache, tous les exemples continuent de fonctionner et la version minifiée est plus petite que la version actuelle (en utilisant Rollup pour générer un fichier UMD), donc c'est une bonne nouvelle.