Browserify
Pindah ke arsitektur ini memiliki kelebihan dan kekurangan. Silakan tambahkan pemikiran Anda.
Catatan: ini tidak memerlukan konsumen three.js untuk menggunakan browserify.
Salah satu keuntungannya adalah bahwa ini akan menerapkan arsitektur modular untuk pengembangan berkelanjutan dari three.js.
Gaya umum di node/browserify membuat setiap file mendeklarasikan dependensinya di bagian atas, dan menganggap variabel global sebagai anti-pola.
Berikut adalah contoh cuplikan:
// src/geometry/BoxGeometry.js
var Geometry = require('./Geometry.js');
var Vector3 = require('../core/Vector3.js');
module.exports = BoxGeometry;
function BoxGeometry() {
// ...
}
BoxGeometry.prototype = Geometry.prototype;
Keuntungan lainnya adalah konsumen three.js
menggunakan browserify dapat memilih suku cadang yang mereka inginkan. Mereka hanya bisa mengimpor Scene
, BoxGeometry
, PerspectiveCamera
, dan WebGLRenderer
, mendapatkan dependensi untuk semua itu secara otomatis ( Object3D
dll ), dan memiliki bundel kecil javascript yang hanya mendukung set fitur yang mereka inginkan.
Ini dapat dilakukan dengan cara yang tidak memaksakan perubahan yang melanggar. Di tingkat atas, kami akan mengekspor semua kelas yang kami anggap sebagai bagian dari paket standar
// src/three.js
var THREE = { rev: 101 }
module.exports = THREE
THREE.Geometry = require('./geometry/Geometry.js')
THREE.BoxGeometry = require('./geometry/BoxGeometry.js')
// ...
catatan: Saya tidak benar-benar membutuhkan dependensi di bagian atas dalam contoh ini, karena file ini hampir secara eksklusif membutuhkan pernyataan.
Akhirnya kami akan membungkusnya dalam Definisi Modul Universal yang mendeteksi jika sistem modul (node/browserify, AMD) sedang digunakan, dan jika demikian mengekspornya, atau menambahkannya ke objek global ( window
).
Mari kita tinjau:
three.js
menggunakan browserify untuk memilih dan memilih fungsionalitasIni akan membutuhkan penggantian sistem build, tetapi yang baru akan cukup mudah.
Beberapa keuntungan lainnya:
@shi-314 Saya kira saya sedikit bingung, saya merasa You can structure your code
dan You can build for production
adalah hal-hal yang dapat Anda lakukan tanpa perubahan arsitektur? Apakah Anda berbicara tentang sumber three.js atau hal-hal yang dibangun menggunakan three.js?
Salah satu praktik yang digunakan three.js yang membuatnya sulit untuk digunakan di lingkungan commonjs adalah penggunaan instanceof
: https://github.com/mrdoob/three.js/blob/master/src/core/Geometry .js#L82
Ini karena dalam aplikasi Anda sering berakhir dengan versi berbeda dari pustaka yang sama di pohon sumber Anda, jadi memeriksa instanceof tidak berfungsi di antara versi berbeda dari pustaka yang sama. Akan lebih baik dalam persiapan untuk pindah ke sistem modul commonjs untuk menggantikan pemeriksaan instanceof tersebut dengan pemeriksaan fitur di belakang antarmuka gaya Geometry.isGeometry(geom)
.
@kumavis Saya berbicara tentang hal-hal yang dibangun di three.js. Katakanlah Anda ingin membuat materi Anda sendiri dengan shader Anda, dll. Saat ini Anda perlu memperluas objek THREE global agar tetap konsisten dengan kode three.js lainnya:
THREE.MeshMyCoolMaterial = function (...) { ... }
Tetapi jika kami memiliki Browserify daripada yang dapat Anda lakukan:
var MeshLambertMaterial = require('./../MeshLambertMaterial');
var MeshMyCoolMaterial = function (...) {...}
Jadi namespace Anda tetap konsisten dan Anda tidak perlu menggunakan THREE.MeshLambertMaterial
dan MeshMyCoolMaterial
dalam kode Anda.
Dan dengan You can build for production
pada dasarnya maksud saya sama dengan yang Anda sebutkan: allows three.js consumers using browserify to pick and choose functionality
.
@shi-314 terima kasih, itu lebih jelas. Itu berdampak pada solusi umum yang saya usulkan untuk deserialisasi kelas yang ditentukan konsumen:
// given that `data` is a hash of a serialized object
var ObjectClass = THREE[ data.type ]
new ObjectClass.fromJSON( data )
Ini dari refactor serialisasi/deserialisasi yang saya usulkan
https://github.com/mrdoob/three.js/pull/4621
Performa seharusnya tidak terpengaruh oleh perubahan seperti ini.
Ini adalah perubahan yang cukup besar tetapi saya juga mendukungnya.
Beberapa keuntungan utama lainnya:
standalone
browserify untuk menghasilkan build UMD untuk Anda. Tidak perlu mengotak-atik secara manual dengan pembungkus UMD.threejs-vecmath
tanpa khawatir tentang pemecahan kode semua orang. Dan di sisi lain, jika kita membuat patch atau rilis minor pada modul tertentu, orang yang menggunakan modul tersebut akan bisa mendapatkan perubahan secara otomatis.npm install threejs-shader-bloom
)require()
modul yang sebenarnya digunakan oleh aplikasi kita.Kepada @mrdoob dan penulis lainnya; jika Anda tidak memiliki banyak pengalaman dengan NPM/Browserify, saya akan menyarankan untuk membuat beberapa proyek kecil dengannya dan merasakan "filosofi"-nya. Ini sangat berbeda dari arsitektur ThreeJS; daripada kerangka besar itu mendorong banyak hal-hal kecil .
Keuntungan lain dari pendekatan ini adalah bahwa bisa ada ekosistem open source, modul Three.JS pihak ketiga, terutama shader, geometri, model loader, dll. Diterbitkan melalui NPM atau Github/Component yang kemudian dapat dengan mudah dirujuk dan digunakan orang. Saat ini barang-barang dibagikan dengan mengadakan demo yang kemudian orang-orang 'melihat sumber'. Three.JS layak mendapatkan yang lebih baik!
Saya pikir salah satu masalah yang saya miliki dengan Three.JS adalah seberapa cepat kode menjadi tidak kompatibel dengan versi Three.JS saat ini. Keuntungan lain dari beralih ke sesuatu seperti ini adalah dapat menentukan versi _bits_ tertentu dari Three.JS akan sangat kuat dan praktis.
+1
+1 untuk arsitektur CommonJS/browserify, itu akan membuat inti lebih ringan dan ekstensi akan cocok bahkan jika mereka berasal dari pihak ketiga
Memecahkan three.js menjadi modul kecil juga membutuhkan banyak biaya. Sistem saat ini memungkinkan tambahan pihak ketiga yang cukup sederhana (saksi misalnya modul THREEx jetienne). Ada banyak yang bisa dikatakan tentang kesederhanaan pengaturan saat ini, selama sistem modul JS hanya membungkus sistem build.
Cara lain untuk meminimalkan ukuran build adalah yang dilakukan ClojureScript. Mereka mengikuti beberapa konvensi untuk memungkinkan kompiler Penutupan Google melakukan analisis seluruh program dan penghapusan kode mati.
+1 untuk keanggunan kesederhanaan yang tidak dihargai, dan sering diabaikan
+1
Memecahkan three.js menjadi modul kecil juga membutuhkan banyak biaya. Sistem saat ini memungkinkan tambahan pihak ketiga yang cukup sederhana (saksi misalnya modul THREEx jetienne).
Idenya di sini adalah bahwa build UMD akan tetap disediakan untuk lingkungan non-Node. Plugin seperti THREEx akan bekerja dengan cara yang sama untuk mereka yang bergantung pada ThreeJS dengan tag <script>
.
Hal yang rumit adalah: bagaimana kita require()
plugin tertentu jika kita berada di lingkungan CommonJS? Mungkin browserify-shim bisa membantu.
Ada banyak yang bisa dikatakan tentang kesederhanaan pengaturan saat ini, selama sistem modul JS hanya membungkus sistem build.
Sistem plugin/ekstensi ThreeJS saat ini cukup buruk untuk digunakan, dan jauh dari "sederhana" atau mudah. Sebagian besar proyek ThreeJS cenderung menggunakan beberapa bentuk plugin atau ekstensi, seperti EffectComposer, atau FirstPersonControls, atau pemuat model, atau salah satu dari banyak file JS lain yang beredar di folder examples
. Saat ini satu-satunya cara untuk bergantung pada plugin ini:
vendor
Sekarang, bayangkan, dengan browserify Anda dapat melakukan sesuatu seperti ini:
var FirstPersonControls = require('threejs-controls').FirstPersonControls;
//more granular, only requiring necessary files
var FirstPersonControls = require('threejs-controls/lib/FirstPersonControls');
Plugin tersebut akan require('threejs')
dan apa pun yang mungkin mereka perlukan (seperti cuplikan GLSL atau triangulasi teks ). Manajemen ketergantungan/versi semuanya tersembunyi bagi pengguna, dan tidak perlu untuk tugas-tugas grunt/gulp concat yang dikelola secara manual.
Hal yang rumit adalah: bagaimana kita membutuhkan() plugin tertentu jika kita berada di lingkungan CommonJS?
Saya telah menggunakan CommonJS untuk proyek TIGA.js sekarang. Ini sedikit proses manual, mengubah potongan kode orang lain menjadi modul dan saya tidak berpikir akan ada cara mudah untuk menghindarinya untuk kode lama yang tidak dikonversi oleh penulis atau kontributor.
Yang penting adalah bahwa ada modul yang mengekspor seluruh objek TIGA 'standar', yang kemudian dapat diminta oleh apa pun yang ingin memperluasnya.
var THREE = require('three');
THREE.EffectComposer = // ... etc, remembering to include copyright notices :)
Ini telah bekerja cukup baik untuk saya, terutama ketika proyek berkembang dan saya mulai menambahkan shader dan geometri saya sendiri ke dalam modul mereka sendiri, dll.
Selama ada paket npm 'threejs-full' atau 'threejs-classic' maka ini menjadi cara yang cukup layak untuk bekerja dengan barang-barang Three.js lama di lingkungan CommonJS tapi saya curiga ini cukup niche!
+1
Saya percaya setelah modul threejs yang terfragmentasi tersedia di npm, plugin
pengembang akan senang bermigrasi ke CommonJS env.
Pada tanggal 5 Juni 2014 21:19, "Charlotte Gore" [email protected] menulis:
Hal yang sulit adalah: bagaimana kita membutuhkan() plugin tertentu jika kita
berada di lingkungan CommonJS?Saya telah menggunakan CommonJS untuk proyek TIGA.js sekarang. Itu sedikit
dari proses manual, mengubah potongan kode orang lain menjadi modul
dan saya tidak berpikir akan ada cara mudah untuk menghindarinya untuk kode lama
yang tidak dikonversi oleh penulis atau kontributor.Yang penting adalah ada modul yang mengekspor seluruh 'standar'
TIGA objek, yang kemudian dapat diminta oleh apa pun yang ingin diperluas
dia.var TIGA = membutuhkan('tiga');
THREE.EffectComposer = // ... dll, ingat untuk menyertakan pemberitahuan hak cipta :)Ini telah bekerja cukup baik untuk saya, terutama ketika proyek tumbuh dan saya
mulai menambahkan shader dan geometri saya sendiri ke dalam modul mereka sendiri, dll.Selama ada paket npm 'threejs-full' atau 'threejs-classic' maka
ini menjadi cara yang cukup layak untuk bekerja dengan barang-barang Three.js lama di a
Lingkungan CommonJS tapi saya curiga ini cukup niche!—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -45236911.
Bisa juga membuat shader dibuat modular juga, misal menggunakan glslify . Bahkan hal-hal seperti membuat middleware Express yang menghasilkan shader sesuai permintaan menjadi lebih mudah.
Beberapa bulan yang lalu saya memindahkan frame.js ke require.js dan akhirnya saya mengerti cara kerja AMD ini.
Saya masih perlu belajar, bagaimanapun, bagaimana "mengkompilasi" ini. Apa alat/alur kerja untuk menghasilkan three.min.js
dari daftar modul?
Saya lebih suka gulp.js sebagai sistem build dengan plugin gulp-browserify . Sangat mudah dimengerti dan kodenya terlihat lebih bersih daripada gerutuan menurut saya. Lihat ini: http://travismaynard.com/writing/no-need-to-grunt-take-a-gulp-of-fresh-air :wink:
beberapa pemikiran: (berdasarkan pengalaman saya yang terbatas dengan node, npm, tentu saja browserify)
yang mengatakan, mengikuti diskusi di utas ini, saya tidak yakin apakah semua orang memiliki pemahaman yang sama tentang browserify (browserify, commonjs, requirejs, amd, umd agak terkait meskipun mungkin tidak perlu hal yang sama).
sekarang jika Anda dapat mengikuti rantai pemikiran saya sedikit.
Di situlah Browserify muncul. Nah, secara teknis seseorang dapat menggunakan requireJS di browser. Tetapi Anda ingin menggabungkan file js bersama-sama tanpa membuat terlalu banyak panggilan jaringan (tidak seperti sistem file yang membutuhkan () yang cepat). Di sanalah Browserify melakukan beberapa hal keren seperti analisis statis untuk melihat modul mana yang perlu diimpor dan membuat build yang lebih dioptimalkan untuk aplikasi Anda. (Tentu saja ada batasan, mungkin tidak dapat menguraikan require('bla' + variabel)) bahkan dapat menukar bagian yang memerlukan lapisan emulasi untuk hal-hal yang bergantung pada node.js. ya, ini menghasilkan build js yang sekarang dapat saya sertakan di browser saya.
Berikut adalah beberapa hal yang dapat dilakukan browserify https://github.com/substack/node-browserify#usage
Kedengarannya seperti semuanya bagus sejauh ini... tapi ada beberapa poin yang menurut saya layak dipertimbangkan untuk pindah ke "arsitektur browser"
Jadi jika kita melihat keragaman ini dan pemuatan modul yang nyaman (terutama mengendarai ekosistem npm) bersama dengan build yang disesuaikan adalah hal yang hebat, maka mungkin ada baiknya melakukan perubahan paradigma, refactoring kode dan mengubah sistem build kita saat ini.
@mrdoob beberapa alat di sekitar browserify tercantum di sini: https://github.com/substack/node-browserify/wiki/browserify-tools.
mengenai three.min.js
, Anda tidak akan menggunakan kode yang diperkecil dalam proyek Anda. yang Anda lakukan hanyalah var three = require('three')
di project.js
dan kemudian jalankan browserify project.js > bundle.js && uglifyjs bundle.js > bundle.min.js
. catatan: Anda masih dapat mengirimkan kode yang diperkecil seharga <script src="min.js">
.
saya saat ini membungkus three.js dengan
if ('undefined' === typeof(window))
var window = global && global.window ? global.window : this
var self = window
dan
module.exports = THREE
lalu saya membungkus ekstensi dengan
module.exports = function(THREE) { /* extension-code here */ }
jadi saya bisa memintanya seperti itu:
var three = require('./wrapped-three.js')
require('./three-extension')(three)
jadi ini tidak optimal, tetapi saya pribadi sebenarnya dapat menerimanya dan berpikir itu tidak terlalu buruk - meskipun proposal @kumavis akan menjadi keuntungan _besar_.
tapi mungkin masuk akal untuk membagi tiga dan meletakkan semua hal di modul terpisah hanya untuk melihat bagaimana hasilnya.
juga checkout http://modules.gl/ yang sangat didasarkan pada browserify (meskipun Anda dapat menggunakan setiap modul sendiri tanpa browserify).
@mrdoob @shi-314 gulp-browserify telah masuk daftar hitam karena hanya menggunakan browserify secara langsung (yaitu melalui vinyl-source-stream).
Alat seperti grunt/gulp/etc terus berubah, dan Anda akan menemukan banyak pendapat yang berbeda. Pada akhirnya tidak masalah yang Anda pilih, atau apakah Anda hanya melakukannya dengan skrip khusus. Pertanyaan yang lebih penting adalah: bagaimana pengguna akan menggunakan ThreeJS, dan seberapa banyak kompatibilitas mundur yang ingin Anda pertahankan?
Setelah beberapa pemikiran lagi, saya pikir akan _sangat_ sulit untuk memodulasi semuanya tanpa sepenuhnya memfaktorkan ulang kerangka kerja dan arsitekturnya. Berikut adalah beberapa masalah:
../../../math/Vector2
jelek dll.three-scene
akan dipisahkan dari three-lights
dll. Kemudian Anda dapat membuat versi setiap paket secara terpisah. Fragmentasi semacam ini tampaknya tidak realistis untuk kerangka kerja sebesar ThreeJS, dan akan sulit untuk dipertahankan.require('three/src/math/Vector2')
Saran saya? Kami mempertimbangkan dua hal untuk maju:
Saya ingin melihat semuanya termodulasi, tetapi saya tidak yakin dengan pendekatan yang realistis untuk ThreeJS. Mungkin seseorang harus melakukan eksperimen di garpu untuk melihat seberapa layak hal itu.
Terima kasih atas penjelasannya teman-teman!
Yang saya takutkan adalah memperumit hal-hal bagi orang-orang yang baru memulai. Memaksa mereka untuk mempelajari hal-hal browserify/modul ini mungkin bukan ide yang baik ...
Harus setuju dengan @mrdoob di sini. Saya, dan banyak rekan, bukan pemrogram web (lebih tepatnya VFX/TD animasi). Mengambil WebGL dan Tiga tentu saja sudah cukup bekerja seperti di atas beban kerja kami saat ini (dan dalam beberapa kasus beberapa dari kami harus belajar js di tempat). Banyak dari apa yang saya baca di utas ini, kadang-kadang, membuat saya bergidik memikirkan berapa banyak lagi pekerjaan yang akan ditambahkan ke piring saya jika Tiga pindah ke struktur ini. Saya bisa saja salah, tetapi begitulah yang terbaca bagi saya.
Dengan build UMD ( browserify --umd
) yang telah dikompilasi di repo, tidak ada perubahan pada alur kerja untuk pengembang yang ada.
@mrdoob Ide sistem manajemen ketergantungan adalah kesederhanaan. Membaca lusinan posting tentang opsi dan membangun sistem mungkin berlebihan, tetapi pada akhirnya sistem saat ini tidak berkelanjutan. Setiap kali satu file bergantung pada yang lain, itu adalah perburuan -dan- pencarian yang harus dilakukan pengembang baru untuk menemukan referensi. Dengan browserify, ketergantungannya eksplisit dan ada jalur ke file.
@repsac Sistem ketergantungan harus membuat Tiga lebih mudah diakses oleh pengguna bahasa lain karena menghindari cakupan global, memuat mimpi buruk urutan dan mengikuti paradigma yang mirip dengan bahasa populer lainnya. var foo = require('./foo');
adalah (loosly) mirip dengan C # 's using foo;
atau Jawa import foo;
Saya ingin melihat semuanya termodulasi, tetapi saya tidak yakin dengan pendekatan yang realistis untuk ThreeJS. Mungkin seseorang harus bereksperimen di garpu untuk melihat seberapa layak hal itu
Saya pikir ini adalah cara untuk pergi, sungguh. Selesaikan pekerjaan, tunjukkan cara kerjanya.
Dan mengkonsumsi API akan cukup
ugly: require('three/src/math/Vector2')
Sebagai percobaan, saya baru saja mengonversi 'memulai' dari Tiga dokumen ke pendekatan modular baru ini. Saya bisa membayangkan ada banyak referensi kecuali orang-orang cukup ketat dalam memecah kode mereka menjadi modul-modul kecil.
Keuntungan utama dari melakukan ini adalah bahwa ukuran build yang dihasilkan akan menjadi sebagian kecil dari ukuran Three.js penuh karena Anda hanya akan memasukkan hal-hal yang secara khusus dirujuk di sini dan kemudian hal-hal yang bergantung pada hal-hal itu.
Saya kira mereferensikan semua dependensi yang Anda butuhkan (dan menginstal semuanya secara individual) dapat terbukti agak terlalu buruk dalam praktiknya.
Jika Anda secara eksplisit menargetkan perangkat seluler maka pendekatan yang sangat terperinci ini akan menjadi sempurna tetapi pada kenyataannya saya menduga kita akan membutuhkan paket yang mengekspor seluruh TIGA api yang akan berfungsi seperti biasa, kemudian paket yang lebih kecil yang merangkum semua geometri bonus, semua penyaji, semua matematika, semua materi dll, lalu turun ke tingkat modul individu sehingga pengembang dapat memutuskan sendiri.
Dan ya, pengkodean untuk web itu menyebalkan.
Pokoknya, dengan percobaan ...
Instal dependensi kami..
npm install three-scene three-perspective-camera three-webgl-renderer three-cube-geometry three-mesh-basic-material three-mesh three-raf
Tulis kode kita...
// 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();
lalu buat file kami
browserify entry.js -o scripts/hello-world.js
kemudian sertakan di halaman kami
<script src="/scripts/hello-world.js" type="text/javascript"></script>
Saya kira mereferensikan semua dependensi yang Anda butuhkan (dan menginstal semuanya secara individual) dapat terbukti agak terlalu buruk dalam praktiknya.
Pengguna akhir tidak perlu menggunakan browserify dalam proyek mereka agar Three menggunakan browserify untuk mengelola basis kodenya. Tiga dapat diekspos sebagai THREE
global seperti sekarang...termasuk file build dan jalankan dengannya.
@repsac @mrdoob perubahan akan kompatibel ke belakang, sehingga pengguna saat ini tidak perlu mengubah apa pun jika mereka tidak mau. Saran ini adalah untuk meningkatkan pemeliharaan jangka panjang dan umur panjang dari basis kode ThreeJS yang luas dan monolitik. Hal-hal seperti ketergantungan dan manajemen versi mungkin terdengar seperti memusingkan bagi yang belum tahu, tetapi mereka luar biasa untuk mereka yang mengembangkan alat, kerangka kerja, plugin, dan situs web skala besar di atas ThreeJS.
yaitu Kode pengguna akhir masih dapat terlihat sama, dan examples
tidak perlu diubah sama sekali:
<script src="three.min.js"></script>
<script>
var renderer = new THREE.WebGLRenderer();
</script>
Untuk pengembang yang lebih ambisius yang mencari bangunan modular, _atau_ bagi mereka yang ingin mengembangkan solusi jangka panjang di atas ThreeJS (yaitu dan memanfaatkan manajemen versi/dependensi), mungkin terlihat seperti ini:
npm install three-vecmath --save
Kemudian, dalam kode:
var Vector2 = require('three-vecmath').Vector2;
//.. do something with Vector2
Dan, lebih jauh lagi, ini memungkinkan orang untuk menggunakan hal-hal seperti matematika vektor ThreeJS, konversi warna, triangulasi, dll. di luar cakupan ThreeJS.
Meskipun saya pikir kekacauan require() adalah ide yang buruk dan tradeoff yang buruk, itu akan menjadi ide yang lebih buruk untuk mengekspos pengguna ke dua jenis kode three.js yang berbeda, memberi tahu pengguna satu adalah rasa sistem modul yang mewah dan yang lainnya adalah rasa sistem modul yang lebih sederhana (tetapi kelas dua).
@erno Saya pikir Anda melewatkan intinya, three.js
akan diatur oleh struktur modul secara internal, tetapi itu digunakan untuk menghasilkan file build yang tidak berbeda dari pengaturan saat ini.
Keuntungan utama adalah meningkatkan pengalaman mengembangkan dan memelihara three.js
.
@kumavis - tidak @erno sebenarnya tidak melewatkan itu, tapi saya mengerti(*) bahwa dia menyatakan bahwa jika three.js
terkadang digunakan melalui require dan terkadang tidak, itu bisa membingungkan. Misalnya seseorang melihat keduanya pada tiga sumber dan kemudian beberapa contoh pihak ke-3 dan menemukan perbedaan dalam cara kerjanya dan semuanya.
(*) kita sudah membicarakan ini di irc hari ini.
Saya pikir itu semacam poin yang valid tetapi saya tidak yakin apakah/bagaimana cara kerjanya pada akhirnya - apakah itu benar-benar masalah dengan modul & membangun penggunaan. Tapi tentu tampaknya layak untuk dipikirkan dan secara keseluruhan tampak baik bagi saya bahwa masalah keseluruhan telah dipertimbangkan di sini dengan cermat, terima kasih atas info dan pandangan sejauh ini dari pihak saya.
@anton saya mengerti. Orang-orang telah menyarankan berbagai pendekatan berbeda di sini, saya berasumsi bahwa kami terutama akan menyediakan dokumentasi untuk penggunaan tingkat atas (menarik semuanya dari THREE
), tetapi orang lain mungkin membuat contoh yang tidak akan mengikuti ini dan mungkin menyebabkan beberapa kebingungan. Dan itu kekhawatiran yang valid.
Saya pikir saya agak bingung dengan bahasanya.
dan lainnya adalah rasa sistem modul yang lebih sederhana (tetapi kelas dua).
Ini hanya mengacu pada file build, ya?
Dalam pemahaman saya, ya. Tidak bisa membayangkan apa lagi selain bisa kehilangan sesuatu.
antont, kumavis: Proposal di sini telah berbicara tentang mengekspos kode gaya require() kepada pengguna akhir juga, lihat mis. komentar terbaru mattdesl.
"Untuk pengembang yang lebih ambisius yang mencari bangunan modular, atau bagi mereka yang ingin mengembangkan solusi jangka panjang di atas ThreeJS (yaitu dan memanfaatkan manajemen versi/dependensi) [...]"
salah satu cara untuk memiliki build yang lebih optimal sebenarnya adalah memiliki skrip yang mengetahui dependensi Anda secara otomatis dan menghasilkan modul yang diperlukan.
saat ini bower & browserify tidak diperlukan, tetapi itu bukan satu-satunya solusi. saya tidak tahu apakah ada proyek open source off-the-shelf lain yang melakukan itu (mungkin seperti ng-dependencies) tetapi saya telah menulis alat seperti itu sebelumnya saya pikir akan ada pendekatan lain untuk menyelesaikan rasa sakit ini.
kompiler penutupan google mungkin merupakan alat seperti itu?
Di sisi pengguna, mungkinkah ini bisa membantu?
http://marcinwieprzkowicz.github.io/three.js-builder/
itu cukup menarik @erichlof :) saya ingin tahu apakah @marcinwieprzkowicz membuat ini dengan tangan... https://github.com/marcinwieprzkowicz/three.js-builder/blob/gh-pages/threejs-src/r66/modules.json
Salah satu praktik yang digunakan three.js yang membuatnya sulit untuk digunakan di lingkungan commonjs adalah penggunaan instanceof: https://github.com/mrdoob/three.js/blob/master/src/core/Geometry.js#L82
Ini karena dalam aplikasi Anda sering berakhir dengan versi berbeda dari pustaka yang sama di pohon sumber Anda, jadi memeriksa instanceof tidak berfungsi di antara versi berbeda dari pustaka yang sama. Akan lebih baik dalam persiapan untuk pindah ke sistem modul js umum untuk mengganti contoh pemeriksaan tersebut dengan pemeriksaan fitur di belakang antarmuka gaya Geometry.isGeometry(geom).
di git/three.js/src:
grep -r instanceof . | wc -l
164
di git/three.js/examples:
grep -r instanceof . | wc -l
216
jadi ada total 380 penggunaan instanceof
di three.js. Apa yang akan menjadi implementasi terbaik sebagai pengganti?
Saya baru-baru ini menambahkan properti type
yang dapat digunakan untuk menggantikan sebagian besar properti tersebut.
Saya baru-baru ini menambahkan properti tipe yang dapat digunakan untuk menggantikan sebagian besar dari mereka.
baik! Akan menyiapkan PR.
Untuk contoh bagaimana ini ditangani di perpustakaan JS populer dan besar lainnya, lihat https://github.com/facebook/react . Basis kode disusun menggunakan sistem modul berbasis gaya simpul (yang diimplementasikan oleh browserify) tetapi dibuat untuk rilis menggunakan grunt. Solusi ini fleksibel untuk 3 kasus penggunaan.
require
dependensi spesifik. Manfaat dari manajemen ketergantungan yang tepat telah didokumentasikan dengan baik.Saya membuat beberapa penelitian ...
Kemarin saya meretas skrip (agak bodoh) yang mengubah kode sumber Three.js untuk menggunakan pernyataan CommonJS require()
untuk mendeklarasikan dependensi antar file. Hanya untuk melihat apa yang terjadi... Ini:
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');
Kami akan membutuhkan beberapa refactoring besar, mungkin membagi WebGLRenderer (dan semacamnya) menjadi beberapa modul (atm file lebih dari 6000 baris).
THREE.ShaderChunk
pada waktu kompilasi dan kemudian ke THREE.ShaderLib
saat runtime (bergabung dengan array THREE.ShaderChunk
s) yang agak sulit dilakukan hanya dengan browserify. Saya kira itu akan membutuhkan transformasi browserify yang melakukan hal yang sama.React.js menggunakan orang biasa untuk mencari modul mereka tanpa harus merujuknya melalui jalur file. Mungkin kita bisa melakukan hal yang sama dan juga menentukan aturan khusus yang memungkinkan kita mengubah file GLSL require
menjadi sintaks JS.
@rasteiner Anda mungkin sangat senang belajar tentang https://github.com/stackgl/glslify , itu berasal dari keluarga http://stack.gl yang berkembang
Saya memiliki sedikit pengalaman dengan modul dan pendekatan "unixy" dalam beberapa bulan terakhir dan pemikiran saya sekarang adalah bahwa itu terlalu sedikit terlambat, dan refactoring threejs untuk modul modularitas atau npm akan menjadi tujuan yang tidak realistis.
Inilah yang saat ini saya lakukan untuk mengatasi masalah modularitas/penggunaan kembali:
Proyek baru saya cenderung menggunakan "tiga" di npm hanya untuk bangun dan berjalan. Akan sangat luar biasa jika ThreeJS secara resmi menerbitkan build ke npm menggunakan tag versi yang sesuai dengan nomor rilis.
PS: bagi mereka yang tertarik untuk membawa shader yang dapat digunakan kembali/modular ke alur kerja mereka:
https://Gist.github.com/mattdesl/b04c90306ee0d2a412ab
dikirim dari iPhone saya
Pada 20 November 2014, pukul 07:42, aaron [email protected] menulis:
@rasteiner Anda mungkin sangat senang belajar tentang https://github.com/stackgl/glslify , itu berasal dari keluarga http://stack.gl yang berkembang
—
Balas email ini secara langsung atau lihat di GitHub.
Jika ini membantu orang lain yang mungkin mencari cara menggunakan Three.js dengan browserify, dan tersandung di utas ini, cara saya baru saja mengaturnya sendiri adalah dengan menggunakan browserify-shim .
Mengikuti bagian README pada _"Anda terkadang akan a) Mengekspos variabel global melalui global"_, saya menyertakan tag skrip terpisah untuk Three.js dan mengonfigurasinya untuk mengekspos variabel TIGA global.
Dan kemudian sedikit yang harus saya kerjakan sendiri adalah bagaimana memasukkan ekstra seperti ColladaLoader, OrbitControls dll. Saya melakukan ini seperti ini:
Dari 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" }
};
Kemudian dalam skrip saya sendiri, 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 memerlukan pembuatan ulang seluruh skrip saat Anda memodifikasi bahkan pada byte. Saya pernah menggunakan browserify untuk mengemas proyek yang membutuhkan THREE.js, kemudian dibutuhkan lebih dari dua detik untuk membuat batasan dan memblokir livereload setiap kali saya melakukan perubahan. Itu terlalu membuat frustrasi.
Anda biasanya menggunakan watchify selama pengembangan dengan livereload. Yang satu membangun bundel secara bertahap.
watchify tidak bekerja untuk saya. Ketika saya mengubah file dan menyimpannya, watchify dan livereload yang gemuk menyajikan versi yang lebih lama/cache. Saya tidak tahu mengapa ini terjadi. Untungnya, browserify sudah bekerja dengan cukup baik.
@ChiChou Lewati --noparse=three
ke browserify. Ini mengambil langkah bundel browserify dari 1000ms ke 500ms di mesin saya, yang cukup layak untuk merasakan umpan balik instan.
@rasteiner Saya ingin mengucapkan terima kasih lagi atas penelitian informal Anda tentang interdependensi three.js. Sementara daftar besar deps itu adalah beberapa kode yang tampak jelek, sebenarnya keburukan itu ada apa adanya, hanya tidak terlihat. Kekuatan Browserify adalah mengharuskan kita untuk mengudara cucian kotor kita dan mengejar sistem yang tidak terlalu kusut.
Ada banyak tempat di Three.js di mana kita mengambil beberapa objek, memahami jenisnya, dan melakukan tugas yang berbeda berdasarkan jenis itu. Dalam sebagian besar kasus tersebut, kode yang bergantung pada tipe itu dapat dipindahkan ke tipe itu sendiri, dan kita tidak perlu memiliki pemahaman tentang semua kemungkinan tipe yang sedang kita operasikan.
Berikut ini adalah contoh singkat dari WebGLRenderer :
if ( texture instanceof THREE.DataTexture ) {
// ...
} else if ( texture instanceof THREE.CompressedTexture ) {
// ...
} else { // regular Texture (image, video, canvas)
// ...
}
harus lebih dari bentuk
texture.processTexImage( _gl, mipmaps, otherData )
Biarkan tipe menentukan bagaimana menangani dirinya sendiri. Ini juga memungkinkan konsumen perpustakaan untuk menggunakan jenis Tekstur baru yang tidak terpikirkan oleh kami. Struktur ini harus mengurangi saling ketergantungan.
Saya pikir pindah ke arsitektur browserify jelas merupakan cara yang harus dilakukan. Pembangunan UMD akan membuat konsumsi THREE.js lebih mudah. Ini juga akan memungkinkan kita untuk membagi WebGLRenderer menjadi beberapa file, karena saat ini terlihat agak monolitik dan menakutkan.
Saya telah memulai cabang tempat saya sedang bekerja untuk memindahkannya ke sini: https://github.com/cobalast/three.js/tree/browserify-build-system
Tolong beritahu saya bagaimana menurut anda.
Inilah perubahan @cobalast .
Sepertinya Anda menggunakan pendekatan konversi otomatis dengan file browserifyify.js
, yang menurut saya adalah cara yang tepat.
Satu hal yang belum banyak kita diskusikan adalah cara terbaik untuk mentransisikan library besar yang selalu berubah ini ke browserify. Anda dapat membuat perubahan dan kemudian membuka PR, tetapi itu akan segera kedaluwarsa. Itulah yang menarik tentang pendekatan otomatis.
Jika kita bisa:
browserifyify.js
)...lalu kita dapat mengubahnya menjadi konversi tombol-tekan yang akan tetap berfungsi di masa mendatang. kesederhanaan itu memungkinkan gagasan melamun tentang pergeseran arsitektur mendasar ke proyek besar seperti itu untuk diselesaikan ketika argumen ideologis menang.
@cobalast untuk itu, saya akan menghapus perubahan ke src/Three.js jika berfungsi sama.
Catatan: tidak hanya mengembalikan, tetapi menghapus perubahan itu dari riwayat cabang melalui cabang baru atau dorongan paksa
@coballast Saya ingin tahu apakah akan lebih masuk akal jika utilitas konversi bukan garpu three.js
, tetapi utilitas eksternal yang Anda tunjuk pada direktori pengembangan three.js
, dan itu mengubah sumbernya file, menambahkan skrip build, dan menjalankan tes.
@kumavis Saya setuju dengan meninggalkan direktori src sendirian. Saya pikir hal yang harus dilakukan adalah meminta utilitas menulis direktori duplikat dengan kode commonjs, dan kita dapat menguji dan menjalankan browserify build dari sana untuk memastikan semua contoh berfungsi sebelum kita mencoba melakukan sesuatu yang besar.
Ada juga peluang menarik di sini untuk menulis beberapa hal analisis statis yang secara otomatis akan memeriksa dan menerapkan gaya yang konsisten di seluruh basis kode.
@cobalast terdengar hebat.
Ada banyak alat di luar sana untuk penulisan ulang kode otomatis, misalnya escodegen . Perlu memastikan bahwa kami mempertahankan komentar, dll.
Ingin memulai repo utilitas konversi threejs?
@cobalast yang mengatakan, mempertahankan fokus yang tajam untuk utilitas ini adalah penting
@kumavis Anggap sudah selesai. Saya sangat ingin ini terjadi. Ini hanya satu dari dua proyek yang saya kerjakan saat ini.
@kumavis @mrdoob Beberapa diskusi di sini tampaknya seputar gagasan membagi TIGA menjadi beberapa modul terpisah yang mungkin dapat diinstal melalui npm dan kemudian dikompilasi dengan browserify. Saya tidak langsung menentang gagasan itu, tetapi saya pikir itu harus menjadi masalah yang terpisah. Satu-satunya hal yang saya anjurkan pada saat ini adalah menggunakan browserify untuk mengelola basis kode TIGA secara internal. Pindahkan, dan buat bekerja dengan cara yang sama seperti biasanya bagi pengguna, lalu evaluasi apa yang masuk akal.
Saya akan penasaran untuk melihat apa output dari utilitas itu ^^
@cobalast menautkan repo untuk kami lacak, meskipun saat ini kosong. Kita bisa membangun dari sana.
https://github.com/cobalast/threejs-browserify-conversion-utility
Kodenya berantakan, akan segera dibersihkan.
Ini dia! :roket:
Saya sekarang memiliki utilitas dalam keadaan di mana ia menghasilkan browserify src dan akan membangunnya tanpa masalah. Saya akan memperbarui repo dengan instruksi tentang cara melakukannya sendiri. Pada titik ini, contoh tidak berfungsi. Ada beberapa masalah yang perlu ditangani untuk memperbaikinya. Saya akan menambahkannya ke repo jika ada yang ingin menyingsingkan lengan baju mereka dan membantu.
@cobalast ya tolong ajukan masalah sebagai TODO, dan saya atau orang lain akan melompat semampu kami.
Masalah serius telah muncul. Lihat #6241
Inilah analisis saya tentang apa yang perlu terjadi agar ini berfungsi: https://github.com/coballast/threejs-browserify-conversion-utility/issues/9#issuecomment -83147463
browserify setidaknya mengangkut berlebihan (menyangkal) karena desainnya. Ini membuatnya menggunakan biaya yang melambung (paket data siapa?) Dan lambat.
Solusi sederhana untuk ini adalah dengan memisahkan dokumen dari kode perpustakaan yang akan memerlukan dua file klien dan bukan satu. Ini adalah praktik umum untuk js sisi klien.
Jika pada awalnya browserify rusak dan itu sendiri perlu diperbaiki, saya hampir tidak dapat melihat mengapa itu harus dipertimbangkan untuk meningkatkan apa pun apalagi sesuatu seperti threejs.
@spaesani Karena data untuk threejs harus tetap diunduh. Jika kita membagi threejs menjadi modul yang lebih kecil dan membiarkan sistem build otomatis memilih apa yang dibutuhkan untuk satu aplikasi, sebenarnya sebagian besar aplikasi threejs di luar sana akan lebih ringan.
Jika karena alasan tertentu Anda masih ingin memisahkan "dokumen dari kode perpustakaan", Anda masih dapat melakukan ini dan menggunakan versi pra-bangun seperti yang kami lakukan sekarang. Anda bahkan dapat membagi aplikasi yang dibuat dengan browserify menjadi modul terpisah dengan menggunakan flag --standalone dan --exclude .
Browserify hanyalah cara untuk menggunakan API definisi modul (CommonJS) yang terbukti dalam pertempuran di browser. Ini akan sangat menyederhanakan pengembangan plugin threejs dan meningkatkan kejelasan kode dan oleh karena itu produktivitas, ini akan memungkinkan kita untuk berintegrasi ke dalam ekosistem yang lebih besar (npm) di mana kode secara inheren dipelihara oleh lebih banyak orang sambil tetap mempertahankan integritas melalui sistem versi (pikirkan tentang keluarga stackgl ), dan itu bahkan tidak akan memaksa orang masuk ke CommonJS jika mereka tidak menginginkannya.
Tentu saja ada kerugiannya, tetapi itu bukan yang Anda sebutkan.
three.js dan three.min.js dapat di-cache untuk menghemat transportasi (data) baik oleh proxy, solusi seluler umum, atau browser caching.
Saat Anda memilih dan menggabungkan kode threejs dengan kode khusus dokumen, caching tidak layak.
Jika browserify memungkinkan seseorang untuk
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 Itu (browserify) meningkatkan banyak hal untuk manusia. Kebahagiaan dan kesejahteraan psikologis saya sendiri lebih penting daripada betapa mudahnya sebuah mesin memuat dan menjalankan sesuatu.
Banyak masalah beban jaringan seluler akan sedikit diperbaiki dengan hal-hal seperti http/2. Masalah seperti itu paling baik diselesaikan dengan memodifikasi lapisan yang lebih rendah pada tumpukan abstraksi. Masalah kinerja seharusnya tidak menghalangi kami untuk mengikuti praktik terbaik rekayasa perangkat lunak seperti modularitas/pemisahan masalah, dll.
Saya menemukan Masalah ini karena tim saya baru-baru ini mulai menggunakan jspm. Kami dapat mengimpor threejs (saya yakin ini karena file utama telah di-browser). Saya mencari untuk melihat apakah ada yang membuat threejs menjadi modul es6, terutama karena fitur build jspm (menggabungkan semua dependensi ke dalam satu file, tetapi hanya mengambil dependensi yang digunakan).
Meskipun bagus bahwa mrdoob menjaga ukuran threejs di bawah 100kb, saya menemukan bahwa sebagian besar proyek saya tidak menggunakan banyak basis kode (saya merasa seperti itu, tetapi saya belum mencoba mencari tahu). CubeCamera, OrthographicCamera, CanvasRenderer, berbagai Lampu, Pemuat, Kurva, Geometri, Pembantu, dll. Selain itu, saya menemukan bahwa sebagian besar proyek saya menyertakan beberapa contoh skrip.
Harapan saya adalah dimungkinkan untuk memiliki satu lokasi dari semua modul ini (yang biasanya dibundel dengan threejs serta yang ada dalam contoh), dan cukup mengimpor yang saya butuhkan, lalu ketika saya menggabungkan proyek, hasilnya dalam file yang jauh lebih kecil dari threejs asli, meskipun berisi banyak bagian yang awalnya tidak disertakan.
Saya juga ingin menambahkan bahwa jika threejs dibangun menggunakan modul browserify, itu akan menambah sedikit overhead ukuran file (tetapi tidak dapat dibandingkan dengan 403kb saat ini di r70), tetapi juga akan menghapus penggunaan variabel THREE global dari kode, dengan demikian memungkinkan variabel seperti THREE.Geometry untuk diperkecil dengan penutupan.
Saya melakukan tes cepat melakukan find-replace untuk menyingkirkan objek TIGA (sehingga semua anaknya mencemari namespace) dan membungkus seluruh file dalam IIFE, lalu menjalankan semuanya melalui penutupan google. File yang dihasilkan (non-gzip) adalah 238kb, turun dari 777kb.
Meskipun hasilnya akan bervariasi, saya pikir itu pasti layak untuk memastikan ini bisa terjadi.
terima kasih telah memberi tahu - banyak poin bagus di sana, dan juga akrab bagi kami. kami juga tidak pernah menggunakan banyak penyaji dalam satu proyek tetapi melakukan hal-hal lib dari contoh.
tidak menyadari bahwa tentang mengecilkan - itu perbedaan yang cukup besar.
dan modul es6 pasti tampak menjanjikan - juga senang mendengar bahwa ada jalur di sana dari pola modul AMD/CommonJS/seperti & penggunaan lib juga.
@colin Tidak yakin saya mengikuti Anda tentang bagaimana browserify
membantu kebahagiaan psikologis Anda.
Apakah ada di dokumentasi?
browserify adalah sapi perah pembawa...
Selasa, 31 Maret 2015, 22:11 -04:00 dari Colin Ballast notifications@github.com :
@spaesani Itu (browserify) meningkatkan banyak hal untuk manusia. Kebahagiaan dan kesejahteraan psikologis saya sendiri lebih penting daripada betapa mudahnya sebuah mesin memuat dan menjalankan sesuatu.
Banyak masalah beban jaringan seluler akan sedikit diperbaiki dengan hal-hal seperti http/2. Masalah seperti itu paling baik diselesaikan dengan memodifikasi lapisan yang lebih rendah pada tumpukan abstraksi. Masalah kinerja seharusnya tidak menghalangi kami untuk mengikuti praktik terbaik rekayasa perangkat lunak seperti modularitas/pemisahan masalah, dll.
—
Balas email ini secara langsung atau lihat di GitHub .
Sekarang, jika browserify akan secara otomatis menentukan dependensi tanpa pernyataan yang diperlukan ... hei tunggu ...
@spaesani Saya sebenarnya lebih suka dependensi eksplisit - membantu Anda memahami bagaimana semua kode cocok bersama.
browserify adalah sapi perah pembawa...
@spaesani browserify overhead sangat kecil. Ini benar-benar akan membantu orang membuat bangunan yang lebih minimal.
Pembaruan status:
Saya memiliki cabang dengan beberapa kode yang di-browse:
https://github.com/cobalast/three.js/tree/browserify
Harap diingat ini sangat banyak pekerjaan yang sedang berjalan. Kode ini dibuat secara otomatis dan akan terlihat sangat buruk untuk sementara sebagai hasilnya. Saya masih mencoba untuk memperbaiki beberapa masalah build. Lihat coballast/threejs-browserify-conversion-utility#10 jika Anda merasa dapat memperbaikinya. Itu dibangun untuk sementara waktu, tetapi tidak sekarang.
@kumavis dan saya telah berupaya mengatasi beberapa masalah runtime (dan juga meningkatkan arsitektur perangkat lunak). Saya percaya saya menyebutkannya di atas di suatu tempat.
Maaf untuk jawaban yang panjang. TLDR: jspm/es6 berjalan, tetapi memiliki beberapa keanehan: 1) Mengekspor objek sebelum mendefinisikannya; 2) Mengekspor objek yang berisi kelas tunggal, bukan hanya mengekspor kelas tunggal; 3) IIFE menggunakan dependensi melingkar; 4) Struktur berkas.
Saya bermain dengan cabang browser Anda di jspm ( @spinchristopher di atas adalah saya) dan memiliki beberapa catatan, meskipun pertama: Bukankah lebih baik untuk membuka masalah pada garpu itu, jadi utas ini tidak penuh dengan mereka dan tidak campur aduk?
Meskipun berjalan, itu tidak benar-benar menampilkan hasil yang benar. (menggunakan demo sederhana saat memulai). Membuat kanvas dan mengisinya dengan warna hitam (kecuali saya mengatur warna bening menjadi transparan), tetapi sebenarnya tidak merender kubus. Namun saya tidak mengharapkannya untuk bekerja pada saat ini, karena ini masih sangat awal dalam proses.
Saya mengalami 3 masalah utama:
Satu. Ini adalah yang paling menjengkelkan, dan sejujurnya saya tidak yakin bagaimana Anda mendapatkan sesuatu untuk dikompilasi dengan kesalahan khusus ini, karena seharusnya tidak berfungsi sama sekali. Banyak file dimulai seperti ini (ini tidak masalah karena definisi fungsi diangkat ke waktu, dan pada dasarnya dijalankan sebelum baris module.exports, meskipun muncul lebih dulu):
module.exports.Foo = Foo;
function Foo() {}
Masalahnya muncul di banyak file yang seperti ini (yang pertama saya lihat adalah math/Math.js). Inisialisasi objek diangkat (itulah sebabnya tidak ada kesalahan yang tidak ditentukan) tetapi definisi tetap di tempatnya (sehingga ekspor tidak ditentukan).
module.exports.Foo = Foo;
var Foo = {};
Satu-satunya perbaikan yang saya temukan di sini adalah memindahkan baris ekspor ke akhir, atau menulis ulang seperti ini (lebih disukai):
var Foo = module.exports.Foo = {};
Dua. Data yang diekspor. Ketika berhadapan dengan file termodulasi, standarnya adalah bahwa setiap file mengekspor satu objek. Sementara sebagian besar file dengan cara ini (meskipun beberapa mengekspor lebih banyak), mereka tidak mengekspor konstruktor tunggal, mereka mengekspor objek yang berisi konstruktor itu (yaitu: module.exports.Foo = Foo;
daripada module.exports = Foo;
. Yang terakhir adalah cara semua contoh browserify bekerja). Jadi, saat menggunakan persyaratan, Anda harus melangkah lebih dalam ( var Vector3 = require('../math/Vector3').Vector3;
). Selain tidak perlu, tidak ada cara untuk melakukan ini saat mengimpor ke es6. ( import Vector3 from '../math/Vector3'; var vector = new Vector3.Vector3();
). Meskipun ada cara untuk mengambil ekspor tertentu di es6, itu berlaku saat menggunakan modul yang di-browse, dan masih akan memiliki redundansi yang sama ( import { Vector3 } from '../math/Vector3';
). Ada beberapa file yang hanya mengumpulkan objek lain (yang jelas adalah Three.js), tetapi ini harus dijaga seminimal mungkin, dan seharusnya hanya digunakan untuk proses pembuatan, bukan sebagai cara untuk mengambil banyak hal dalam produksi .
Tiga. Ini ada hubungannya dengan dependensi melingkar. System.js (pemuat modul yang digunakan oleh jspm) dapat menangani dependensi melingkar dengan baik, tetapi ada satu masalah. Di banyak tempat, kode membaca sesuatu seperti berikut. Masalahnya adalah, meskipun Vector3 telah diteruskan sebagai dependensi, pada saat ini belum dimuat sepenuhnya (karena Vector3 juga menyertakan file ini, masing-masing tidak dapat diselesaikan sampai yang lain diselesaikan) dan tidak dapat dibuat. Saya menambahkan perbaikan yang sangat buruk (ditunjukkan di bawah), meskipun saya tidak yakin bagaimana ini akan diperbaiki dengan lebih baik. Tampaknya ini adalah masalah arsitektur yang mungkin tidak memiliki solusi sederhana. Itu terjadi berkali-kali. Tampaknya merupakan pengoptimalan untuk mencegah pembuatan Vector3 baru setiap kali fungsi dipanggil. Jika memang ada hit kinerja yang signifikan yang tidak dapat diperbaiki dengan mengoptimalkan Vector3, maka mungkin menambahkan fungsi ke Vector3 untuk mengembalikan vector3 yang tidak digunakan yang dirilis nanti?
Foo.prototype.bar = function() {
var vector = new Vector3();
return function() {
// some data which reuses vector repeatedly.
};
}();
Perbaikannya:
Foo.prototype.bar = function() {
var vector;
return function() {
if(!vector) vector = new Vector3();
// some data which reuses vector repeatedly.
};
}();
Terakhir, saya ingin menambahkan sedikit tentang organisasi file. Ini jelas sesuatu yang harus ditangani setelah set saat ini dibangun dengan benar, tetapi saya ingin membahasnya sekarang. Sementara struktur file saat ini berfungsi, bagian-bagiannya agak aneh atau bahkan canggung. Pengelompokan utama (kamera, bahan, geometri, dll) tampaknya memilikinya dengan baik, meskipun saya akan membuat beberapa perubahan, seperti yang terlihat di bawah. Saya juga akan memindahkan global di ThreeGlobals masing-masing ke hal yang menjadi globalnya. IE: FrontSide, BackSide, DoubleSide semuanya termasuk dalam Material (bersama dengan NoShading, FlatShading, dan SmoothShading. Sebenarnya, tampaknya sebagian besar dari mereka melakukannya...).
Kebingungan utama saya datang dengan inti dan ekstra. core/Geometry.js harus berada di folder geometri, sama seperti Material ada di folder material. Tapi tidak ada folder geometri, itu ada di ekstra. Kebetulan, ekstra juga memiliki inti dan geometri, tetapi geometri dasar tidak ada di folder ini. Ada banyak kumpulan pembantu, tetapi bukankah setiap pembantu harus bersama dengan benda yang ditolongnya? Proses build dapat dengan mudah dikonfigurasi untuk hanya mengambil file yang Anda inginkan, jadi tidak ada alasan untuk meletakkan file yang tidak penting di tempat lain.
Saat ini saya memiliki baris dalam kode saya yang membaca import BoxGeometry from 'threejs/extras/geometries/BoxGeometry';
dan var geometry = new BoxGeometry.BoxGeometry( 1, 1, 1 );
Karena terbiasa menggunakan `new THREE.BoxGeometry()``` butuh waktu cukup lama untuk menemukan file. Saat menggunakannya secara modular, lokasi file sama pentingnya dengan sesuatu seperti tanda tangan fungsi.
Perubahan umum yang akan saya buat pada struktur file. Ini berlaku di banyak tempat, tetapi saya hanya menunjukkan sebuah contoh. (Sebagai catatan, saya selalu lebih suka model penamaan file setelah kelas tunggal yang diekspor, dan menempatkan file di folder dengan nama yang sama. Setiap keturunan langsung umumnya akan masuk ke folder itu, tapi sekali lagi, di folder dengan nama yang sama seperti mereka sendiri. Namun jika seseorang tidak menyukai pola ini, struktur yang sama di bawah ini berlaku, hanya dengan menghilangkan level ekstra itu. Juga, setiap pemuat file dapat dengan mudah dimodifikasi [hook biasanya disediakan secara langsung, sebenarnya] untuk mengotomatiskan layering dan menyederhanakan pernyataan yang diperlukan].) (Saya juga lebih suka semua file huruf kecil, dengan garis bawah bila perlu.)
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
Saya juga kemungkinan akan mengganti nama math menjadi utils (setiap kategori mungkin juga memiliki utils, seperti geometri di atas) sehingga dapat menampung lebih dari sekadar matematika (banyak hal dari inti).
@HMUDesign @spinchristopher terima kasih atas analisisnya yang luar biasa! Terbaik untuk menempatkan masalah semacam ini ke dalam repo coballast/threejs-browserify-conversion-utility di masa depan.
ok izinkan saya membaca komentar Anda dengan benar sekarang.
Saya entah bagaimana melewatkan tautan ke repo di atas. Saya akan dengan senang hati memindahkan masalah saya
ke repo itu besok, membelah kemudian seperlunya (saya perhatikan setidaknya
sebagian sudah ada)
Pada 9 April 2015 12:09, "kumavis" notifications@github.com menulis:
@HMUDesign https://github.com/HMUDesign @spinchristopher
https://github.com/spinchristopher terima kasih atas analisisnya yang luar biasa! Terbaik
untuk menempatkan masalah semacam ini ke dalam
coballast/threejs-browserify-conversion-utility repo di masa mendatang.ok izinkan saya membaca komentar Anda dengan benar sekarang.
—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -91132413.
Ya, dan saya melakukannya untuk perpustakaan tipe util milik saya sendiri (* File util adalah
hanya saja saya tidak memiliki ekspor default, meskipun terkadang saya akan menambahkan
ahli selain default), namun sintaks ini hanya berfungsi ketika Anda
ekspor beberapa variabel bernama. Pemuat untuk modul js umum memperlakukan
modules.exports sebagai ekspor default, yang tidak dapat dirusak di
impor =(
Pada 9 April 2015 12:12, "kumavis" notifications@github.com menulis:
di es6 Anda dapat mengimpor properti dari objek ekspor melalui
merusak.impor { Vector3 } dari '../math/Vector3';
yang mengatakan, saya setuju bahwa satu ekspor per modul lebih disukai.
—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -91132982.
@HMUDesign sekali lagi terima kasih atas energi dan analisis Anda -- di sini kami sedang menyusun daftar tugas, silakan masuk dan sebagainya. https://github.com/cobalast/threejs-browserify-conversion-utility/issues/17
+1 untuk browserify.
Juga +1 untuk memindahkan shader ke file terpisah menggunakan glslify.
Juga +1 untuk mengadopsi beberapa fitur ES6 - seperti kelas dan modul. Tumpukan build baru akan memungkinkan kita untuk mengkompilasi kembali ke ES5 jika perlu. Lihat contoh:
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 Saat kita melakukannya, kita dapat menggunakan modul es6 dan menggunakan babeljs untuk mengkompilasi semuanya.
@cobalast Saya tertarik untuk membuat cabang dari cabang browserify
dan mewujudkan beberapa hal ini
@lmcd saya tidak akan repot. Saya akan mengembangkan perkakas otomatis untuk memindahkan barang es5 ke es6 secara otomatis. Masuk akal, karena ada sejumlah besar kode es5 di luar sana, dan kebutuhan tenaga kerja untuk memindahkannya dengan tangan sangat besar.
@cobalast Saya berpikir lebih banyak tentang menjalankan pass 5to6
: https://github.com/thomasloh/5to6
@lmcd oo
tapi tbh, sepertinya akan lebih mudah untuk menulis ulang three.js dari awal : P
@lmcd Saya sangat senang Anda menemukan itu. Itu adalah salah satu hal yang akan saya lakukan karena kebutuhan, tetapi terdengar jelas tidak menyenangkan.
@mrdoob apa pendapat Anda saat ini tentang masalah ini?
@anvaka Saat ini saya sedang fokus pada refactoring WebGLRenderer
. Saya tidak memiliki lebih banyak bandwidth mental
Saya baru-baru ini menemukan beberapa proyek yang menggunakan modul es6 dengan senang hati dengan babel polyfill yang sudah disebutkan di sini juga. Tidak dapat mengingat atau menemukan sekarang apa itu, bagaimanapun juga tampak bagus bagi saya.
Juga es6 tampaknya sudah selesai sekarang di depan standar: "Akhirnya, ECMA-262 Edition 6 secara resmi disetujui dan diterbitkan sebagai standar pada 17 Juni 2015" kata https://developer.mozilla.org/en-US/docs /Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
Sekedar catatan bahwa mengenai perkakas dan stabilitas spesifikasi modul, situasinya tampak bagus di bagian depan itu.
Saya baru-baru ini menemukan beberapa proyek yang menggunakan modul es6 dengan senang hati dengan babel polyfill yang sudah disebutkan di sini juga. Tidak dapat mengingat atau menemukan sekarang apa itu, bagaimanapun juga tampak bagus bagi saya.
Ini juga merupakan 47kb js ekstra dan membaca serta mentranspilasikan javascript Anda yang disertakan ke es5 di browser, jadi tidak bagus untuk waktu mulai.
Tidak ada yang menghentikan siapa pun yang menggunakan three.js untuk menggunakan es6 dalam kode mereka sendiri; namun menggunakannya di perpustakaan akan memperkenalkan kompatibilitas browser dan masalah kinerja di seluruh papan.
Ah - berdiri dikoreksi di sini, terima kasih atas infonya. Saya kira browserify dan semacamnya yang berfungsi dalam proses pembuatan lebih baik sekarang.
Ah - berdiri dikoreksi di sini, terima kasih atas infonya. Saya kira browserify dan semacamnya yang berfungsi dalam proses pembuatan lebih baik sekarang.
Salah satu masalah utama dengan es6 adalah telah melanggar perubahan sintaks dengan es5; misalnya panah gemuk => tidak valid es5 dan akan menyebabkan parser javascript gagal dan jaminan mencoba mengkompilasi kode. Mudah-mudahan seseorang akan menemukan cara untuk mengatasi ini, tetapi mereka belum melakukannya.
Saya sebenarnya hanya memikirkan sistem modul, pernyataan impor, dll.
Ini juga merupakan 47kb js ekstra dan membaca serta mentranspilasikan javascript Anda yang disertakan ke es5 di browser, jadi tidak bagus untuk waktu mulai.
misalnya panah gemuk => tidak valid es5 dan akan menyebabkan parser javascript gagal dan jaminan mencoba mengkompilasi kode
Kode es6 dapat ditranspilasikan ke es5 selama _build_ tanpa penalti runtime. Ini hanya masalah menambahkan langkah babel ke pipeline build.
Misalnya, fungsi panah dapat ditranspilasikan ke es5 selama build tanpa polyfill atau penalti runtime. Babel akan mengubah cuplikan es6 ini
function MyObj() {
this.step = 1;
this.increment = function ( arr ) {
return arr.map( v => v + this.step );
}
}
ke dalam versi portabel ini:
function MyObj() {
this.step = 1;
this.increment = function (arr) {
var _this = this;
return arr.map(function (v) {
return v + _this.step;
});
};
}
Fitur lain, seperti kelas es6, akan menghasilkan polyfill kecil (Anda dapat melihat di babel repl http://babeljs.io/repl/).
@mrdoob mengerti. Apakah Anda mendukung gagasan untuk memecah three.js menjadi modul yang lebih kecil yang dihosting di npm?
Repositori three.js utama akan tetap tidak berubah: konsumen tidak perlu membangun apa pun. Pengguna yang lebih berpengalaman akan dapat memilih bit three.js yang diperlukan.
Boleh juga. Padahal saya tidak tahu detailnya.
Kode es6 dapat ditranspilasikan ke es5 selama build tanpa penalti runtime. Ini hanya masalah menambahkan langkah babel ke pipeline build.
Misalnya, fungsi panah dapat ditranspilasikan ke es5 selama build tanpa polyfill atau penalti runtime. Babel akan mengubah cuplikan es6 ini
Transpiling ES6 masih disertai dengan penalti runtime yang signifikan: http://www.incaseofstairs.com/2015/06/es6-feature-performance/ terutama untuk perpustakaan kinerja tinggi.
modul/npm/browserfy dll mungkin merupakan ide yang bagus
+1 pada modularisasi yang tepat menggunakan modul ES6
+1 pada modularisasi yang tepat menggunakan sistem modul waras ( commonjs, amd, es6 )
Saya pikir commonjs dan amd adalah pilihan yang lebih disukai karena mereka tidak memerlukan transpiling
Namun, mereka memang memerlukan langkah pembuatan, yang setara dengan
langkah transpile.
Menggunakan ES6, selain menjadi versi bahasa berikutnya, akan memungkinkan
penggunaan fitur berikutnya sesuai keinginan, tetapi tidak merusak kode asli yang ada.
Apakah benar-benar bijaksana untuk mereaktor basis kode menjadi sistem yang sudah ada
bukan yang terbaru?
Pada 20 Juli 2015 12:05, "kumavis" notifications@github.com menulis:
+1 pada modularisasi yang tepat menggunakan sistem modul waras ( commonjs, amd,
es6 )
Saya pikir commonjs dan amd adalah pilihan yang lebih disukai b/c mereka tidak
memerlukan transpiling—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -122990605.
Namun, mereka memang memerlukan langkah pembuatan, yang setara dengan
langkah transpile.
bangunan dan transpiling tidak setara dalam hal kompleksitas yang mereka perkenalkan.
Apakah benar-benar bijaksana untuk mereaktor basis kode menjadi sistem yang sudah ada
bukan yang terbaru?
commonjs sederhana dan berfungsi dengan baik. saya tidak menjual dengan anggapan bahwa 'terbaru' === 'lebih baik'.
Menggunakan ES6 [...] akan memungkinkan penggunaan fitur berikutnya sesuai keinginan
jadi ini layak dipertimbangkan. apakah kita menginginkan fitur es6? jika kita mulai menerjemahkan es6, orang-orang akan memulai PR'ing es6. seperti yang disarankan @benaadams, ada dampak kinerja non-intuitif dalam penggunaan fitur es6.
lebih jauh lagi, kita tidak perlu mencampuradukkan masalah 'sistem modul' dan 'fitur es6'. anda dapat mengubah es6 dan menggunakan commonjs. dan Anda dapat memperkenalkannya secara terpisah.
+1 untuk browserify / commonjs - mudah untuk dikompilasi dengan browserify sedemikian rupa sehingga orang masih dapat menggunakan perpustakaan dengan cara tradisional jika mereka mau - inilah gunanya UMD, izinkan AMD membutuhkan (seperti require.js), CommonJS membutuhkan (seperti node + browserify) dan jendela global (untuk tag skrip) tergantung pada lingkungan tempat kami menjalankan.
PIXI.js baru saja pindah ke arsitektur modular menggunakan browserify dan library disiapkan dengan cara yang sangat mirip - semuanya dilampirkan ke objek PIXI global. Pengaturan mereka sangat mirip dengan yang dijelaskan @kumavis di posting kedua.
Baik browserify maupun commonjs tidak menjawab kebutuhan spesifik mesin 3D, yang tidak berarti mereka tidak dapat digunakan, tetapi mereka harus dilihat sebagai satu bagian dari teka-teki yang lebih besar:
Komponen perlu mengekspor informasi meta tentang properti instansnya, sehingga bisa ada loader untuk objek arbitrer dan koneksi data memori bersama. Dengan arsitektur seperti itu, hanya masalah akal sehat untuk juga memuat kode komponen di luar inti pada penggunaan pertama. Telah melakukan brainstorming tentang topik ini di #6464 dan #6557.
+1
+1
Sebagai solusi hybrid juga memungkinkan untuk menambahkan persyaratan sebagai komentar. Saya tahu browserfy sudah ada di banyak ekosistem, tetapi saya hanya ingin meninggalkan ini di sini sebagai varian implementasi yang cepat :) karena Anda tidak perlu mengubah apa pun. Anda hanya perlu menambahkan komentar di atas setiap file.
Sebagai pengembang, Anda dapat dengan mudah membuat file min.js Anda sendiri dengan informasi @requires
dan plugin gulp.
Hai semua, saya baru-baru ini memiliki kebutuhan yang sama untuk memuat sumber daya arbitrer dengan dependensi mereka sendiri dengan cara yang bersih dan terstruktur dan saya menemukan solusi untuk menulis plugin require.js untuk setiap jenis sumber daya. Dengan cara ini saya membiarkan resolusi ketergantungan require.js untuk mengurus pengunduhan dan caching sumber daya dengan benar.... Pada saat yang sama pendekatan ini menciptakan 'bundel' sumber daya yang dapat digunakan kembali yang dapat saya gunakan di berbagai proyek saya.
Jika Anda tertarik, Anda dapat menemukan proyeknya di sini: https://github.com/wavesoft/three-bundles
(Contoh menggunakan perpustakaan ini akan segera tersedia)
Di masa mendatang, saya berencana untuk menyertakan fase pengoptimalan dalam plug-in ini untuk memungkinkan pengoptimal require.js mengompilasi sumber daya ke dalam format yang lebih ringkas.
Melihat percakapan ini https://twitter.com/defunctzombie/status/682279526454329344 sepertinya modul es6 tidak akan diimplementasikan dalam waktu dekat. Sesuatu yang perlu diingat.
Saya melakukan beberapa prototipe dengan modul commonjs dan browserify.
Bundel browser terakhir saya menyertakan setiap file dari folder src
dan menghasilkan ukuran file 962K
(dibandingkan dengan versi asli yang tidak dijelajahi 885K
).
Contoh build yang ditargetkan dari
580K
(~44% lebih kecil)431K
(~8% lebih kecil)Berikut adalah rincian ukuran bundel: http://output.jsbin.com/yogoxawozu. Renderer mengambil 40% dari bundel, dan 10% dari yang diambil oleh perpustakaan shader.
Saya pikir kita dapat mengurangi ukuran bundel dengan:
instance of
- mereka memerlukan modul referensi secara eksplisit bahkan ketika tidak digunakan. Saya melihat beberapa kelas sudah memiliki type
- kita bisa menggunakan ini di seluruh perpustakaan.glslify
dibawa beberapa kali, dan itu pasti bisa membantu. Idealnya setiap komponen yang membutuhkan shader perlu secara eksplisit bergantung pada shader.Anda dapat memverifikasi hasil dan memeriksa kode:
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
sepertinya modul es6 tidak akan diimplementasikan dalam waktu dekat. Sesuatu yang perlu diingat.
Itu benar, tetapi penting juga untuk menyadari bahwa dukungan modul CommonJS akan _never_ diimplementasikan di browser, jadi pilihannya adalah antara
Pustaka seperti D3 mengadopsi modul ES6 karena mereka sudah dapat melakukan semua yang dapat dilakukan oleh modul CommonJS (kecuali dijalankan secara native di Node.js, yang sebenarnya bukan masalah untuk pustaka seperti Three.js), dan menghasilkan build yang lebih kecil.
Saya telah melakukan beberapa percobaan di https://github.com/rollup/three-jsnext , dan sementara itu belum siap produksi (saya perlu menghabiskan lebih banyak waktu untuk mem-porting contoh dll!) UMD build yang dihasilkannya sebenarnya _smaller_ daripada bangunan saat ini.
Saya setuju dengan catatan tentang modul es6 vs sistem lain. Apakah atau
bukan standar es, mereka adalah standar komunitas. Dan meskipun mereka
tidak dapat menjalankan "asli" di simpul, itu dapat terlihat asli dengan kait Babel.
Saya akan segera menindaklanjuti repo Anda.
Juga, fakta bahwa itu lebih kecil adalah sesuatu yang saya bicarakan sebelumnya
percakapan ini. "TIGA.Geometri" menjadi "geometri" yang dapat
diperkecil menjadi "a" misalnya.
Juga, solusi untuk contoh cek adalah menghapus semuanya
bersama. Satu modul tidak boleh mengemis berbeda tergantung pada apa
itu diberikan, melainkan tunduk pada hal yang disediakan untuk dilakukan sesuai kebutuhan
melakukan. Maka tidak ada pemeriksaan instance atau tipe.
Pada 1 Januari 2016 20:23, "Rich Harris" notification@github.com menulis:
sepertinya modul es6 tidak akan diimplementasikan dalam waktu dekat
masa depan. Sesuatu yang perlu diingat.Itu benar, tetapi penting juga untuk menyadari bahwa modul CommonJS
dukungan akan _tidak pernah_ diimplementasikan di browser, jadi pilihannya adalah antara
- melanjutkan dengan arsitektur non-modular dan pembangunan ad hoc
sistem, yang sejauh ini telah melayani Three.js dengan baik tetapi bertindak sebagai rem pertumbuhan
dalam jangka panjang- menggunakan modul CommonJS, yang melibatkan beberapa tipu daya seputar siklus
dependensi dan menghasilkan build yang lebih besar, atau- menggunakan modul ES6, yang sangat cocok untuk basis kode seperti Three.js
yang memiliki ketergantungan siklis, dan yang menghasilkan terkecil dan terbesar
bangunan yang dapat diminimalkan mungkin. Akhirnya, browser akan mendukungnya secara asli,
dan perubahan yang diperlukan untuk mengakomodasi kebiasaan yang tidak terduga di loader
spec kemungkinan besar akan sepele dibandingkan dengan upaya yang terlibat dalam
memutakhirkan dari basis kode CommonJS.Perpustakaan seperti D3 mengadopsi modul ES6 karena mereka sudah dapat melakukannya
semua yang dapat dilakukan modul CommonJS (kecuali dijalankan secara native di Node.js, yang
tidak benar-benar menjadi perhatian untuk perpustakaan seperti Three.js), dan hasilnya lebih kecil
membangun.Saya telah melakukan beberapa percobaan di
https://github.com/rollup/three-jsnext , dan sementara itu bukan produksi
siap (saya perlu menghabiskan lebih banyak waktu untuk mem-porting contoh dll!) UMD build
yang dihasilkan sebenarnya _lebih kecil_ daripada build saat ini.—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -168363092.
Apakah CommonJS masih akan menghasilkan build yang lebih besar dengan basis kode yang tidak memiliki ketergantungan siklus?
@cecilemuller Ya – lihat https://github.com/nolanlawson/rollup-comparison. Dengan modul CommonJS Anda membayar biaya per modul (setiap modul harus dibungkus dalam suatu fungsi, dan perlu mendeklarasikan ulang impor yang dibagikan di seluruh bundel, sehingga Anda dikenakan sanksi untuk basis kode yang lebih modular), biaya per bundel (perlu mensimulasikan lingkungan Node.js), dan biaya lain seperti nama properti objek yang tidak dapat diminifikasi yang akan menjadi nama variabel yang dapat diperkecil dalam modul ES6. Modul ES6 memungkinkan Anda untuk membundel dengan benar-benar nol overhead.
Meskipun akan ada beberapa overhead dalam transpiling kemudian ke es5. Saat sekarang,
Saya menggunakan webpack dengan babel yang menambahkan sangat sedikit. Ada biaya per modul
karena juga dibungkus dengan fungsi s. Dependensi dideklarasikan di final
kode dengan memanggil fungsi seperti yang dibutuhkan dengan indeks bilangan bulat, sehingga mendapat
diperkecil menjadi sesuatu seperti "var a=f(5)" dari yang awalnya 'import
Geometri dari "./geometry";'
Menggunakan generator juga menambahkan sedikit lebih banyak, tapi saya tidak membayangkan strukturnya
kode akan berubah sebanyak itu dalam waktu dekat.
Pada 2 Jan 2016 5:53 AM, "Rich Harris" notifications@github.com menulis:
@cecilemuller https://github.com/cecilemuller Ya – lihat
https://github.com/nolanlawson/rollup-comparison. Dengan modul CommonJS
Anda membayar biaya per modul (setiap modul harus dibungkus dengan fungsi,
dan perlu mendeklarasikan ulang impor yang dibagikan di seluruh bundel, jadi
Anda dikenakan sanksi untuk basis kode yang lebih modular), biaya per bundel (perlu
untuk mensimulasikan lingkungan Node.js), dan biaya lain seperti tidak dapat diperkecil
nama properti objek yang akan menjadi nama variabel yang dapat diperkecil di ES6
modul. Modul ES6 memungkinkan Anda untuk membundel dengan benar-benar nol overhead.—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -168394376.
Meskipun akan ada beberapa overhead dalam transpiling kemudian ke es5
Jika Anda hanya menggunakan sintaks import
dan export
untuk menjelaskan hubungan antar modul, tidak perlu mentranspile kode itu sendiri dengan Babel atau yang serupa. Hanya ketika Anda mulai menambahkan fitur ES6 lainnya (seperti kelas dan pelingkupan blok dan fungsi panah dll) transpiling menjadi perlu, jadi tidak ada biaya tambahan untuk menggunakan import
dan export
. D3 dan PouchDB adalah dua contoh pustaka yang menggunakan import
dan export
tetapi sebaliknya ES5 tanpa Babel, dan three-jsnext dilakukan dengan cara yang sama.
Oke, kita semua punya ide yang sama. Akan sangat bagus untuk memiliki cerita seperti lodash.
Saya mengusulkan untuk membuat paket _three-foo_ untuk setiap komponen _foo_ (misalnya tiga-vektor2) yang dapat dimodulasi, dengan hampir tidak ada perubahan dalam kode, sehingga dapat diimpor dalam repo ini tanpa dampak.
Orang yang menerbitkan di npm harus bermain dengan baik dan berkolaborasi dengan @mrdoob karena dia adalah pencipta perangkat lunak yang hebat ini, jadi jika dia ingin memusatkan lagi semua paket seperti yang dilakukan _babel_ author (maksud saya semua paket inti di folder yang sama), penerbit harus memberinya kendali pada namespace npm yang diambil.
Saya akan mencoba melakukan itu, untuk paket yang saya butuhkan. Mari lihat apa yang terjadi.
Hanya ada satu komunitas besar :)
Saya tidak melihat ada orang yang menyarankan untuk memisahkan perpustakaan sepenuhnya seperti
malas. Lodash adalah kumpulan utilitas dengan nama umum; kamu taksi
ambil satu bagian dan gunakan. Threejs tidak; itu komprehensif
perpustakaan, yang sebagian besar tidak berguna tanpa sisanya. Ada beberapa potong
yang dapat dipisahkan, seperti jenis bahan tertentu yang spesifik kami
generator geometri, tetapi itu pasti akan sangat dekat
terikat ke inti, kemungkinan membutuhkan kecocokan versi yang tepat. Mengingat mereka
ukuran, itu akan membuat sakit kepala pemeliharaan tanpa keuntungan yang terukur.
Haruskah mr doob menyetujui pemisahan sifat itu, bagaimanapun, saya tidak berpikir itu
cocok untuk siapa saja kecuali pengelola resmi untuk mengklaim threejs-*
paket.
Terlepas dari hal di atas, saya pikir itu bijaksana untuk membuatnya bekerja di modular
lingkungan sebelum hal lain. Ada beberapa proyek dengan ini
tujuan, tetapi semua tampaknya telah menggelepar.
Pada 6 Maret 2016 11:39, "Gianluca Casati" notifikasi@github.com menulis:
Oke, kita semua punya ide yang sama. Akan sangat bagus untuk memiliki cerita seperti
malas.Saya mengusulkan untuk membuat paket _three-foo_ untuk setiap komponen _foo_ (untuk
contoh tiga-vektor2) yang dapat dimodulasi, dengan hampir tidak ada perubahan dalam
kode, sehingga dapat diimpor dalam repo ini tanpa dampak.Orang yang mempublikasikan di npm harus bermain dengan baik dan berkolaborasi dengan @mrdoob
https://github.com/mrdoob karena dia adalah pencipta karya hebat ini
perangkat lunak, jadi jika dia ingin memusatkan lagi semua paket seperti di
_babel_, penerbit harus memberinya kontrol pada namespace npm yang diambil.Saya akan mencoba melakukan itu, untuk paket yang saya butuhkan. Mari lihat apa yang terjadi.
Hanya ada satu komunitas besar :)
—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -192970867.
@mattdesl : misalnya three-shader-fxaa Anda menggunakan THREE.Vector2 dan THREE.Texture, selain three-effectcomposer yang tidak saya periksa, itu akan menghasilkan build yang sangat ringan menggunakan pendekatan modularitas yang diusulkan di atas.
@HMUDesign : Saya mengerti keraguan Anda, tetapi bagi saya itu masih merupakan pendekatan yang baik. Saya ingin mencoba, tetapi saya akan mendengarkan saran Anda, menggunakan paket npm dari URL GitHub, tidak menerbitkannya di registri suci.
Saya mencobanya, mulai dari TrackballControls yang bergantung pada Vector2, Vector3, Quaternion, dan sebagainya.
Ada deps melingkar (misalnya Matrix4 tergantung pada Vector3 dan sebaliknya). Itu tidak dapat dilakukan jika lib (yaitu threejs) dimulai secara monolitik.
Sangat disayangkan bahwa pola modul dengan segala manfaatnya tidak dapat diterapkan dengan mudah pada proyek-proyek penting seperti ini.
Saya mencoba juga dengan proyek lain seperti svg.js, vvvvjs, bahkan x3dom, tetapi penulis tidak sepenuhnya yakin bahwa pilihan radikal ini tidak dapat dilakukan.
Maaf untuk spamnya, tapi saya ingin mencoba secara proaktif: omong-omong, saya mulai dengan repo tiga trackballcontrols .
@fibo ES6 Modul pola seharusnya tidak memiliki masalah dengan dependensi circ afaik. Bukankah pengikatan diatur sebelum modul dijalankan, seperti halnya mengangkat di JS biasa?
Saya yakin Anda telah melihat ini: https://github.com/kamicane/three-commonjsify Dia menyelesaikannya di commonJS.
@drcmda sangat menarik, saya akan mencobanya
+1 untuk pindah ke arsitektur modular.
+1
+1
@drcmda benar. Modul ES6 memiliki langkah inisialisasi dan langkah eksekusi yang memungkinkan referensi melingkar. Namun, segera setelah Anda memiliki dependensi melingkar langsung dari konteks eksekusi modul (di area global modul) maka yang pertama dimuat selama runtime akan mengalami nilai yang tidak ditentukan untuk dependensinya. Selama referensi digunakan dalam konteks yang berbeda di mana urutan eksekusi runtime penting, dependensi melingkar tidak menjadi masalah.
Saya sarankan untuk mempertimbangkan juga webpack daripada browserify.
@gionkunz kami memiliki referensi melingkar di langkah inisialisasi bc dari pola di mana ada penutupan untuk menghasilkan variabel awal
Beta Webpack 2 baru saja dirilis (https://twitter.com/TheLarkInn/status/747955723003322368/photo/1), jadi modul es6 juga dapat memanfaatkan guncangan pohon saat dibundel.
@mrdoob
Apakah ada pernyataan resmi baru-baru ini? Seperti banyak kita telah meninggalkan ES5 dan lem-concat sejak lama dan cukup buruk berapa banyak TIGA keluar dari barisan dalam sistem pembangunan modern. Kami menggunakan mungkin 10% dari apa yang dapat dilakukannya, namun itu adalah ketergantungan terbesar yang kami kirimkan.
Ini mungkin _the_ proyek paling favorit di Github bagi saya pribadi - saya sangat berharap prioritas akan dipertimbangkan kembali.
Hmm, saya ingin tahu lebih detail tentang dukungan browser. Browser mana yang melakukannya dan mana yang tidak. Untuk browser yang tidak, apa solusinya dan apa hukuman kinerjanya.
Sebenarnya, dukungan browser tidak menjadi masalah (bahkan mungkin kurang dari sekarang). Sistem build mengambil kode ES6 itu dan mengubahnya menjadi es5 (terkadang menghabiskan lebih sedikit ruang daripada yang dimiliki ES5 asli). Jenis-jenis tertentu dari hal-hal yang diubah menjadi besar (terutama: generator dan fungsi async), tetapi jika Anda menghindarinya, Anda tidak akan mendapatkan penalti itu.
Seperti yang disebutkan @drcmda , sistem build masih akan menghasilkan output monolitik (dan akan sangat mudah untuk menyesuaikan dengan tepat apa yang disertakan dalam output itu), tetapi modul individual juga dapat dimasukkan dalam proyek kita sendiri, sehingga hanya menggunakan bagian yang kita butuh. Untuk memanfaatkan sepenuhnya
bahwa, antar-ketergantungan perlu disesuaikan, tetapi itu bisa terjadi seiring waktu. Saya pikir fitur utama yang kami inginkan adalah membuatnya termodulasi dengan impor/ekspor. Dari sudut pandang Anda, itu akan memungkinkan penggunaan kelas di atas prototipe (mereka masih menggunakan prototipe di bawah tenda, jadi Anda masih bisa
mengacaukannya jika perlu).
Ada beberapa sistem build. Pilihan saya adalah webpack (yang menggunakan babel untuk transpiling). Dengan babel, Anda dapat menentukan pemuat khusus, sehingga sistem chunking yang Anda kembangkan untuk shader dapat direduksi menjadi kode glsl aktual dengan ekstensi #include (saya benar-benar melakukan shader saya dengan cara ini, dan dengan senang hati akan menyumbangkannya ke proyek). Ini mendapatkan manfaat yang sama dari sistem Anda (tidak ada duplikasi kode), tetapi sangat mudah digunakan.
Saya ingin menjadi bagian dari proyek modularisasi, tetapi saya tahu bahwa ini tidak akan berhasil dengan cara apa pun tanpa dukungan Anda (dan kemungkinan bantuan). Banyak dari kita tahu cara menggunakan perpustakaan, tetapi tidak satu pun dari kita yang tahu cara kerjanya secara internal sejauh yang Anda lakukan.
Jenis-jenis tertentu dari hal-hal yang diubah menjadi besar (terutama: generator dan fungsi async), tetapi jika Anda menghindarinya, Anda tidak akan mendapatkan penalti itu.
Seberapa besar?
Juga, Anda tidak berbicara tentang penalti kinerja. Apakah itu bukan masalah kalau begitu?
Sejauh yang saya lihat, ES6 Imports masih belum didukung oleh browser apa pun , jadi refactor modul ini terutama untuk membangun sistem, bukan?
Jangan lupa tentang manfaat yang Anda dapatkan dengan menggunakan alat seperti rollupjs, ini akan secara otomatis mengecualikan semua ekspor yang tidak digunakan pengguna. (Yang default dengan JSPM)
Paket babel-polyfil, yang hanya diperlukan jika Anda menggunakan
generator (yang mungkin bahkan tidak masuk akal dalam proyek ini) atau async
fungsi (yang menurut saya tidak akan banyak berubah dalam proyek
baik), menambahkan sekitar 50k ke build akhir. Tapi sekali lagi, ini opsional.
Sejauh kinerja, itu benar-benar tergantung pada fitur mana Anda sebenarnya
menggunakan. Misalnya, fungsi panah sedikit lebih lambat, karena
ikatan yang mendasarinya, kelas sedikit lebih lambat untuk dibuat, meskipun
waktu instantiating adalah sama. https://kpdecker.github.io/six-speed/
Impor/ekspor ES6 tidak didukung oleh browser, tetapi sejak itu
melalui sistem build, itu bukan masalah. Keluaran produk adalah
dapat digunakan persis seperti saat ini (bahkan kompatibel ke belakang), tapi
akan memungkinkannya untuk diintegrasikan ke dalam sistem pembangunan kami, dan membuat
komponen internal dapat digunakan kembali untuk kami.
Hal lain yang perlu diperhatikan adalah ukuran build akhir. Saat ini, hal-hal seperti Geometri,
Material, Mesh, dll adalah bagian dari ruang nama TIGA. Saat diperkecil,
referensi ke THREE.Geometry, THREE.Material, THREE.Mesh dll tetap ada di
kode. Dengan sistem modular, masing-masing file tersebut akan mendapatkan sesuatu seperti
var Geometry = require('./geometry');
kemudian memiliki referensi ke
variabel Geometry
nanti. Kemudian di minifaciton, Geometry
dan require
keduanya dialihkan ke karakter singe, './geometry' diganti dengan a
jumlah, menghasilkan sedikit penghematan. Matematika serbet: yang diperkecil
build adalah 511.794 byte dan berisi 2942 referensi ke
THREE\.[A-Z][a-zA-Z]+
. Mengganti semua ini dengan satu karakter
menghasilkan pengurangan ukuran file hampir 10% (turun menjadi 464.782). (yang di-gzip
ukuran masing-masing 117.278 dan 110.460, pengurangan 6%). bangunan
mungkin bisa disetel untuk mengurangi ini lebih jauh.
Rollup (yang menghilangkan kode yang tidak digunakan dari build final) adalah default
dengan jspm, akan menjadi default dengan webpack2 (dan saya yakin itu dapat digunakan
dengan paket web). Jika semuanya ditulis secara modular, saya rasa ini tidak akan terjadi
membantu, meskipun. Bagaimanapun, selama kode dapat ditranspilasikan dengan
babel, ini dapat digunakan dalam sistem build apa pun (pemuat glsl yang saya sebutkan
sebelumnya juga dapat dibuat untuk bekerja dengan webpack).
Pada Kam, 7 Juli 2016 pukul 13.28, Mr.doob notifications@github.com menulis:
Jenis-jenis tertentu dari hal-hal yang ditransfusikan menjadi besar (terutama:
generator dan fungsi async), tetapi jika Anda menghindarinya, Anda tidak akan memiliki
hukuman itu.Seberapa besar?
—
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/mrdoob/three.js/issues/4776#issuecomment -231197171,
atau matikan utasnya
https://github.com/notifications/unsubscribe/AA71cqAqmgxsUjpvamnI_xyL2wpzeWrdks5qTWGBgaJpZM4B4aA7
.
Tidak yakin apakah ini sangat membantu, tetapi ini adalah utas diskusi untuk D3 mengenai masalah yang sama: https://github.com/d3/d3/issues/2220. D3 4.0 telah mengadopsi impor/ekspor ES6 untuk mengelola modul, tetapi masih ditulis dalam ES5 (https://github.com/d3/d3/issues/2220#issuecomment-111655235).
Sangat menarik @jpweeks!
Jadi... dengan pendekatan impor/ekspor ini... Bagaimana hal-hal seperti object instanceof THREE.Mesh
terlihat?
@mrdoob
import/export
hanyalah cara modul dideklarasikan dan diperlukan. Itu tidak akan mempengaruhi/mengubah kode yang ditentukan dalam modul sama sekali:
src/Objek/Mesh.js
// Mesh class, stays the same as today (except the export part)
var Mesh = function ( geometry, material ) {
// ...
}
export default Mesh
src/Tiga.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..
Aplikasi.js
// In node
import {Mesh} from 'three'
var mesh = new Mesh(geo, mat)
console.log(mesh instanceof Mesh) // true
Klien.js
// In a browser
var mesh = new THREE.Mesh(geo, mat)
console.log(mesh instanceof THREE.Mesh) // true
Itu sangat membantu @GGalanSmithee! Terima kasih!
Saya orang yang visual jadi contoh pseudo-code meyakinkan saya lebih dari potongan besar teks
Benar, jadi itu akan membutuhkan sedikit refactoring ...
Adakah yang tahu jika kompiler penutupan berencana mendukung ini?
Benar, jadi itu akan membutuhkan sedikit refactoring ...
Aku mendapatkanmu! Karena utas ini menjadi hidup selama beberapa hari terakhir, saya telah bekerja sedikit lebih banyak pada three-jsnext . Ini adalah proyek yang mengambil basis kode Three.js yang ada dan mengubahnya menjadi modul ES secara otomatis. Hanya berselisih dengan beberapa dependensi siklus yang rumit (terutama sekitar KeyframeTrack
), tetapi harus segera memiliki sesuatu untuk dibagikan. Sejauh yang saya tahu, semua contoh terus berfungsi, dan build yang diperkecil lebih kecil dari yang sekarang (menggunakan Rollup untuk menghasilkan file UMD), jadi itu semua kabar baik.
Oke, saya sudah membuka permintaan tarik untuk ini: #9310
@mrdoob
Kami memiliki perpustakaan dalam produksi yang kurang lebih terstruktur seperti TIGA. Ia bekerja di browser dan lingkungan modular. Basis kodenya adalah ES6 tetapi browser sama sekali bukan urusan Anda.
Anda akan mengirimkan ini pada npm _as is_, semua modul disertakan + monolit browser namespace global yang dikompilasi (three.js). Siapa pun yang perlu menggunakan satu bagiannya menggunakan alat untuk membuat bundel.
Pertimbangkan struktur seperti ini:
/src
classA.js
classB.js
classC.js
/index.js
/browser.js
index.js cukup mengekspor kembali semua modul dan fungsi dalam satu file:
export ClassA from './src/classA';
export ClassB from './src/classB';
export ClassC from './src/classC';
Jadi pengguna akhir dapat menginstal lib npm dan menggunakannya tanpa basa-basi lagi:
// 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 akan menjadi satu-satunya bagian yang dikompilasi dari paket. Biasanya ditranspilasikan ke ES5 melalui Babel dan diekspor ke namespace global sehingga dapat digunakan sebagai skrip yang disertakan. Rollup, Webpack, dll. dapat membuat ini dengan mudah.
@mrdoob ini perjalanan yang luar biasa
Komentar yang paling membantu
Aku mendapatkanmu! Karena utas ini menjadi hidup selama beberapa hari terakhir, saya telah bekerja sedikit lebih banyak pada three-jsnext . Ini adalah proyek yang mengambil basis kode Three.js yang ada dan mengubahnya menjadi modul ES secara otomatis. Hanya berselisih dengan beberapa dependensi siklus yang rumit (terutama sekitar
KeyframeTrack
), tetapi harus segera memiliki sesuatu untuk dibagikan. Sejauh yang saya tahu, semua contoh terus berfungsi, dan build yang diperkecil lebih kecil dari yang sekarang (menggunakan Rollup untuk menghasilkan file UMD), jadi itu semua kabar baik.