Browserify-ブラウザのbrowserifyで生成されたファイルにバンドルされている関数を呼び出す方法


95

nodejsとbrowserifyは初めてです。私はこのリンクから始めました。

このコードを含むファイルmain.jsがあります

var unique = require('uniq');

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

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

次に、npmを使用してuniqモジュールをインストールします。

 npm install uniq

次に、browserifyコマンドを使用して、main.jsから始まるすべての必要なモジュールをbundle.jsという単一のファイルにバンドルします。

browserify main.js -o bundle.js

生成されたファイルは次のようになります。

(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ファイルをindex.htmページに含めた後、logData関数を呼び出すにはどうすればよいですか?


どこに呼びたいですか?そして、なぜあなたはそれを呼びたいのですか?
artur grzesiak 2014

2
@arturgrzesiak:この機能を、ブラウザーで実行する他のプロジェクトの1つで利用したいと考えています。
SharpCoder 2014

回答:


80

デフォルトでは、browserifyではブラウザ化されたコードの外部からモジュールにアクセスできません。ブラウザ化されたモジュールのコードを呼び出す場合は、モジュールとともにコードをブラウザ化する必要があります。その例については、http://browserify.org/を参照してください。

もちろん、次のように外部からメソッドに明示的にアクセスできるようにすることもできます。

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

次にLogData()、ページ上のどこからでも呼び出すことができます。


1
ありがとうございました。これは機能します。これは、this.functionNameを言う代わりに関数を作成するときに、window.functionNameを記述する必要があることを意味しますか?これについて他に回避策はありますか?window.functionNameを使用する理由は何ですか?
SharpCoder 2014

19
「あなたはあなたのコードをモジュールと一緒にブラウザ化することになっている」 - うーん、私がのようなことをしたい場合はどうでしょうかonclick="someFunction()"。あなたはそれがまれなユースケースであると主張することはできません!?!
BlueRaja-Danny Pflughoeft 2015

55
初心者がクライアント上で実際にBrowserifyを使用する方法については、どこにも深刻なドキュメント不足があります。
Oliver Dixon

1
ええ、ドキュメントにはこれは避けるべき設計上の決定であることを明確に記載する必要がありますが、代替案がない場合に機能させるための明確なパスを提供します(私の場合、テンプレートからのデータを使用してJSオブジェクトにデータを入力します) ... @thejhにシンプルなソリューションを指定していただきありがとうございます。;)
アレクサンドルマルティーニ

1
主要な機能をモジュールの外部で利用できるようにしたくないような状況も考えられません。これはデフォルトの動作ではないのですか?どのようなWebアプリケーションが関数を呼び出さないのですか?
サイバネティック

100

Browserifyでスタンドアロンモジュールをバンドルする際の重要な部分は、--sオプションです。ノードをmodule.exportsグローバル変数として使用して、モジュールからエクスポートしたものをすべて公開します。その後、ファイルを<script>タグに含めることができます。

これを行う必要があるのは、何らかの理由でそのグローバル変数を公開する必要がある場合のみです。私の場合、クライアントは、このBrowserifyビジネスについて心配することなく、Webページに含めることができるスタンドアロンモジュールを必要としていました。

以下--sは、引数を指定してオプションを使用する例ですmodule

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

これにより、モジュールがという名前のグローバル変数として公開されmoduleます。
ソース

更新: @fotinakisに感謝します。あなたが合格していることを確認してください--standalone your-module-name--standalone引数を取ることを忘れると、Browserifyはそれを見つけることができなかったため、空のモジュールを黙って生成する可能性があります。

これにより時間を節約できることを願っています。


2
バベル化されたES6コードをブラウザ化しようとしています。しかし、スタンドアロンオブジェクトは、ブラウザでコンソール化しようとすると空になります。モジュールなしの単純なES6コードは、スタンドアロンモードで正常に動作します。これへのポインタは?
John

