如何使用Webpack和ES6处理CommonJS模块的依赖关系?

6
我正在使用Laravel开发一个项目,它默认使用webpack来捆绑其资产。在其中,我有一个依赖于一个包的依赖项,该包反过来又依赖于lodash和deepdash。
由于deepdash作为lodash的mixin提供,因此根据文档,使用它的方式如下:
// load Lodash if you need it
const _ = require('lodash');
//mixin all the methods into Lodash object
require('deepdash')(_);

或者,如果你想使用ES6语法(至少这是我的理解),它将被翻译成:

import _ from 'lodash';
import deepdash from 'deepdash';

deepdash(_);

我已经这样做了,现在正在尝试使用webpack创建一个捆绑包以在浏览器中使用。我的问题是,由于某种原因,webpack似乎用一些“__webpack_require__”的魔法功能替换了lodash的导入,导致lodash不再是一个函数,浏览器会显示以下错误信息:

enter image description here

为了更好地展示我的问题,我创建了一个演示github repo,只尝试webpack deepdash和lodash: ArSn/webpack-deepdash 这是浏览器抱怨的行:https://github.com/ArSn/webpack-deepdash/blob/master/dist/main.js#L17219

我尝试了很多关于添加Babel配置的方法,最好的方案似乎是使用插件babel-plugin-transform-commonjs-es2015-modules。我试过了,结果仍然完全一样。

我感觉自己要么对情况有深刻的误解,要么只是缺少一个微小的东西。但是,我无论如何都想不出哪一个是什么以及是什么。

附注:

  • 我知道deepdash也有一个ES6版本,显然当同时使用这两个版本时,webpack机制可以正常工作(在deepdash的github问题回应中已经说明了这一点),但我使用的依赖项没有使用那些版本。此外,我真的看不出来(或者说理解?)为什么首先要有一个专门的ES6版本。
  • 完全相同的代码(使用lodash的这种方式)在node.js上执行时可以正常工作,在那里它在被webpack打包之前并没有被打包。我应该提到这里使用了require语法。

import * as deepdash from 'deepdash'; 但我见过一些打包工具将全局对象转换为对象,即使 module.exports 是一个函数。 - Patrick Roberts
导致几乎完全相同的错误,只是在“不是函数”之前的(...)现在不显示 - ArSeN
你正在使用哪个版本?我在一个包含“webpack”:“^4.16.4”,“webpack-cli”:“^3.1.0”的样板文件上遇到了同样的问题。 - Maiya
在示例存储库(重现问题)中,我正在使用webpack 4.40.2和webpack-cli 3.3.9 - 应该都非常最新。我尚未在webpack项目上找到已报告的问题,但也许我只是错过了它(或者是第一个发现它的人)。 - ArSeN
你能详细说明这里的解决方案是什么吗?下面madflow的答案似乎非常棒(而且还能工作,耶!) - ArSeN
显示剩余2条评论
1个回答

4
指向 deepdash 主模块对我来说是可行的,当我从 deepdash 网站运行其中一个示例时:
import _ from 'lodash';
import deepdash from 'deepdash/deepdash';

deepdash(_);

Webpack 使用 browser 入口作为默认值:

  "main": "deepdash.js",
  "module": "es/standalone.js",
  "browser": "browser/deepdash.min.js",

这对于Webpack和静态导入是不起作用的,因为没有真正的“导出”。此外,通常这些条目不指向缩小版本。这些通常仅用于CDN用例,而不用于打包程序。相反,“deepdash/deepdash.js”导出装饰器函数。deepdash-es构建基本上做同样的事情,只是它使用es6导出。也许这是树摇可以开箱即用的方式。不确定那个...为了规避“浏览器”问题,deepdash的作者可以简单地修改它以使用“deepdash.js”或将其删除:

https://github.com/defunctzombie/package-browser-field-spec

如果你的模块是纯JavaScript并且可以在客户端和服务器环境中运行,那么你不需要一个浏览器字段。

这个运行得非常好!您能详细介绍一下为什么这是必要的,甚至更好的是说一下deepdash需要改变什么来避免破坏当前接口,但也能以“标准方式”import deepdash from 'deepdash'工作吗?deepdash的维护者似乎非常乐意进行更改以使其正常工作,因此我很想在deepdash上打开一个拉取请求,无论如何我都会接受您的答案。 - ArSeN
我更新了我的回答。阅读这个内容很有趣。当涉及到捆绑的内部机制时,我并不是真正的专家。 - madflow
你让我不再度过那些试图弄明白问题却屡屡失败的夜晚,非常感谢! - ArSeN
嘿,谢谢你的帮助。你在 Github 上的昵称也是这个吗?我想把你加入贡献者列表。 - Yuri Gor
我在 Github 上使用相同的用户名。 - madflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接