Saya membuat aplikasi kecil dengan klien JavaScript (dijalankan di browser) dan server Node.js, berkomunikasi menggunakan WebSocket.
Saya ingin membagikan kode antara klien dan server. Saya baru saja mulai dengan Node.js dan pengetahuan saya tentang JavaScript modern sedikit berkarat, untuk sedikitnya. Jadi saya masih memikirkan fungsi CommonJS membutuhkan (). Jika saya membuat paket saya dengan menggunakan objek 'ekspor', maka saya tidak bisa melihat bagaimana saya bisa menggunakan file JavaScript yang sama di browser.
Saya ingin membuat seperangkat metode dan kelas yang digunakan pada kedua ujungnya untuk memfasilitasi pengodean dan pendekodean pesan, dan tugas-tugas cermin lainnya. Namun, sistem pengemasan Node.js / CommonJS tampaknya menghalangi saya untuk membuat file JavaScript yang dapat digunakan di kedua sisi.
Saya juga mencoba menggunakan JS.Class untuk mendapatkan model OO yang lebih ketat, tetapi saya menyerah karena saya tidak tahu bagaimana cara mendapatkan file JavaScript yang disediakan agar berfungsi dengan memerlukan (). Apakah ada sesuatu yang saya lewatkan di sini?
sumber
Jawaban:
Jika Anda ingin menulis modul yang dapat digunakan baik sisi klien dan sisi server, saya punya posting blog pendek tentang metode cepat dan mudah: Menulis untuk Node.js dan browser , pada dasarnya yang berikut (di mana
this
sama denganwindow
) :Atau ada beberapa proyek yang bertujuan untuk mengimplementasikan API Node.js di sisi klien, seperti Marini's gemini .
Anda mungkin juga tertarik dengan DNode , yang memungkinkan Anda mengekspos fungsi JavaScript sehingga dapat dipanggil dari komputer lain menggunakan protokol jaringan sederhana berbasis JSON.
sumber
Epeli memiliki solusi yang bagus di sini http://epeli.github.com/piler/ yang bahkan berfungsi tanpa pustaka, cukup masukkan ini dalam file yang disebut share.js
Di sisi server cukup gunakan:
Dan di sisi klien hanya memuat file js dan kemudian gunakan
sumber
Periksa kode sumber jQuery yang menjadikan ini berfungsi dalam pola modul Node.js, pola modul AMD, dan global di peramban:
sumber
Jangan lupa bahwa representasi string dari fungsi JavaScript mewakili kode sumber untuk fungsi itu. Anda cukup menulis fungsi dan konstruktor Anda dengan cara enkapsulasi sehingga mereka bisa menjadiString () dan dikirim ke klien.
Cara lain untuk melakukannya adalah menggunakan sistem build, meletakkan kode umum dalam file terpisah, dan kemudian memasukkannya ke dalam skrip server dan klien. Saya menggunakan pendekatan itu untuk permainan klien / server sederhana melalui WebSockets di mana server dan klien menjalankan keduanya pada dasarnya lingkaran permainan yang sama dan klien menyinkronkan dengan server setiap centang untuk memastikan tidak ada yang curang.
Sistem build saya untuk gim ini adalah skrip Bash sederhana yang menjalankan file melalui prepro C dan kemudian melalui sed untuk membersihkan beberapa sampah sampah cpp di belakang, jadi saya dapat menggunakan semua hal preprosesor normal seperti #include, #define, #ifdef , dll.
sumber
Saya akan merekomendasikan melihat ke dalam adaptor RequireJS untuk Node.js . Masalahnya adalah bahwa pola modul CommonJS yang digunakan Node.js secara default tidak asinkron, yang memblokir pemuatan di browser web. RequireJS menggunakan pola AMD, yang asinkron dan kompatibel dengan server dan klien, selama Anda menggunakan
r.js
adaptor.sumber
Mungkin ini tidak sepenuhnya sejalan dengan pertanyaan, tetapi saya pikir saya akan membagikan ini.
Saya ingin membuat beberapa fungsi utilitas string sederhana, dideklarasikan pada String.prototype, tersedia untuk node dan browser. Saya cukup menyimpan fungsi-fungsi ini dalam file yang disebut utilities.js (dalam subfolder) dan dapat dengan mudah mereferensikan keduanya dari tag-skrip dalam kode browser saya, dan dengan menggunakan require (menghilangkan ekstensi .js) di skrip Node.js saya :
my_node_script.js
my_browser_code.html
Saya harap ini adalah informasi yang berguna untuk orang lain selain saya.
sumber
utilites.js
dengan satu barismodule.exports = require('./static/js/utilities');
. Dengan cara ini Anda hanya perlu memperbarui satu jalur jika Anda mengacak barang-barang.utilities.js
ada dishared
bawah proyek. Menggunakanrequire('/shared/utilities')
memberi saya kesalahanCannot find module '/shared/utilities'
. Saya harus menggunakan sesuatu seperti inirequire('./../../shared/utilities')
untuk membuatnya bekerja. Jadi, selalu berjalan dari folder saat ini dan melakukan perjalanan ke root lalu turun.Jika Anda menggunakan bundler modul seperti webpack untuk membundel file JavaScript untuk digunakan di browser, Anda bisa menggunakan kembali modul Node.js Anda untuk antarmuka yang berjalan di browser. Dengan kata lain, modul Node.js Anda dapat dibagi antara Node.js dan browser.
Misalnya, Anda memiliki kode sum.js berikut:
Modul Node.js normal: sum.js
Gunakan modul di Node.js
Gunakan kembali di frontend
sumber
Server hanya dapat mengirim file sumber JavaScript ke klien (browser) tetapi masalahnya adalah bahwa klien harus menyediakan lingkungan "ekspor" mini sebelum dapat
exec
kode dan menyimpannya sebagai modul.Cara sederhana untuk membuat lingkungan seperti itu adalah dengan menggunakan penutupan. Misalnya, server Anda menyediakan file sumber melalui HTTP like
http://example.com/js/foo.js
. Browser dapat memuat file yang diperlukan melalui XMLHttpRequest dan memuat kode seperti ini:Kuncinya adalah bahwa klien dapat membungkus kode asing menjadi fungsi anonim untuk segera dijalankan (penutupan) yang menciptakan objek "ekspor" dan mengembalikannya sehingga Anda dapat menetapkannya di tempat yang Anda inginkan, daripada mencemari namespace global. Dalam contoh ini, ditugaskan ke atribut jendela
fooModule
yang akan berisi kode yang diekspor oleh filefoo.js
.sumber
window.fooModule = {}; (new Function('exports', xhr.responseText))(window.fooModule)
.Tidak ada solusi sebelumnya yang membawa sistem modul CommonJS ke browser.
Seperti disebutkan dalam jawaban lain, ada solusi manajer aset / paket seperti Browserify atau Piler dan ada solusi RPC seperti dnode atau nowjs .
Tetapi saya tidak dapat menemukan implementasi CommonJS untuk browser (termasuk
require()
fungsi danexports
/module.exports
objek, dll.). Jadi saya menulis sendiri, hanya untuk menemukan setelah itu bahwa orang lain telah menulisnya lebih baik daripada saya: https://github.com/weepy/brequire . Ini disebut Brequire (kependekan dari Browser membutuhkan).Dilihat berdasarkan popularitas, manajer aset sesuai dengan kebutuhan kebanyakan pengembang. Namun, jika Anda memerlukan implementasi browser CommonJS, Brequire mungkin akan sesuai dengan tagihan.
Pembaruan 2015: Saya tidak lagi menggunakan Brequire (belum diperbarui dalam beberapa tahun). Jika saya hanya menulis modul kecil, open-source dan saya ingin siapa saja dapat menggunakan dengan mudah, maka saya akan mengikuti pola yang mirip dengan jawaban Caolan (di atas) - Saya menulis posting blog tentang hal itu beberapa tahun lalu.
Namun, jika saya menulis modul untuk penggunaan pribadi atau untuk komunitas yang distandarisasi pada CommonJS (seperti komunitas Ampersand ) maka saya hanya akan menulisnya dalam format CommonJS dan menggunakan Browserify .
sumber
now.js juga patut dilihat. Ini memungkinkan Anda untuk memanggil sisi server dari sisi klien, dan fungsi sisi klien dari sisi server
sumber
Jika Anda ingin menulis peramban dengan gaya seperti Node.js, Anda dapat mencoba memilah .
Tidak ada kompilasi kode browser, sehingga Anda dapat menulis aplikasi Anda tanpa batasan.
sumber
Tulis kode Anda sebagai modul RequireJS dan tes Anda sebagai tes Jasmine .
Kode cara ini dapat dimuat di mana saja dengan RequireJS dan tes dijalankan di browser dengan jasmine-html dan dengan jasmine-node di Node.js tanpa perlu memodifikasi kode atau tes.
Ini adalah contoh yang bagus untuk ini.
sumber
Use case: bagikan konfigurasi aplikasi Anda antara Node.js dan browser (ini hanya ilustrasi, mungkin bukan pendekatan terbaik tergantung pada aplikasi Anda).
Masalah: Anda tidak dapat menggunakan
window
(tidak ada di Node.js) atauglobal
(tidak ada di browser).Larutan:
File config.js:
Di browser (index.html):
Anda sekarang dapat membuka alat dev dan mengakses variabel global
config
Di Node.js (app.js):
Dengan Babel atau TypeScript:
sumber
shared.js
danhelpers.js
-shared.js
menggunakan fungsi darihelpers.js
, jadi perluconst { helperFunc } = require('./helpers')
di bagian atas, agar dapat bekerja di sisi server. Masalahnya adalah pada klien, ia mengeluh tentangrequire
tidak menjadi fungsi, tetapi jika saya membungkus baris memerlukanif (typeof module === 'object') { ... }
, server mengatakan bahwa helperFunc () tidak didefinisikan (di luar pernyataan if). Ada ide untuk membuatnya bekerja pada keduanya?shared.js
:helperFunc = (typeof exports === 'undefined') ? helperFunc : require('./helpers').helperFunc;
- Akan membutuhkan garis untuk setiap fungsi yang diekspor, tapi mudah-mudahan ini solusi yang baik?Saya menulis modul sederhana , yang dapat diimpor (baik menggunakan wajib di Node, atau tag skrip di browser), yang dapat Anda gunakan untuk memuat modul baik dari klien dan dari server.
Contoh penggunaan
1. Menentukan modul
Tempatkan yang berikut dalam file
log2.js
, di dalam folder file web statis Anda:Sederhana seperti itu!
2. Menggunakan modul
Karena ini adalah pemuat modul bilateral , kami dapat memuatnya dari kedua sisi (klien dan server). Oleh karena itu, Anda dapat melakukan hal berikut, tetapi Anda tidak perlu melakukan keduanya sekaligus (apalagi dalam urutan tertentu):
Di Node, itu sederhana:
Ini harus kembali
2
.Jika file Anda tidak ada di direktori Node saat ini, pastikan untuk memanggil
loader.setRoot
dengan path ke folder file web statis Anda (atau di mana pun modul Anda berada).Pertama, tentukan halaman web:
Pastikan Anda tidak membuka file secara langsung di browser Anda; karena menggunakan AJAX, saya sarankan Anda melihat
http.server
modul Python 3 (atau apa pun supercepat Anda, baris perintah, solusi penyebaran folder server web) sebagai gantinya.Jika semuanya berjalan dengan baik, ini akan muncul:
sumber
Saya menulis ini, mudah digunakan jika Anda ingin mengatur semua variabel ke lingkup global:
sumber