Browserify - Tarayıcıda browsererify aracılığıyla oluşturulan bir dosyada paketlenmiş işlev nasıl çağrılır


96

Nodejs ve browsererify konusunda yeniyim. Bu bağlantıyla başladım .

Bu kodu içeren main.js dosyam var

var unique = require('uniq');

var data = [1, 2, 2, 3, 4, 5, 5, 5, 6];

this.LogData =function(){
console.log(unique(data));
};

Şimdi uniq modülünü npm ile kuruyorum:

 npm install uniq

Ardından, main.js'den başlayarak gerekli tüm modülleri, browsererify komutuyla birlikte bundle.js adlı tek bir dosyada topluyorum:

browserify main.js -o bundle.js

Oluşturulan dosya şuna benzer:

(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])

Bundle.js dosyasını index.htm sayfama ekledikten sonra logData işlevini nasıl çağırırım?


Onu nerede aramak istersiniz? Ve neden onu aramak istiyorsun?
artur grzesiak

2
@arturgrzesiak: Bu işlevi tarayıcıda çalıştıracağım diğer bir projemde kullanmak istiyorum.
SharpCoder

Yanıtlar:


83

Varsayılan olarak, browsererify, modüllere tarayıcı tarafından doğrulanmış kodun dışından erişmenize izin vermez - tarayıcı doğrulanmış bir modülde kod çağırmak istiyorsanız, kodunuzu modülle birlikte gözden geçirmeniz gerekir. Bunun örnekleri için http://browserify.org/ adresine bakın .

Elbette, yönteminizi aşağıdaki gibi açıkça dışarıdan da erişilebilir hale getirebilirsiniz:

window.LogData =function(){
  console.log(unique(data));
};

Sonra LogData()sayfanın herhangi bir yerinden arayabilirsin .


1
Teşekkür ederim. Bu çalışıyor. Bu, this.functionName yerine işlevler oluştururken window.functionName yazmam gerektiği anlamına mı geliyor? Bunun için başka işimiz var mı? Window.functionName kullanmak için herhangi bir neden var mı?
SharpCoder

21
"modülle birlikte kodunuzu doğrulamanız gerekiyor" - Ugh, ya ben böyle bir şey yapmak istersem onclick="someFunction()". Bunun nadir bir kullanım durumu olduğunu iddia edemezsiniz!?!
BlueRaja - Danny Pflughoeft

57
Yeni başlayanlar için istemcide Browserify'ın nasıl kullanılacağına dair ciddi bir belge eksikliği var.
Oliver Dixon

1
evet, dokümantasyon, bunun kaçınılması gereken bir tasarım kararı olduğunu açıkça belirtmeli, ancak bir alternatifiniz olmadığında çalışmasını sağlamak için net bir yol sağlamalıdır (benim durumumda, bir JS nesnesini doldurmak için şablondaki verileri kullanmak) ... @thejh'ye basit bir çözüme işaret ettiği için teşekkürler! ;)
Alexandre Martini

1
Ana işlevlerinizi modülün dışında kullanıma sunmak istemeyeceğiniz bir durumu bile düşünemiyorum. Bu nasıl varsayılan davranış değildir? Ne tür bir web uygulaması işlevleri çağırmaz?
Sibernetik

101

Bağımsız modülleri Browserify ile bir araya getirmenin en önemli kısmı --sseçenektir. Düğümleri module.exportsglobal bir değişken olarak kullanarak modülünüzden aktardığınız her şeyi ortaya çıkarır . Dosya daha sonra bir <script>etikete eklenebilir .

Bunu sadece bir sebepten ötürü global değişkenin açığa çıkmasına ihtiyaç duyduğunuzda yapmanız gerekir. Benim durumumda, müşterinin bu Browserify işi hakkında endişelenmelerine gerek kalmadan web sayfalarına eklenebilecek bağımsız bir modüle ihtiyacı vardı.

Aşağıda, --sseçeneği bir argümanla birlikte kullandığımız bir örnek verilmiştir module:

browserify index.js --s module > dist/module.js

Bu, modülümüzü adlı global bir değişken olarak ortaya çıkaracaktır module.
Kaynak .

Güncelleme: @fotinakis'e teşekkürler. Geçtiğinden emin ol --standalone your-module-name. Bunun --standalonebir argüman gerektirdiğini unutursanız , Browserify onu bulamadığı için sessizce boş bir modül oluşturabilir.

Umarım bu size biraz zaman kazandırır.


2
Babelifiye ES6 koduna göz atmaya çalışıyorum. Ancak tarayıcıda konsolide etmeye çalıştığımda bağımsız nesne boş. Herhangi bir modül içermeyen basit ES6 kodu, bağımsız modda iyi çalışır. Bununla ilgili herhangi bir işaret var mı?
John

@jackyrudetsky fikrim yok, SO'ya bir soru eklemenizi tavsiye ederim, ilginç bir konu gibi geliyor. bununla ilgili olabilir. github.com/substack/node-browserify/issues/1357
Matas Vaitkevicius


