Weboldal keresés

javascript - Hogyan tudom megosztani a kódot a Node.js és a böngésző között?


Készítek egy kis alkalmazást egy JavaScript klienssel (ami a böngészőben fut) és egy Node.js szerverrel, amelyek WebSocket segítségével kommunikálnak.

Szeretném megosztani a kódot a kliens és a szerver között. Épp most kezdtem el a Node.js-t, és modern JavaScript ismereteim - enyhén szólva - kissé rozsdásak. Szóval még mindig próbálom átlátni a CommonJS require() függvényt. Ha a csomagjaimat az 'export' objektum használatával hozom létre, akkor nem látom, hogyan tudnám ugyanazokat a JavaScript fájlokat a böngészőben is használni.

Szeretnék létrehozni egy készletnyi metódust és osztályt, amelyeket mindkét oldalon használnak az üzenetek kódolásának és dekódolásának, valamint más tükrözött feladatok megkönnyítésére. Azonban a Node.js/CommonJS csomagolási rendszerek úgy tűnik, hogy megakadályozzák, hogy JavaScript fájlokat hozzak létre, amelyeket mindkét oldalon lehetne használni.

Megpróbáltam a JS.Class-t is használni egy szorosabb objektumorientált modell kialakításához, de feladtam, mert nem tudtam rájönni, hogyan lehet a mellékelt JavaScript fájlokat működésre bírni a require() segítségével. Van valami, amit kihagytam itt?

Válasz #1

Ha szeretnél írni egy modult, amit mind kliens oldalon, mind szerver oldalon lehet használni, van egy rövid blogbejegyzésem egy gyors és egyszerű módszerről: Írás Node.js-hez és a böngészőhöz, lényegében a következő (ahol a this ugyanaz, mint a window):

(function(exports){

    // Your code goes here

   exports.test = function(){
        return 'hello world'
    };

})(typeof exports === 'undefined'? this['mymodule']={}: exports);

Alternatívaként léteznek olyan projektek is, amelyek a Node.js API-t a kliens oldalon kívánják megvalósítani, mint például Marak gemini projektje.

Érdekelhet még a DNode is, amely lehetővé teszi, hogy egy JavaScript-függvényt kiteszel, így az egy másik gépről egyszerű, JSON-alapú hálózati protokollt használva meghívható.

Válasz #2

Epelinek van itt egy jó megoldása http://epeli.github.com/piler/, ami még a könyvtár nélkül is működik, csak tedd ezt egy share.js nevű fájlba

(function(exports){

  exports.test = function(){
       return 'This is a function from shared module';
  };

}(typeof exports === 'undefined' ? this.share = {} : exports));

A szerver oldalon egyszerűen használd:

var share = require('./share.js');

share.test();

És a kliens oldalon csak töltsd be a js fájlt, majd használd

share.test();

Válasz #3

Tekintse meg a jQuery forráskódját, amely lehetővé teszi ezt a működést a Node.js modulmintában, az AMD modulmintában és a böngésző globális környezetében:

(function(window){
    var jQuery = 'blah';

    if (typeof module === "object" && module && typeof module.exports === "object") {

        // Expose jQuery as module.exports in loaders that implement the Node
        // module pattern (including browserify). Do not create the global, since
        // the user will be storing it themselves locally, and globals are frowned
        // upon in the Node module world.
        module.exports = jQuery;
    }
    else {
        // Otherwise expose jQuery to the global object as usual
        window.jQuery = window.$ = jQuery;

        // Register as a named AMD module, since jQuery can be concatenated with other
        // files that may use define, but not via a proper concatenation script that
        // understands anonymous AMD modules. A named AMD is safest and most robust
        // way to register. Lowercase jquery is used because AMD module names are
        // derived from file names, and jQuery is normally delivered in a lowercase
        // file name. Do this after creating the global so that if an AMD module wants
        // to call noConflict to hide this version of jQuery, it will work.
        if (typeof define === "function" && define.amd) {
            define("jquery", [], function () { return jQuery; });
        }
    }
})(this)

Válasz #4

Ne feledd, hogy egy JavaScript függvény string reprezentációja a függvény forráskódját jelenti. Egyszerűen írhatnád a függvényeidet és konstruktoraidat kapszulázott módon, így azok toString() segítségével lekérhetők és elküldhetők a kliensnek.

Egy másik módja annak, hogy ezt megtegyük, az, hogy használunk egy build rendszert, a közös kódot külön fájlokba tesszük, majd mindkettőbe, a szerver és a kliens szkriptekbe is beillesztjük. Én ezt a megközelítést használom egy egyszerű kliens/szerver játékhoz WebSocketeken keresztül, ahol a szerver és a kliens lényegében ugyanazt a játékhurokot futtatja, és a kliens minden ütemben szinkronizál a szerverrel, hogy megbizonyosodjon arról, hogy senki sem csal.

A játékomhoz használt build rendszer egy egyszerű Bash script, ami átfuttatja a fájlokat a C preprocesszoron, majd a sed-en, hogy eltakarítsa a cpp után maradt szemétmaradékot, így minden normál preprocesszoros dolgot használhatok, mint például #include, #define, #ifdef stb.

Válasz #5

Azt javasolnám, hogy nézzen utána a RequireJS adapternek a Node.js-hez. A probléma az, hogy a Node.js által alapértelmezés szerint használt CommonJS modulminta nem aszinkron, ami blokkolja a betöltést a web böngészőben. A RequireJS az AMD mintát használja, amely egyszerre aszinkron és kompatibilis mind a szerverrel, mind a klienssel, amennyiben a r.js adaptert használja.

Válasz #6

Lehet, hogy ez nem teljesen felel meg a kérdésnek, de gondoltam, megosztom ezt.

Szerettem volna néhány egyszerű karakterlánc segédfüggvényt létrehozni, amelyek a String.prototype-on vannak deklarálva, és mind a node, mind a böngésző számára elérhetők legyenek. Egyszerűen ezek a függvények egy utilities.js nevű fájlban vannak, egy almappában, és könnyedén hivatkozhatok rájuk mind a böngészőbeli script-tagből, mind a Node.js szkriptben a require használatával (a .js kiterjesztés elhagyásával):

my_node_script.js

var utilities = require('./static/js/utilities')

my_browser_code.html

<script src="/static/js/utilities.js"></script>

Remélem, hogy ez másnak is hasznos információ, nem csak nekem.

Válasz #7

Ha modulcsomagolókat, például a webpack-et használ a JavaScript fájlok böngészőben történő használatra történő összefűzéséhez, egyszerűen újra felhasználhatod a Node.js modulodat a böngészőben futó frontendhez. Más szóval, a Node.js modulod megosztható a Node.js és a böngésző között.

Például a következő kódod van sum.js fájlban:

Normál Node.js modul: sum.js

const sum = (a, b) => {
    return a + b
}

module.exports = sum

Használd a modult Node.js-ben

const sum = require('path-to-sum.js')
console.log('Sum of 2 and 5: ', sum(2, 5)) // Sum of 2 and 5:  7

Használd újra a frontendben

import sum from 'path-to-sum.js'
console.log('Sum of 2 and 5: ', sum(2, 5)) // Sum of 2 and 5:  7

Kapcsolódó cikkek