Jestem nowy w nodejs i browserify. Zacząłem od tego linku .
Mam plik main.js, który zawiera ten kod
var unique = require('uniq');
var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
this.LogData =function(){
console.log(unique(data));
};
Teraz instaluję moduł uniq z npm:
npm install uniq
Następnie łączę wszystkie wymagane moduły zaczynając od main.js w jednym pliku o nazwie bundle.js za pomocą polecenia browserify:
browserify main.js -o bundle.js
Wygenerowany plik wygląda następująco:
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var unique = require('uniq');
var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];
this.LogData =function(){
console.log(unique(data));
};
},{"uniq":2}],2:[function(require,module,exports){
"use strict"
function unique_pred(list, compare) {
var ptr = 1
, len = list.length
, a=list[0], b=list[0]
for(var i=1; i<len; ++i) {
b = a
a = list[i]
if(compare(a, b)) {
if(i === ptr) {
ptr++
continue
}
list[ptr++] = a
}
}
list.length = ptr
return list
}
function unique_eq(list) {
var ptr = 1
, len = list.length
, a=list[0], b = list[0]
for(var i=1; i<len; ++i, b=a) {
b = a
a = list[i]
if(a !== b) {
if(i === ptr) {
ptr++
continue
}
list[ptr++] = a
}
}
list.length = ptr
return list
}
function unique(list, compare, sorted) {
if(list.length === 0) {
return []
}
if(compare) {
if(!sorted) {
list.sort(compare)
}
return unique_pred(list, compare)
}
if(!sorted) {
list.sort()
}
return unique_eq(list)
}
module.exports = unique
},{}]},{},[1])
Po dołączeniu pliku bundle.js do mojej strony index.htm, jak wywołać funkcję logData?
node.js
npm
browserify
SharpCoder
źródło
źródło
Odpowiedzi:
Domyślnie browserify nie pozwala na dostęp do modułów spoza kodu przeglądarkowego - jeśli chcesz wywołać kod w module z przeglądarką, powinieneś przeglądać swój kod razem z modułem. Przykłady można znaleźć pod adresem http://browserify.org/ .
Oczywiście możesz również jawnie udostępnić swoją metodę z zewnątrz w następujący sposób:
window.LogData =function(){ console.log(unique(data)); };
Wtedy możesz zadzwonić
LogData()
z dowolnego innego miejsca na stronie.źródło
onclick="someFunction()"
. Nie możesz argumentować, że to rzadki przypadek użycia!?!Kluczową częścią łączenia samodzielnych modułów z Browserify jest
--s
opcja. Ujawnia wszystko, co eksportujesz z modułu, używając węzłamodule.exports
jako zmiennej globalnej. Plik można następnie umieścić w<script>
tagu.Musisz to zrobić tylko wtedy, gdy z jakiegoś powodu chcesz, aby ta zmienna globalna była ujawniona. W moim przypadku klient potrzebował samodzielnego modułu, który można umieścić na stronach internetowych bez martwienia się o ten biznes związany z przeglądarką.
Oto przykład, w którym używamy
--s
opcji z argumentemmodule
:browserify index.js --s module > dist/module.js
Spowoduje to ujawnienie naszego modułu jako zmiennej globalnej o nazwie
module
.Źródło .
Aktualizacja: dzięki @fotinakis. Upewnij się, że zdajesz
--standalone your-module-name
. Jeśli zapomnisz, że--standalone
pobiera argument, Browserify może po cichu wygenerować pusty moduł, ponieważ nie może go znaleźć.Mam nadzieję, że zaoszczędzi ci to trochę czasu.
źródło
Odpowiedź @Matas Vaitkevicius z samodzielną opcją Browserify jest poprawna (odpowiedź @ thejh przy użyciu zmiennej globalnej okna również działa, ale jak zauważyli inni, zanieczyszcza globalną przestrzeń nazw, więc nie jest idealna). Chciałem dodać trochę więcej szczegółów na temat korzystania z opcji samodzielnej.
W skrypcie źródłowym, który chcesz spakować, upewnij się, że ujawnisz funkcje, które chcesz wywołać za pośrednictwem module.exports. W skrypcie klienta można wywołać te ujawnione funkcje za pomocą <nazwa-pakietu>. <nazwa-func> . Oto przykład:
Mój plik źródłowy src / script.js będzie miał to:
module.exports = {myFunc: func};
Moje polecenie browserify będzie wyglądać mniej więcej tak:
browserify src/script.js --standalone myBundle > dist/bundle.js
A mój skrypt klienta dist / client.js załaduje dołączony skrypt,
<script src="bundle.js"></script>
a następnie wywoła udostępnioną funkcję w następujący sposób:
<script>myBundle.myFunc();</script>
Nie ma potrzeby wymagania nazwy pakietu w skrypcie klienta przed wywołaniem udostępnionych funkcji, np.
Nie jest to konieczne i nie będzie działać.<script src="bundle.js"></script><script>var bundled = require("myBundle"); bundled.myFunc();</script>
W rzeczywistości, podobnie jak wszystkie funkcje dostarczane przez browserify bez trybu samodzielnego, funkcja require nie będzie dostępna poza dołączonym skryptem . Browserify umożliwia korzystanie z niektórych funkcji węzła po stronie klienta, ale tylko w samym skrypcie dołączonym ; nie jest przeznaczony do tworzenia samodzielnego modułu, który można importować i używać w dowolnym miejscu po stronie klienta, dlatego musimy zadać sobie tyle trudu, aby wywołać pojedynczą funkcję poza powiązanym kontekstem.
źródło
myBundle
przyczepia się do obiektu okna,window.myBundle.myFunc()
zamiast do okna. MyFunc ()Właśnie przeczytałem odpowiedzi i wygląda na to, że nikt nie wspomniał o zastosowaniu zakresu zmiennej globalnej? Co jest przydatne, jeśli chcesz użyć tego samego kodu w node.js iw przeglądarce.
class Test { constructor() { } } global.TestClass = Test;
Następnie możesz uzyskać dostęp do TestClass w dowolnym miejscu.
<script src="bundle.js"></script> <script> var test = new TestClass(); // Enjoy! </script>
Uwaga: klasa TestClass staje się wtedy dostępna wszędzie. To jest to samo, co użycie zmiennej okna.
Dodatkowo możesz utworzyć dekorator, który uwidacznia klasę w zakresie globalnym. Co jest naprawdę fajne, ale utrudnia śledzenie, gdzie zdefiniowano zmienną.
źródło
global
daje taki sam efekt jak dodanie dowindow
, co zostało już uwzględnione w jh. Ta odpowiedź nie dodaje żadnych nowych informacji.return {}
ale upuść otwierający nawias klamrowy do następnej linii.Przeczytaj plik README.md w pliku browserify o
--standalone
parametrze lub google "browserify umd"źródło
Aby Twoja funkcja była dostępna zarówno z poziomu HTML, jak iz węzła po stronie serwera:
main.js:
var unique = require('uniq'); function myFunction() { var data = [1, 2, 2, 4, 3]; return unique(data).toString(); } console.log ( myFunction() ); // When browserified - we can't call myFunction() from the HTML, so we'll externalize myExtFunction() // On the server-side "window" is undef. so we hide it. if (typeof window !== 'undefined') { window.myExtFunction = function() { return myFunction(); } }
main.html:
<html> <head> <script type='text/javascript' src="bundle.js"></script> <head> <body> Result: <span id="demo"></span> <script>document.getElementById("demo").innerHTML = myExtFunction();</script> </body> </html>
Biegać:
i powinieneś uzyskać takie same wyniki podczas otwierania main.html w przeglądarce, jak podczas uruchamiania
źródło
Minimalny działający przykład
Jest to w zasadzie to samo, co: https://stackoverflow.com/a/43215928/895245, ale z konkretnymi plikami, które pozwolą ci po prostu uruchomić i łatwo odtworzyć go samodzielnie.
Ten kod jest również dostępny pod adresem : https://github.com/cirosantilli/browserify-hello-world
index.js
const uniq = require('uniq'); function myfunc() { return uniq([1, 2, 2, 3]).join(' '); } exports.myfunc = myfunc;
index.html
<!doctype html> <html lang=en> <head> <meta charset=utf-8> <title>Browserify hello world</title> </head> <body> <div id="container"> </body> </div> <script src="out.js"></script> <script> document.getElementById('container').innerHTML = browserify_hello_world.myfunc(); </script> </html>
Użycie Node.js:
#!/usr/bin/env node const browserify_hello_world = require('./index.js'); console.log(browserify_hello_world.myfunc());
Wygeneruj
out.js
do użytku w przeglądarce:Zarówno przeglądarka, jak i wiersz poleceń wyświetlają oczekiwane dane wyjściowe:
1 2 3
Testowane z przeglądarką Browserify 16.5.0, Node.js 10.15.1, Chromium 78, Ubuntu 19.10.
źródło
exports.myfunc.= myfunc
Część to było absolutnie konieczne i brakowało w innych odpowiedzi.to naprawdę proste - cała ta koncepcja dotyczy owijania
1. alternatywa - obiekt „this”
w tym celu zakładam, że masz „tylko 1 skrypt dla całej aplikacji {{app_name}}” i „1 funkcję {{function_name}}”
dodaj funkcję {{function_name}} do obiektu „this”
function {{function_name}}(param) {} -> this.{{function_name}} = function(param) {}
wtedy musisz nazwać ten obiekt aby był dostępny - zrobisz to dodając parametr "samodzielny z nazwą" tak jak radzili inni
więc jeśli używasz "watchify" z "browserify", użyj tego
var b = browserify({ ... standalone: '{{app_name}}' });
lub wiersz poleceń
wtedy możesz wywołać swoją funkcję z przeglądarki
{{app_name}}.{{function_name}}(param); window.{{app_name}}.{{function_name}}(param);
2. alternatywa - obiekt „okno”
dodaj funkcję {{function_name}} do obiektu „window”
function {{function_name}}(param) {} -> window.{{function_name}} = function(param) {}
wtedy możesz wywołać swoją funkcję z przeglądarki
{{function_name}}(param); window.{{function_name}}(param);
-
może komuś pomogę
źródło
Masz kilka możliwości:
Niech plugin browserify-bridge automatycznie wyeksportuje moduły do wygenerowanego modułu wejściowego. Jest to przydatne w przypadku projektów SDK lub sytuacji, w których nie trzeba ręcznie nadążać za eksportowanymi danymi.
Postępuj zgodnie z wzorcem pseudo-przestrzeni nazw, aby uzyskać pełną ekspozycję:
Najpierw ułóż swoją bibliotekę w ten sposób, korzystając z wyszukiwania indeksów w folderach:
Za pomocą tego wzorca definiujesz wpis w ten sposób:
exports.Helpers = require('./helpers'); exports.Providers = require('./providers'); ...
W swoich podfolderach możesz po prostu dołączyć podobny manifest dostępnych modułów w tym kontekście:
exports.SomeHelper = require('./someHelper');
Ten wzorzec bardzo dobrze się skaluje i pozwala na kontekstowe (folder po folderze) śledzenie tego, co należy uwzględnić w zwiniętym api.
źródło
window.LogData =function(data){ return unique(data); };
Wywołaj funkcję po prostu
LogData(data)
To tylko niewielka modyfikacja odpowiedzi thejh, ale ważna
źródło
W celu debugowania dodałem ten wiersz do mojego code.js:
window.e = function(data) {eval(data);};
Wtedy mogłem uruchomić wszystko, nawet poza pakietem.
e("anything();");
źródło