3
IMO bu kabul edilen cevap olmalıdır. Global bir işlev kullanıyorsanız, her işlevi pencereden asmaktansa kendi ad alanınıza sahip olmak çok daha iyidir.
VictorB

1
@VictorB Javascript'teki tüm global değişkenler pencerenin öğeleridir, bu nedenle her iki yöntem de aynı şeyi başarır (global değişkenleri pencereye ekleyerek)
David Lopez

37

@Matas Vaitkevicius'un Browserify'nin bağımsız seçeneği ile cevabı doğrudur (@ thejh'nin pencere global değişkenini kullanan yanıtı da işe yarıyor, ancak diğerlerinin de belirttiği gibi, küresel ad alanını kirletiyor, bu yüzden ideal değil). Bağımsız seçeneğin nasıl kullanılacağına dair biraz daha ayrıntı eklemek istedim.

Paketlemek istediğiniz kaynak komut dosyasında, module.exports aracılığıyla çağırmak istediğiniz işlevleri gösterdiğinizden emin olun. İstemci komut dosyasında, bu açıklanmış işlevleri <paket-adı>. < İşlev -adı> aracılığıyla çağırabilirsiniz . İşte bir örnek:

Benim kaynak dosya src / script.js bu sahip olacaktır:
module.exports = {myFunc: func};

Benim browserify komut şuna benzer olacaktır:
browserify src/script.js --standalone myBundle > dist/bundle.js

Ve istemci komut dosyam dist / client.js , paketlenmiş komut dosyasını yükleyecek
<script src="bundle.js"></script>
ve ardından gösterilen işlevi şu şekilde çağıracak:
<script>myBundle.myFunc();</script>


Sunulan işlevleri çağırmadan önce istemci komut dosyasında paket adını gerektirmeye gerek yoktur, örneğin <script src="bundle.js"></script><script>var bundled = require("myBundle"); bundled.myFunc();</script>gerekli değildir ve çalışmaz.

Aslında, tek başına mod olmadan tarayıcı tarafından paketlenen tüm işlevler gibi, gerekli işlevi de paketlenmiş komut dosyasının dışında kullanılamaz . Browserify, bazı Node işlevlerini istemci tarafında, ancak yalnızca paketlenmiş komut dosyasının kendisinde kullanmanıza izin verir ; İstemci tarafında herhangi bir yerde içe aktarabileceğiniz ve kullanabileceğiniz bağımsız bir modül oluşturmak anlamına gelmez, bu nedenle tüm bu ekstra sorunlara yalnızca paket bağlamının dışında tek bir işlevi çağırmak için gitmemiz gerekiyor.


3
Vaov! Son olarak pratik bir örnek.
N73k

1
İyi bir örnek, ancak "küresel ad alanını kirlettiği için ideal değil" otomatik olarak takip etmediği sürece, yalnızca bir işlev olması kabul edilebilir; Sadece duman ve aynalar, myBundlepencere window.myBundle.myFunc()yerine pencere nesnesine bile tutturulur . MyFunc ()
19'da

1
Uçtan uca örnekler veren kişiler için ekstra puanlar olmalıdır.
Sharud

Dokümantasyon böyle yazılmalıdır
Ellery Leung

8

Sadece cevapları okudum ve hiç kimse global değişken kapsamının kullanımından bahsetmemiş gibi görünüyor? Aynı kodu node.js'de ve tarayıcıda kullanmak istiyorsanız bu yararlıdır.

class Test
{
  constructor()
  {
  }
}
global.TestClass = Test;

Daha sonra TestClass'a her yerden erişebilirsiniz .

<script src="bundle.js"></script>
<script>
var test = new TestClass(); // Enjoy!
</script>

Not: TestClass daha sonra her yerde kullanılabilir hale gelir. Pencere değişkenini kullanmakla aynı şey.

Ek olarak, bir sınıfı genel kapsamda gösteren bir dekoratör oluşturabilirsiniz. Bu gerçekten güzel ama bir değişkenin nerede tanımlandığını takip etmeyi zorlaştırıyor.


Sizin de dediğiniz gibi, işlevin eklenmesi, ekleme ile globalaynı etkiyi üretir window, ki bu zaten thejh tarafından kapsanmıştır. Bu cevap yeni bilgi eklemiyor.
Galen Long

@GalenLong, node.js'de pencere değişkeni olmadığını unutmuş olabilirsiniz? Düğümü ve tarayıcıyı hedefleyen bazı kitaplıklar bunun yerine global kullanmak isteyebilir. Cevabım birkaç olumlu oy aldı ve henüz eksi değil, bu yüzden sizin için değilse başkaları için bilgilendirici olduğunu düşünüyorum.
DDD

Haklısın @Azarus. Sayfada iki yinelenen yanıt daha vardı ve ben de sizinkini gruba yanlışlıkla ekledim. Özür dilerim.
Galen Long

sadece burada asılı parenlerin javascript için çok kötü bir uygulama olduğunu not etmek isterim, örneğin: bu kalıbı return anahtar sözcüğüne uygulayın ve ağlamaya hazırlanın. örneğin return {}, açılış küme ayracını sonraki satıra bırakın.
Sgnl

1
@Azarus Ne demek istediğimi göstermek için bir keman oluşturdum - jsfiddle.net/cubaksot/1
Sgnl

6

Browsererify hakkında README.md'yi okuyun, --standaloneparametre veya google "browsererify umd"


19
Bu, bir cevaptan çok bir cevabı nerede bulacağınıza dair bir ipucudur.
user2314737

bu beni iki gündür aradığım çözüme götürüyor (bir require.js ortamından browsererify çıktısını nasıl kullanırım) teşekkür ederim!
Flion

2

İşlevinizin hem HTML'den hem de sunucu tarafı düğümünden kullanılabilmesi için:

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>

Çalıştırmak:

npm install uniq
browserify main.js > bundle.js

ve main.html'yi bir tarayıcıda açarken, çalıştırırken olduğu gibi aynı sonuçları almalısınız

node main.js

2

Minimum çalıştırılabilir örnek

Bu, temelde şununla aynıdır: https://stackoverflow.com/a/43215928/895245, ancak bunu kendiniz çalıştırmanıza ve kolayca yeniden üretmenize olanak tanıyan somut dosyalarla.

Bu kod şu adreste de mevcuttur: 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>

Node.js kullanımı:

#!/usr/bin/env node

const browserify_hello_world = require('./index.js');

console.log(browserify_hello_world.myfunc());

out.jsTarayıcı kullanımı için oluştur :

npx browserify --outfile out.js --standalone browserify_hello_world index.js

Hem tarayıcı hem de komut satırı beklenen çıktıyı gösterir:

1 2 3

Browserify 16.5.0, Node.js v10.15.1, Chromium 78, Ubuntu 19.10 ile test edilmiştir.


1
Bunun exports.myfunc.= myfunckısmı kesinlikle kritikti ve diğer cevaplarda gözden kaçtı.
parttimeturtle

2

gerçekten basit - tüm bu konsept,

1. alternatif - nesne "bu"

bu amaçla, "{{app_name}} tüm uygulama için yalnızca 1 komut dosyası" ve "1 işlev {{function_name}}" olduğunu varsayacağım

"this" nesnesine {{function_name}} işlevini ekleyin

function {{function_name}}(param) {}
->
this.{{function_name}} = function(param) {}

o nesnenin kullanılabilir olması için bir ad vermeniz gerekir - bunu diğerlerinin önerdiği gibi "adla bağımsız" param ekleyeceksiniz

Kullanmak eğer öyleyse "browserify" ile "watchify" Bunu kullanmak

var b = browserify({
    ...
    standalone: '{{app_name}}'
});

veya komut satırı

browserify index.js --standalone {{app_name}} > index-bundle.js

o zaman fonksiyonunuzu tarayıcıdan çağırabilirsiniz

{{app_name}}.{{function_name}}(param);
window.{{app_name}}.{{function_name}}(param);

2. alternatif - nesne "pencere"

"window" nesnesine {{function_name}} işlevini ekleyin

function {{function_name}}(param) {}
->
window.{{function_name}} = function(param) {}

o zaman fonksiyonunuzu tarayıcıdan çağırabilirsiniz

{{function_name}}(param);
window.{{function_name}}(param);

-

belki birine yardım ederim


1

Birkaç seçeneğiniz var:

  1. Eklenti browsererify-bridge'in modülleri oluşturulan bir giriş modülüne otomatik olarak aktarmasına izin verin . Bu, SDK projeleri veya dışa aktarılanları manuel olarak takip etmek zorunda olmadığınız durumlar için yararlıdır.

  2. Toplayıcı pozlama için sözde bir ad alanı modelini izleyin:

Öncelikle, klasörler üzerinde dizin aramalarından yararlanarak kitaplığınızı şu şekilde düzenleyin:

/src
--entry.js
--/helpers
--- index.js
--- someHelper.js
--/providers
--- index.js
--- someProvider.js
...

Bu şablonla girişi şu şekilde tanımlarsınız:

exports.Helpers = require('./helpers');
exports.Providers = require('./providers');
...

Index.js'nin her bir ilgili alt klasörden otomatik olarak yüklenmesinin gerekliliğine dikkat edin

Alt klasörlerinize, bu bağlamda mevcut modüllerin benzer bir bildirimini dahil edebilirsiniz:

exports.SomeHelper = require('./someHelper');

Bu kalıp gerçekten iyi ölçeklenir ve toplanan API'ye nelerin dahil edileceğinin bağlamsal (klasöre göre) izlenmesine izin verir.


-1
window.LogData =function(data){
   return unique(data);
};

Fonksiyonu basitçe şu şekilde çağırın: LogData(data)

Bu sadece jh'nin cevabında küçük bir değişiklik ama önemli olan


Bu değişiklik, soruyu soran kişinin endişeleriyle ilgisizdir ve halihazırda var olan yanıtlar göz önüne alındığında herhangi bir yeni bilgi eklemez.
Galen Long

-2

Hata ayıklama amacıyla bu satırı code.js'ye ekledim:

window.e = function(data) {eval(data);};

O zaman paketin dışında bile her şeyi çalıştırabilirim.

e("anything();");
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.