@jackyrudetskyわからない。SOに質問を追加することをお勧めします。興味深い問題のように聞こえます。これに関連している可能性があります。github.com/substack/node-browserify/issues/1357
マタスVaitkevicius

1
@fotinakisこれは実際にはBrowserifyの問題でしたgithub.com/substack/node-browserify/issues/1537
John

3
IMOこれは受け入れられる答えであるはずです。グローバル関数を使用している場合は、すべての関数をウィンドウから切り離すよりも、独自の名前空間を使用する方がはるかに優れています。
VictorB 2016年

1
@VictorB Javascriptのすべてのグローバル変数はウィンドウの要素であるため、両方のメソッドが同じことを達成します(グローバル変数をウィンドウに追加)
David Lopez

37

Browserify のスタンドアロンオプションを使用した @Matas Vaitkeviciusの回答は正しいです(ウィンドウグローバル変数を使用した @thejhの回答も機能しますが、他の人が指摘したように、グローバルネームスペースを汚染するため、理想的ではありません)。スタンドアロンオプションの使用方法についてもう少し詳しく説明します。

バンドルするソーススクリプトで、module.exportsを介して呼び出す関数を公開してください。クライアントスクリプトでは、<bundle-name>。<func-name>を介してこれらの公開された関数を呼び出すことができます。次に例を示します。

私のソースファイルsrc / script.jsはこれを持っています:
module.exports = {myFunc: func};

私のbrowserifyコマンドは次のようになります。
browserify src/script.js --standalone myBundle > dist/bundle.js

そして、私のクライアントスクリプトdist / client.jsは、バンドルされたスクリプトをロードして
<script src="bundle.js"></script>
、次のように公開された関数を呼び出します。
<script>myBundle.myFunc();</script>


公開された関数を呼び出す前に、クライアントスクリプトでバンドル名を要求する必要<script src="bundle.js"></script><script>var bundled = require("myBundle"); bundled.myFunc();</script>はありません。たとえば、不要で機能しません。

実際、スタンドアロンモードなしでbrowserifyによってバンドルされたすべての関数と同様に、require関数は、バンドルされたスクリプトの外部では使用できません。Browserifyでは、一部のノード関数をクライアント側で使用できますが、バンドルされたスクリプト自体でのみ使用できます。インポートしてクライアント側のどこでも使用できるスタンドアロンモジュールを作成することを意図したものではないため、バンドルされたコンテキストの外で単一の関数を呼び出すだけでこの余分な問題すべてに対処する必要があります。


3
うわー!最後に実用的な例です。
N73k 2018

1
良い例ですが、「グローバルネームスペースを汚染するため、理想的ではない」ということが自動的に実行されない限り、それが1つの関数のみであれば、許容される場合があります。煙と鏡だけで、window.myFunc()の代わりにmyBundlewindowオブジェクトにアタッチされます window.myBundle.myFunc()
joedotnot

1
エンドツーエンドの例を示す人には、余分なポイントがあるはずです。
シャルド

これがドキュメントの書き方です
Ellery Leung

7

私は答えを読んだだけですが、グローバル変数スコープの使用について誰も言及していないようです?これは、node.jsとブラウザーで同じコードを使用する場合に便利です。

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

その後、どこからでもTestClassにアクセスできます。

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

注:その後、TestClassはどこでも使用できるようになります。これは、ウィンドウ変数を使用するのと同じです。

さらに、クラスをグローバルスコープに公開するデコレーターを作成できます。これは本当に素晴らしいことですが、変数が定義されている場所を追跡することが難しくなります。


あなたが言うように、関数を追加すると、に追加globalするのと同じ効果が得られますがwindow、これはすでにjhでカバーされていました。この答えは新しい情報を追加しません。
ガレンロング

@GalenLong多分あなたはnode.jsにウィンドウ変数がないことを忘れましたか?また、ノードとブラウザをターゲットとする一部のライブラリでは、代わりにグローバルを使用する場合があります。私の回答はいくつかの賛成票を獲得しましたが、まだマイナスではありません。そのため、あなたのためではないにしても、他の人にとっては参考になると思います。
DDD

