【问题标题】:How to exclude library files from browserify bundle如何从 browserify 包中排除库文件
【发布时间】:2016-11-06 09:48:22
【问题描述】:

我想避免将我的分发包与库文件混淆,并在 HTML 中为它们使用单​​独的脚本标签。

一种方法是这样的......

m1.js

module.exports = "first module";

m2.js

module.exports = "second module";

cnd-m1.js

var m1 =  "first module";

main.js

var m1 = this.m1 || require("./src/m1");
var m2 = require("./src/m2");

console.log(m1);
console.log(m2);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>browserify test</title>
</head>
<body>
    <script type="text/javascript" src="src/cdn-m1.js"></script>
    <script type="text/javascript" src="dist/bundle.js"></script>
</body>
</html>

例如,cdn-m1.js 可以是一个库。

我能想出让它工作的唯一方法是在 require 语句中放置一个短路回退,并在我的构建中 --ignore 文件。

在 package.json 中

  "scripts": {
    "build-ignore": "browserify ./main.js -i ./src/m1.js > ./dist/bundle.js",
    "build": "browserify ./main.js > ./dist/bundle.js"
  },

使用 build-ignore 脚本,m1 模块在包中被存根,使其更小(假设它是一个 50k 行的库)并且它回退到 cdn 提供的版本。

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);
                var f = new Error("Cannot find module '" + o + "'");
                throw f.code = "MODULE_NOT_FOUND", f
            }
            var l = n[o] = {exports: {}};
            t[o][0].call(l.exports, function(e) {
                var n = t[o][1][e];
                return s(n ? n : e)
            }, l, l.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) {
    //    browserify creates a stub for "./src/m1"
    }, {}], 

    2: [function(require, module, exports) {
        var m1 = this.m1 || require("./src/m1");
        var m2 = require("./src/m2");

        console.log(m1);
        console.log(m2);
    }, {"./src/m1": 1, "./src/m2": 3}], 

    3: [function(require, module, exports) {
        module.exports = "second module";
    }, {}]

}, {}, [2]);

有没有更好的方法来实现这一点?

【问题讨论】:

  • 尝试:browserify -u ./src/m1.js ./main.js &gt; ./dist/bundle.js 从捆绑包中排除 m1.js
  • @marcel -u 导致模块定义对象为{"./src/m1": undefined, "./src/m2": 2},这会导致错误
  • 好的。您可以为m1.js 创建一个单独的包,然后在“普通”包中引用它。这样,您的 HTML 文件中也会有单独的 &lt;script&gt;-Tags。
  • 是的,这一直是我的目标:说起来容易做起来难,但一如既往......当你知道如何做时,这很容易。似乎有很多排列,我只需要找到正确的排列。不幸的是,它不像手册中宣传的那样有效,所以我花了一段时间......

标签: node.js browserify


【解决方案1】:

答案是使用browserify-shim 为了弄清楚这一点,我创建了一个稍微复杂一点的场景,其中包含一个带有两个子依赖项(m1.jsm2.js)的假 lib 文件(main-a.js),并使应用程序(main-b.js)依赖于假库。

我将main-a.js 滚动到一个独立的包中,该包暴露了一个名为fakeLib 的全局变量,并在 index.html 中使用了一个单独的脚本标记来加载它。

然后我使用browserify-shim 构建应用程序的同构版本,该版本需要在节点中使用main-a.js,但在浏览器中使用window.fakeLib

使用这个应用程序:

/**
 * main-b.js
 */
require("./src/main-a").say();

这不起作用:

  "browserify-shim": {
    "./src/main-a": "fakeLib"
  },

但确实如此:

  "browserify-shim": {
    "./src/main-a": "global:fakeLib"
  },

你必须使用这个global: 我认为这可能是由于 browserify 中的一个错误,因为它不同意 browserify handbook


index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>browserify test</title>
</head>
<body>
    <div style="white-space: pre;" id="output"></div>
    <script type="text/javascript" src="dist/main-a-lib-pretty.js"></script>
    <script type="text/javascript" src="dist/bundle-B.js"></script>
</body>
</html>

假图书馆...

/**
 * m1.js
 */
exports.say = "first module";

.

/**
 * m2.js
 */
exports.say = "second module";

.

/**
 * main-a.js
 */
var m1 = require("./src/m1");
var m2 = require("./src/m2");

exports.say = function() {
    function op(t){
        this.document
            ? document.getElementById("output").textContent += t + "\n"
            : console.log(t);
    }
    op(m1.say);
    op(m2.say);
};

package.json 用于假库。这使得一个独立的包暴露了 fakeLib

{
  "name": "browserify-nightmare",
  "version": "1.0.0",
  "main": "main-a.js",
  "dependencies": {
  },
  "devDependencies": {
    "browserify-shim": "^3.8.12"
  },
  "scripts": {
    "build-lib": "browserify ./main-a.js -s fakeLib > ../dist/main-a-lib-pretty.js",
    "build-lib-pretty": "browserify ./main-a.js -s fakeLib | js-beautify > ../dist/main-a-lib-pretty.js"
  },
  "author": "cool.blue",
  "license": "MIT",
  "description": ""
}

假应用

/**
 * main-b.js
 */
require("./src/main-a").say();

package.json 在浏览器中使用browserify-shimrequire("./src/main-a") 返回fakeLib,但在节点中的行为类似于普通的CommonJS 模块。

{
  "name": "browserify-nightmare",
  "version": "1.0.0",
  "main": "main-b.js",

  "browserify-shim": {
    "./src/main-a": "global:fakeLib"
  },
  "browserify": {
    "transform": "browserify-shim"
  },
  "devDependencies": {
    "browserify-shim": "^3.8.12"
  },

  "scripts": {
    "build-B": "browserify ./main-b.js > ./dist/bundle-B.js",
    "build-B-pretty": "browserify ./main-b.js | js-beautify > ./dist/bundle-B.js"
  },
  "author": "cool.blue",
  "license": "MIT",
  "description": ""
}

this answer 非常有帮助

git repo

【讨论】:

    【解决方案2】:

    首先你必须为m1.js创建一个单独的包:

    browserify -r ./src/m1.js > ./dist/m1_bundle.js
    

    然后简单地创建“正常”包并引用创建的m1_bundle.js

    browserify -x m1 -d ./main.js > ./dist/bundle.js
    

    现在您必须将这两个捆绑包包含到您的 HTML 文件中。

    注意:您必须在 HTML 中的“普通”bundle.js 之前包含 m1_bundle.js

    更多详情请查看我的另一个answer。我在那里解释,如何做同样的事情,但使用node_modules 而不是自己的库。

    【讨论】:

    • 感谢您的解释。顺便说一句,除非您使用browserify -x ./src/m1.js,否则它不起作用。您也可以使用browserify -r ./src/m1.js:m1require("m1") 而不是require("./src/m1.js"),但它不再是同构的,您不能使用require("./src/m1"),否则它也会中断。它似乎很脆。我错过了什么吗?
    • 话虽如此,但这无济于事,因为我想从带有脚本标签的 CDN 获取库。您的方法假定您将提供 lib,因此可以将其捆绑为导出 require 函数的 CommonJS 样式模块。不幸的是,这不是我要解决的问题。起点是window.m1
    猜你喜欢
    • 2015-07-11
    • 1970-01-01
    • 2013-01-05
    • 1970-01-01
    • 2018-12-22
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多