繁体   English   中英

Webpack 代码拆分会破坏块之间的 instanceof

[英]Webpack code splitting breaks instanceof between chunks

tl:博士;

class ModuleInBundleA extends ModuleInBundleC { … }

window.moduleInBundleB.foo(new ModuleInBundleA())
class ModuleInBundleB { 
    public foo(bar: ModuleInBundleA|ModuleInBundleC|number) {
        if (bar instanceof ModuleInBundleA || bar instanceof ModuleInBundleC) { 
            // always false
            … 
        }
    }
}

细节:

我正在尝试在主要具有旧代码库的项目上开始使用 TypeScript + Webpack 4.41.6。 基本上我想将几个小模块打包到包中,以便在不将整个项目移动到新的 js 堆栈的情况下进行软迁移。

我发现 Webpack 可以通过代码拆分来做到这一点,并通过一些配置将共享代码打包成自己的包。 但是,我无法真正控制每个包中的内容,除非我单独构建每个包然后只共享类型,使用我自己的模块作为外部库,这有点令人沮丧。

也许在这一点上,您可以说我已经做错了,我想听听我如何实现使用捆绑包作为普通 javascript 的目标(自己控制延迟/异步并使用自己的脚本标记作为好吧),而且我真的不想将所有内容打包为具有自己的配置、类型导出等的独立包。

希望你有整体背景。 更接近正题。

我有以下功能,它被捆绑到它自己的名为modal-manager.js的块中。

public showModal (modal: ModalFilter|AbstractModal|number) {
    let modalId: number;

    console.log(modal);
    console.log(typeof modal);
    console.log(modal instanceof ModalFilter);
    console.log(modal instanceof AbstractModal);

    if (modal instanceof AbstractModal) {
        modalId = modal.getId();
    } else {
        modalId = modal;
    }
    ...
};

(最初它没有ModalFilter因为ModalFilter继承了AbstractModal但我为了演示目的包含了它)

抽象模态会自动捆绑到modal-utils.js因为它在模块之间共享。

接下来,我有另一个名为filter.js大包。 这个字面上创建了 ModalFilter const modalFilter = new ModalFilter(...)实例。 我认为这是提到向全局window变量声明的 modalFilter 实例的工作。 问题是filter.js调用modal.js代码(通过window.modalFilter.showModal(modalFilter) )没有任何问题,但我看到 console.log 的以下结果:

ModalFilter {shown: false, loading: false, closing: false, html: init(1), id: 0, …}
modal.bundle.23e2a2cb.js:264 object
modal.bundle.23e2a2cb.js:265 false
modal.bundle.23e2a2cb.js:266 false

我禁用了映射以获取更多代码并看到:

ModalManager.prototype.showModal = function (modal) {
    var modalId;
    console.log(modal);
    console.log(typeof modal);
    console.log(modal instanceof _builder_component_modal_filter__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"]);
    console.log(modal instanceof _modal_abstract__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"]);
    if (modal instanceof _modal_abstract__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"]) {
        modalId = modal.getId();
    }
    else {
        modalId = modal;
    }
    this.modals[modalId].show();
    this.scrollLock(modalId);
};

根据我对 javascript 工作原理的理解,instanceof 应该检查对象创建器函数。 由于代码块是分开的( modal.jsmodal-utils.js没有相同的代码),creator 函数应该是相同的。 然而,更多地了解细节,我发现webpackJsonp可能非常棘手,并且从某种独立的环境中调用它们,但它仍然应该是调用FilterModalAbstractModal的相同环境。 我相信ModalManager可以有自己的环境。 但是调用的代码是 100% 相同的。 webpackJsonp捆绑数组可能是问题的根源吗? 如果是这样,我怎样才能避免这种情况并使modal.js包理解filter.js和其他人都从modal-utils.js引用相同的AbstractModal

如果我做错了,是否有一种简单的方法可以开始捆绑使用 TypeScript 和 Webpack(或其他工具)构建的小型高效脚本? 另外,我看到了 Webpack 的externals功能,但还没有弄清楚如何在我的情况下使用它。 一般来说,除了instanceof问题,我对当前设置没问题。 我想避免多次构建的原因是我可能会有几十个较小的包,它们在不同的模块之间共享,并且每个包都有几十个 npm 包似乎过多。

以此为序; 我不知道您在问题的instanceOf部分面临的确切问题的答案。 这是针对“你是怎么做到的”部分的。


大约 4 周前,我们还使用大约 1-2 个.js文件从.js更改为.ts实现。 显然,我们不想一次性将这些全部迁移到.ts因为工作量太大。

我们最终做的是识别需要在特定页面上运行的.js脚本,并将它们作为入口文件添加到 webpack 中。 然后对于所有其他支持脚本,如果我们需要在新的.ts文件中包含它们的内容,我们实际上为它们创建了一个大的索引/桶文件,将它们导入,然后 webpack 会自动将它们包含在正确的范围中相应的.ts文件。


这看起来像什么?

legacy.index.ts:对于我们想要在.ts以任何方式引用的每个支持.js文件。

var someFile_js = require("someFile.js");
export { someFile_js };

这允许我们在.ts文件中导入和使用它:

import { someFile_js } from './legacy.index';


回复@tonix 要加载定义的列表:

配置文件

const SITE_INDEX = require('./path-to-js-file/list.js') module.exports = { entry: SITE_INDEX ... }

列表.js

 { "filename1": "./some-path/filename1.js" "filename2": "./some-path/filename2.ts" }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM