【问题标题】:How to do cytoscape initialization with Typescript?如何使用 Typescript 进行 cytoscape 初始化?
【发布时间】:2017-11-16 18:50:29
【问题描述】:

我使用 Typescript 构建了一个 React 组件,它使用 cytoscape(及其 types)作为无头模型。我的目标是创建一个 NPM 包,以便我可以直接将其导入其他项目。

我的图书馆:

  1. 当我将 index.html 中的 cytoscape.js 作为静态资产导入时工作
  2. 当我 npm install 我的组件在一个新的 es6 应用程序中时不会: Uncaught ReferenceError: cytoscape is not defined at new WbsLayout。尽管在安装我的组件时 cytoscape 会自动安装在 node_modules 中。

打字稿源

WbsLayout.tsx:

export class WbsLayout  {
    //...
    public cy: Cy.Core;
    constructor(graph: any, Options?: Options) {           
        this.cy = cytoscape({ // <-- Works or fails, see cases #1 and #2 explained above
            headless: true,
            elements: graph
        });
        //...
    }
    //...
}

请注意,我在组件源中的任何地方都没有 import cytoscape from 'cytoscape'(或任何类似方式),因为我似乎没有任何东西,因为 Typescript 和 cytoscape 的类型定义方式,我不需要它使我的组件与在 html 中导入的 cytoscape 一起工作。也许这是一个 NPN 包的问题......

Wbs.tsx:

一个接收 prop WbsLayout 的简单 React 组件。

cytoscape 的分型(仅相关部分)

declare namespace Cy {
    //...
    interface Core { }

    //...
    interface Static {
        (options?: Cy.CytoscapeOptions): Core;
        (extensionName: string, foo: string, bar: any): Core;
        version: string;
    }
}

declare module "cytoscape" {
    export = cytoscape;
}
declare var cytoscape: Cy.Static;

Webpack 2 配置

Wbs.tsx、WbsLayout.tsx 和其他人使用 Webpack 2 捆绑到 @nodeject/wbs-react:

module.exports = {
  entry: {
    'test/index': './src/test.tsx',
    'dist/index': './src/index.tsx'
  },

  output: {
    filename: "./[name].js",
    libraryTarget: 'umd',
    library: 'wbs-react',
    umdNamedDefine: true
  },

  devtool: "source-map",

  resolve: {
    extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
  },

  node: {
    fs: "empty",
    child_process: "empty"
  },

  module: {
    rules: [    
      {
        enforce: 'pre',
        test: /\.js$/,
        loader: "source-map-loader"
      },
           
      {
        test: /\.tsx?$/,
        loader: "ts-loader"
      },
      {
        test: /\.css$/,
        loader: "style-loader!css-loader"
      },
    ]
  },
  
  externals: {
    "react": {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      amd: 'react'
    },

    "react-dom": {
      root: 'ReactDOM',
      commonjs2: 'react-dom',
      commonjs: 'react-dom',
      amd: 'react-dom'
    },

    "cytoscape": {
      root: 'Cy',
      commonjs2: 'cytoscape',
      commonjs: 'cytoscape',
      amd: 'cytoscape'
    },

    "chai": {
      root: 'chai',
      commonjs2: 'chai',
      commonjs: 'chai',
      amd: 'chai'
    }
  }
};

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./temp/",
    "sourceMap": false,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es2015",
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node",
    "jsx": "react"
  },
  "exclude": [
    "node_modules",
    "dist",
    "temp",
    "test"
  ]
}

新的 es6 应用源

import React from 'react';
import ReactDOM from 'react-dom';
import {Wbs, WbsLayout} from '@nodeject/wbs-react';

let graph = {
  nodes: [
    { data: { id: '1' } },
    { data: { id: '1.1', parent: '1' } }
  ],
  edges: [
    { data: { id: 'e1', source: '1', target: '1.1' } }
  ]
};

layout: new WbsLayout(graph); // <-- Fails here (case #2)

ReactDOM.render(<Wbs layout={layout}/>, document.querySelector('#wbs_example'));

【问题讨论】:

  • 看到打字确实导出了一个模块,import * as cytoscape from "cytoscape"; 应该可以工作。
  • 感谢您的回答。我之前曾尝试在WbsLayout.tsx 中添加它,但在同一位置出现Uncaught TypeError: cytoscape is not a function 错误(this.cy = cytoscape({ .....})。
  • 您是否尝试过将您的module 目标更改为es2015,将您的moduleResolution 选项更改为node 并将allowSyntheticDefaultImports 选项设置为true?
  • 嘿@DanielRosenwasser,又是同样的错误。这可能与webpack有关吗?我阅读了一些选项,例如 library=your-app-name 和其他选项,但我也没有成功。

标签: typescript npm ecmascript-6 webpack-2 cytoscape.js


【解决方案1】:

您是否尝试将其导入为 ..

const cytoscape = require('cytoscape');

如果是,那么您也可以发布您的tsconfig.json。

【讨论】:

  • 你的意思是import cytoscape = require('cytoscape')?同样的错误,它甚至不再作为静态资产工作:cytoscape is not a function。我将编辑我的第一篇文章以添加 tsconfig.json
【解决方案2】:

在注意到如果我从 webpack 的外部组件中完全删除 cytoscape 后,我找到了答案,它可以工作。这是我需要做的:

"cytoscape": {
  root: 'Cy',
  commonjs2: 'cytoscape',
  commonjs: 'cytoscape',
  amd: 'cytoscape'
 }

必须是:

"cytoscape": {
  root: 'cytoscape', <--------
  commonjs2: 'cytoscape',
  commonjs: 'cytoscape',
  amd: 'cytoscape'
 }

【讨论】:

    猜你喜欢
    • 2020-02-13
    • 2017-11-02
    • 1970-01-01
    • 2018-06-22
    • 2015-04-24
    • 2014-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多