あなたは正しい、@ Azarus。ページには他に2つの重複した回答があり、誤ってあなたの回答を束に含めました。謝罪いたします。
Galen Long

ここでぶら下がっている括弧は、JavaScriptの非常に悪い習慣です。たとえば、このパターンをreturnキーワードに適用して、泣く準備をします。たとえばreturn {}、開始中括弧を次の行にドロップします。
Sgnl 2018

1
@Azarus私は意味を示すためにフィドルを作成しました-jsfiddle.net/cubaksot/1
Sgnl

6

--standaloneパラメータまたはgoogle "browserify umd" に関するbrowserifyのREADME.mdをお読みください


19
これは、答えではなく、どこで答えを見つけるかについてのヒントです。
user2314737 14

これにより、2日間探していたソリューションが必要になりました(require.js環境からのbrowserify出力の使用方法)。ありがとうございました!
Flion 2014

2

HTMLとサーバー側ノードの両方から関数を使用できるようにするには:

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>

実行:

npm install uniq
browserify main.js > bundle.js

ブラウザーでmain.htmlを開いたときと同じ結果が得られるはずです。

node main.js

2

最小限の実行可能な例

これは基本的にhttps://stackoverflow.com/a/43215928/895245と同じですが、実行して簡単に自分で再現できる具体的なファイルが含まれています。

このコードは、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の使用:

#!/usr/bin/env node

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

console.log(browserify_hello_world.myfunc());

out.jsブラウザで使用するために生成:

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

ブラウザとコマンドラインの両方に、予想される出力が表示されます。

1 2 3

Browserify 16.5.0、Node.js v10.15.1、Chromium 78、Ubuntu 19.10でテスト済み。


1
このexports.myfunc.= myfunc部分は絶対的に重要であり、他の回答では見落としました。
parttimeturtle

1

いくつかのオプションがあります。

  1. プラグインbrowserify-bridgeにモジュールを生成されたエントリーモジュールに自動エクスポートさせます。これは、SDKプロジェクトや、エクスポートされたものに手動で追いつく必要がない状況で役立ちます。

  2. ロールアップ露出の疑似名前空間パターンに従います。

最初に、フォルダーのインデックスルックアップを利用して、ライブラリを次のように配置します。

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

このパターンでは、次のようにエントリを定義します。

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

requireがそれぞれのサブフォルダーからindex.jsを自動的にロードすることに注意してください

サブフォルダーには、そのコンテキストで使用可能なモジュールの同様のマニフェストを含めることができます。

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

このパターンは非常に適切にスケーリングされ、ロールアップされたAPIに何を含めるかをコンテキストごと(フォルダーごと)に追跡できます。


1

それは本当にシンプルです-この全体のコンセプトはラッピングについてです

1.代替-オブジェクト「これ」

この目的のために、「アプリ全体{{app_name}}に対して1つのスクリプトのみ」と「1つの関数{{function_name}}」があると仮定します

関数「{{function_name}}」をオブジェクト「this」に追加します

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

次に、使用できるようにそのオブジェクトに名前を付ける必要があります-他の人がアドバイスするように、パラメータ「スタンドアロンの名前」を追加します

あなたが使用している場合、「browserify」と「watchifyを」これを使用します

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

またはコマンドライン

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

次に、ブラウザから関数を呼び出すことができます

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

2.代替-オブジェクト「ウィンドウ」

オブジェクト「ウィンドウ」に関数{{function_name}}を追加します

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

次に、ブラウザから関数を呼び出すことができます

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

-

多分私は誰かを助けます


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

単に関数を呼び出す LogData(data)

これはjhの答えを少し変更しただけですが、重要なものです


この変更は質問者の懸念事項とは無関係であり、既存の回答から新しい情報を追加することはありません。
ガレンロング

-2

デバッグのために、次の行をcode.jsに追加しました。

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

そうすれば、バンドルの外でも何でも実行できます。

e("anything();");
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.