如何在 Webpack 项目中导入 XML 编码的 mxGraph?

How to import XML-encoded mxGraph in a Webpack project?

上下文

作为将大型 AngularJS / RequireJS 项目迁移到 Webpack 的一部分,我检查了应用程序的不同部分并调整了依赖关系,以便一切正常。好吧,除了 mxGraph。

问题

我无法解码 XML 编码的图表。我已将问题追溯到 mxCodec.prototype.decode,它依赖于全局范围内的所有函数,使用 window[objectName] 解码 XML 名称以找到实例化对象的相关函数。

当 mxGraph 作为模块被 Webpack 加载时,对象不是全局的并且不包含在 window 对象中,因此解码不起作用。

此外,该应用程序对mxGraph的依赖性很强,并且在不同的模块中使用,因此不能只在一个地方导入。

有人知道如何让它工作吗?

预先感谢您的帮助。

配置

mxGraph 正在使用 Webpack 的 exports-loader 导入,配置与

rules: {
    test: path.resolve(__dirname, 'node_modules/mxgraph/javascript/mxClient.min.js'),
    use: [
      'exports-loader?' + [
        // handler
        'mxHandle', 'mxVertexHandler', 'mxEdgeSegmentHandler',

        // io
        'mxCodec', 'mxCodecRegistry',

        // layout
        'mxHierarchicalLayout', 'mxSwimlaneLayout',
        'mxCircleLayout', 'mxCompactTreeLayout', 'mxCompositeLayout', 'mxFastOrganicLayout', 'mxGraphLayout',
        'mxLayoutManager', 'mxParallelEdgeLayout', 'mxPartitionLayout', 'mxRadialTreeLayout', 'mxStackLayout',

        // model
        'mxCell', 'mxCellPath', 'mxGeometry', 'mxGraphModel',

        'mxClient',

        // shapes
        'mxActor', 'mxArrow', 'mxArrowConnector', 'mxCloud', 'mxConnector', 'mxCylinder', 'mxDoubleEllipse', 'mxEllipse', 'mxHexagon', 'mxLabel', 'mxLine',
        'mxMarker', 'mxPolyline', 'mxRectangleShape', 'mxRhombus', 'mxRubberband', 'mxStencil', 'mxStencilRegistry', 'mxSwimlane', 'mxText', 'mxTriangle',

        // util
        'mxConstants', 'mxEvent', 'mxUndoManager', 'mxUtils', 'mxDivResizer', 'mxImage', 'mxPoint', 'mxRectangle', 'mxLog',

        // view
        'mxGraph', 'mxEdgeStyle', 'mxCellRenderer', 'mxCellOverlay', 'mxCellState',
      ].join(','),
    ]
  }

它很丑陋,但它允许应用程序使用 import { mxArrow } from 'mx'.

的语法很好地导入 mxGraph

尝试次数

我可以按照上面描述的第一次尝试使它工作,即编写我自己的 "mxWrapper" 库。它是为如此简单的需求而设计的,但它确实有效。

基本思路:

import { 
  mxCell, mxCellPath, mxGeometry, mxGraphModel, mxCodec as _mxCodec, ...
} from 'mx';

// Overridden in our application
var mxCodec = _mxCodec;

var KNOWN_OBJECTS = {
  mxCell: mxCell,
  mxCellPath: mxCellPath,
  mxGeometry: mxGeometry,
  mxGraphModel: mxGraphModel,
  ...
  Array: Array,
  array: Array,
}

/**
 * Function: decode
 *
 * Decodes the given XML node. The optional "into"
 * argument specifies an existing object to be
 * used. If no object is given, then a new instance
 * is created using the constructor from the codec.
 *
 * The function returns the passed in object or
 * the new instance if no object was given.
 *
 * Parameters:
 *
 * node - XML node to be decoded.
 * into - Optional object to be decodec into.
 */
mxCodec.prototype.decode = function (node, into) {
  var obj = null;

  if (node != null && node.nodeType == mxConstants.NODETYPE_ELEMENT) {
    var ctor = null;

    try {
      ctor = KNOWN_OBJECTS[node.nodeName];
    }
    catch (err) {
      // ignore
    }

    var dec = mxCodecRegistry.getCodec(ctor);

    if (dec != null) {
      obj = dec.decode(this, node, into);
    }
    else {
      obj = node.cloneNode(true);
      obj.removeAttribute('as');
    }
  }

  return obj;
};


export {
  mxCell, mxCellPath, mxGeometry, mxGraphModel, ...
};

我仍然非常开放并且对更好的想法很感兴趣...