当d3.js迁移到版本4时,对Api进行了重大重写,并对模块化包装进行了更改.

我不想升级到D3.js的版本4,但我必须使用Vite和D3.js的版本3重写我的项目的Reaction/Redux Web应用程序部分,而且它对global的使用与Vite使用的JavaScript模块系统不兼容.

我得到的错误是没有定义"global",而D3.js的版本3使用了"global".

这就是它所说的node_modules/d3/index.js (index.js:4:13)

var globals = {};

// Stash old global.
if ("d3" in global) globals.d3 = global.d3;

module.exports = require("./d3");

// Restore old global.
if ("d3" in globals) global.d3 = globals.d3; else delete global.d3;

因此,我在d3/index.js文件中注释掉了对global的引用,看看会发生什么,我得到了一个类似的属性,"Cannot Read Properties of unfined(Document)"这是源代码

var d3_document = this.document;
function d3_documentElement(node) {
  return node && (node.ownerDocument || node.document || node).documentElement;
}

我猜这与版本4中向模块化d3的转变有关,但D3.js版本3.5.5在我不与Vite.js一起使用时工作得很好.例如,如果我只是将其放在index.html文件中并使用http服务器运行它.

问:有没有办法对Vite.js进行配置,使其与D3.js版本3.5.5兼容?或者,我可以更改D3.js版本3.5.5的源代码,使其在Vite.js上运行吗?

更新

我将此代码添加到了Vite.config.js中

  define: {
    global: {},
    document: {}
  }

现在,VITE投诉无法在#<Window>.上设置属性document

3env.ts:24 Uncaught TypeError: Cannot set property document of #<Window> which has only a getter

StackOverflow 个问题有帮助,但它不能解释什么时候"文档"是未定义的,它不能在窗口上"设置".

可能无关紧要,但这里是unpkg.com上的d3版本3.5.5的源代码 d3 version 3.5.5`

这是unpkg.com上d3版本4的源代码 d3 version 4

推荐答案

The main issue is that node_modules/d3/d3.js file uses the this keyword.
Specifically it reads this.document, instead of window.document or simply directly accessing the global document variable.
So the actual question should be: Is it possible to define this for d3 in Vite.

您看到,当您使用http服务器测试时,d3工作得很好,您可以从index.html文件加载脚本.

It worked because you loaded it using <script type="text/javascript">.
This is because in old script files the default value for top-level this is window.

如果您try 使用<script type="module">来加载它,就像vite所做的那样,它不会起作用,因为对于模块脚本,顶级this变量是undefined.


Vite确实有一个通过在vite.config.js中定义替换来替换变量的选项,但由于其实现方式的原因,它有很多限制:

Entries will be defined as globals during dev and statically replaced during build.

在dev模式下,这对我们来说毫无用处,因为您不能将this定义为全局变量.隐含地,我们也不能定义this.document的替代品.

During build we have a similar problem for a different reason. Vite can replace this, but only in the top level. Unfortunately d3 is wrapped in a function(){} and Vite does not want to replace this inside of functions, since this is seen as a local variable and Vite doesn't want to replace local variables.
It doesn't matter if you tried defining this:'window' or if you try being specific by defining 'this.document':'window.document'.

我在文档中没有发现任何可能对我们有用的东西,所以不太可能使用VITE配置来解决这个问题.

我猜他们不想与官方违约背道而驰,所以他们没有为这一点设立选项.

不幸的是,this不是你可以自己填充的东西.


这只给我们留下了我昨天在 comments 中提到的解决方案,即编辑d3源代码.至少这一变化很小.

First copy node_modules/d3/d3.js file to your source folder.
(you should never edit files in node_modules since npm or yarn might overwrite those changes; and pnpm even uses symbolic links, so it shared the same file for all projects)

然后,您必须将第一行和最后一行替换为:

!function() {
  // ...
}()

致:

(function() {
  // ...
}).call(window)

当然,您必须替换您的导入语句来导入这个新文件,而不是从NODE_MODULES导入d3.


As for node_modules/d3/index.js you can actually skip that file instead of adding polyfills for it.
In later patches like 3.5.17 it was even removed.
All it does is handle the global d3 variable.

Javascript相关问答推荐

如何修复内容安全策略指令脚本-SRC自身错误?

具有相同参数的JS类

如何才能拥有在jQuery终端中执行命令的链接?

如何用显示网格平滑地将元素从一个地方移动到另一个地方?

在Vite React库中添加子模块路径

更改JSON中使用AJAX返回的图像的路径

html + java script!需要帮助来了解为什么我得到(无效的用户名或密码)

如何从网站www.example.com获取表与Cheerio谷歌应用程序脚本

如何在Angular17 APP中全局设置AXIOS

如何强制Sphinx中的自定义js/css文件始终加载更改而不缓存?

使用Google API无法进行Web抓取

为什么这个.add.group({})在教程中运行得很好,但在我的游戏中就不行了?

为什么我的按钮没有从&q;1更改为&q;X&q;?

触发异步函数后不能显示数据

如何使用Astro优化大图像?

在渲染turbo流之后滚动到元素

如果NetSuite中为空,则限制筛选

TabNavigator和StackNavigator之间的Reaction Native中的导航问题

设置复选框根据选中状态输入选中值

暂停后只有一次旋转JS