【问题标题】:Bundle custom library using webpack and lodash as dependency使用 webpack 和 lodash 作为依赖捆绑自定义库
【发布时间】:2017-12-12 12:53:07
【问题描述】:

我在这里需要帮助。 我正在捆绑一个自定义库(以示例 LibraryJS 命名,它使用 lodash 作为依赖项。

在 webpack 配置中,我将 lodash 设置为外部依赖项,如下所示:

{
   externals: {
       "lodash"
   }
}

效果很好。 但是当我想在另一个项目中使用这个库时,我得到了以下错误:“libraryjs.js:77 Uncaught ReferenceError: lodash is not defined

下面这行:

/***/ }),
/* 1 */
/***/ (function(module, exports) {

=> module.exports = lodash;

/***/ }),

事实上,我在我的项目中也使用了 lodash,所以它应该可以工作。 我做错了什么?

顺便说一句,我正在使用 gulp + browserify 来捆绑我的项目并使用 gulp + gulp-webpack 来捆绑库。

编辑:我找到了修复错误的方法,但我真的不想坚持这个修复,因为它真的......丑陋......见下文:

const lodash = require('lodash')
window.lodash = lodash; // <= The fix, ugh

感谢您的帮助!

【问题讨论】:

  • 有人可以帮忙吗? :(

标签: javascript webpack gulp lodash


【解决方案1】:

我在尝试构建库时遇到了类似的情况 - 这是我找到的解决方案。

目标: 构建一个依赖 Lodash 的库,而不在该库包中包含 Lodash。 库的使用者负责将 Lodash 提供给我们的库。

我使用文档的Authoring Libraries 部分来整理此解决方案。

具体是这两个部分:

还有一个示例项目也显示了此配置: https://github.com/webpack/webpack/tree/master/examples/externals


解决方案:

1。捆绑我们的库,不包括 lodash

// "my-lib" package.json
{
    "name": "my-lib",
    "version": "0.5.0",
    "main": "my-lib.js",
    "peerDependencies": {
        "lodash": "^4.17.5"
    },
    "devDependencies": {
        "webpack": "^4.5.0",
        "webpack-cli": "^2.0.14"
    }
}

这是我们导入 lodash 并使用它的示例库。请注意,虽然我们依赖 lodash,但它不会包含在我们的包中。

// lib-entry.js
import _ from "lodash";

export default function doubleUp(listOfNum){
    // Do something using lodash
    let result = _.flatMap(listOfNum, (i) => [i, i]);
    return result;
}

这是我们的 webpack.config.js,它捆绑了我们的库,但从捆绑包中排除了 lodash:

// "my-lib" webpack.config.js
module.exports = {
    entry: {
        'my-lib': './lib-entry.ts', 
    },
    output: {
        filename: '[name].js',

        // [1]
        libraryTarget: 'umd',

        /*
        [2]
        NOTE: until this issue is fixed: https://github.com/webpack/webpack/issues/6525
        we need to define `globalObject` in Webpack 4 to correctly build a universal library
        (i.e. node and browser compatible).
        */
        globalObject: 'this',
    },
    externals: {
        // [3]
        'lodash': {
            commonjs: 'lodash',
            commonjs2: 'lodash',
            amd: 'lodash',
            root: '_',
        },
    },
    resolve: {
        extensions: ['.js'],
    },
};

[1] 这告诉 Webpack 为不同的环境捆绑我们的库(因此它可以在通过浏览器脚本、Node CommonJS、AMD 和下游 Webpack 项目加载时工作)。注意:这是必需的,否则 [3] 中的 externals 配置将在您的包中输出不正确的 undefined 模块。

[2] Webpack 4 错误的解决方法(如果您在未来,请检查这是否仍然相关和需要)。也在这里描述:https://stackoverflow.com/a/49119917/81723

[3] 来自文档:“设置externals 选项以定义应在目标环境中解决的依赖项”。我们告诉 Webpack 从库包中排除 lodash,并且我们库的消费者负责提供它。

2。在下游应用程序中使用该库

定义一个依赖于我们的my-lib 库的应用程序:

// "my-app" package.json
{
    "name": "my-app",
    "version": "1.0.0",
    "dependencies": {
        "lodash": "^4.17.5",
        "my-lib": "^0.5.0"
    },
    "devDependencies": {
        "webpack": "^4.5.0",
        "webpack-cli": "^2.0.14"
    }
}

我们的应用程序将 lodash 导入其环境(因为我们的库需要它),然后使用我们的库:

// app-entry.js
import _ from "lodash";
import doubleUp from "my-lib";

let result = doubleUp([1, 2, 3]);
console.log(result);    // [1, 1, 2, 2, 3, 3]

这是我们应用程序的webpack.config.js

// "my-app" webpack.config.js
const path = require('path');

module.exports = {
    entry: {
        'my-app': './app-entry.ts', 
    },
    output: {
        filename: '[name].js',
    },
    resolve: {
        extensions: ['.js'],
        alias: {
            /*
            [1]
            Resolve all `lodash` requests to the same location otherwise
            we end up with two versions loaded into the bundle, one
            for `my-lib` and one for `my-app`.
            */
            lodash: path.resolve('./node_modules/lodash/index.js'),
        }
    },
};

[1] 这个alias 配置意味着任何时候Webpack 遇到require('lodash')import ... from "lodash"; 都会将其解析为磁盘上的这个模块。我发现我必须这样做以避免将多个版本的 lodash 加载到我的包中。 Webpack 包含一个用于my-app 的版本和一个用于my-lib 的版本,但这修复了它,以便两者获得相同的版本。

【讨论】:

  • lodash 应该是 peerDependency,而不是 devDependency,因为它在运行时需要,但不与 OP 的库捆绑。
  • 谢谢,我已经更新了。不确定 peerDependencies 是否已在库项目中本地安装(例如用于测试),但看起来确实如此。
  • 感谢您的解决方案。答案迟了,但读起来还是很有趣的!
  • @DanO 您应该始终在 devDependencies 中包含 peerDependencies 以进行测试。如果没有,当你测试一个需要 lodash 的模块时,它会失败,因为 lodash 不存在。
  • @cizario lodash: '_' 字符串版本依赖于全局 _ 变量的存在。 The externals docs 对 umd 库项目说“[对象] 语法用于描述使外部库可用的所有可能方式” - 因此它提供了对外部来源的更明确的控制,并且不一定依赖全局变量。一般来说,如果可能的话,最好避免使用全局变量,但这取决于您创作的特定环境。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-11
  • 2016-10-07
相关资源
最近更新 更多