Browserify - 如何调用浏览器中通过browserify生成的文件中捆绑的功能

时间:2014-04-25 14:35:01

标签: node.js npm browserify

我是nodejs和browserify的新手。我从这个link开始。

我有包含此代码的文件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函数?

12 个答案:

答案 0 :(得分:84)

使用Browserify捆绑独立模块的关键部分是--s选项。它使用节点的module.exports作为全局变量公开从模块导出的任何内容。然后,该文件可以包含在<script>标记中。

如果出于某种原因需要公开全局变量,则只需执行此操作。在我的情况下,客户端需要一个可以包含在网页中的独立模块,而无需担心这个Browserify业务。

以下是我们使用--s参数并使用module参数的示例:

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

这会将我们的模块公开为名为module的全局变量 Source

<强>更新 感谢@fotinakis。确保您已通过--standalone your-module-name。如果您忘记了--standalone接受了争论,那么Browserify可能会静默生成一个空模块,因为它无法找到它。

希望这可以节省你一些时间。

答案 1 :(得分:65)

默认情况下,browserify不允许您从浏览器化代码外部访问模块 - 如果您想在浏览器模块中调用代码,则应该将代码与模块一起浏览。有关此示例,请参阅http://browserify.org/

当然,您还可以明确地从外部访问您的方法,如下所示:

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

然后,您可以从页面上的任何其他位置拨打LogData()

答案 2 :(得分:20)

@Matas Vaitkevicius的answer with Browserify's standalone option是正确的(@ thejh的answer using the window global variable也可以,但正如其他人所说,它会污染全局命名空间,因此它并不理想)。我想添加一些关于如何使用独立选项的更多细节。

在要捆绑的源脚本中,确保通过module.exports公开要调用的函数。在客户端脚本中,您可以通过&lt; bundle-name&gt;。&lt; func-name&gt; 调用这些公开的函数。这是一个例子:

我的源文件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> 不是必需的,也不会起作用。

实际上,就像浏览器没有独立模式捆绑的所有功能一样,require function won't be available outside of the bundled script。 Browserify允许您在客户端使用某些Node功能,但仅在捆绑脚本本身;它并不意味着创建一个独立的模块,您可以在客户端的任何地方导入和使用,这就是为什么我们不得不在捆绑的上下文之外调用单个函数来解决所有这些问题。

答案 3 :(得分:7)

阅读browserify关于--standalone参数的README.md 或google&#34; browserify umd&#34;

答案 4 :(得分:5)

我刚读完答案,似乎没有人提到使用全局变量范围?如果您想在node.js和浏览器中使用相同的代码,这将非常有用。

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

然后您可以随时随地访问 TestClass

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

注意:然后,TestClass随处可用。这与使用窗口变量相同。

此外,您可以创建一个将类公开给全局范围的装饰器。这非常好,但很难跟踪变量的定义位置。

答案 5 :(得分:1)

您有几个选择:

  1. 让插件browserify-bridge将模块自动导出到生成的输入模块。这对于SDK项目或您不必手动跟上导出内容的情况很有用。

  2. 遵循伪命名空间模式进行汇总曝光:

  3. 首先,像这样安排你的图书馆,利用文件夹上的索引查找:

    /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中包含的内容。

答案 6 :(得分:1)

要通过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

答案 7 :(得分:0)

即使有这些答案,我也需要花点时间找出并理解这个问题

这很简单-它是关于包装的

为此,我假设整个应用程序{{app_name}}仅有1个脚本

1个替代

向对象“ this”添加功能

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

然后您必须命名该对象以使其可用-您将像其他建议的那样添加“带有名称的独立对象”参数

因此,如果您使用"watchify" with "browserify",请使用此

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

或命令行

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

然后您可以从浏览器调用函数

app_name.somefunction(param);
window.app_name.somefunction(param);

2个替代

向对象“窗口”添加功能

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

然后您可以从浏览器调用函数

somefunction(param);
window.somefunction(param);

-

也许我可以帮助某人

答案 8 :(得分:0)

最小的可运行示例

这与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进行了测试。

答案 9 :(得分:0)

您也可以像这样从 html 文件中调用您的函数:

main.js:(将在 bundle.js 中)

window.onload = function () {
    document.getElementById('build-file')
        .addEventListener('click', buildFile)

}
function buildFile() {
 ...
}

index.html:

<button id="build-file"">Build file</button>

答案 10 :(得分:-1)

出于调试目的,我将此行添加到我的code.js:

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

然后我甚至可以在捆绑之外运行任何东西。

e("anything();");

答案 11 :(得分:-1)

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

只需LogData(data)

即可调用此功能

这只是对thejh's答案的轻微修改,但重要的是