2

I am using a very large library in my spfx solution and I would like to not only share it among webparts within this app but share it across any other webparts that might be using this library.

What I know

  • I know that you can include external libraries such as jquery and some libraries that have typings separate from their npm package.
  • I know that even if I put a reference to an external library in the externals section it won't actually pull down the library if I don't import it anywhere in my code.
  • I understand the current examples in the documentation. I managed to successfully use moment-timezone which is great.

Problem I am having

I am trying to use the DevExtreme and devextreme-react libraries. This library is very large so I want to include it once from a cdn when a webpart is requesting it and continue using the same script with each additional webpart instance. The problem is that the library comes with typings included in it. It is in a subfolder bundles/dx.all.d.ts instead of in its own package. It also has multiple files you can include instead of including the entire library. In addition the devextreme-react is depending on the devextreme library so it is also including files from devextreme.

The project either doesn't load the external libraries because I don't include them, or things fail to compile because I am not importing it properly..? maybe?

My question is how do I exclude the library, add it to externals configuration, import it into my project files with typings and still have my project compile?

Community
  • 1
  • 1
Rudy Garcia
  • 522
  • 1
  • 6
  • 19
  • Without any source code or reproducible repo, it is hard for anyone to figure out what's going on. – Mrchief Oct 31 '18 at 23:17
  • Well it is tagged with spfx. You only have to run the yo generator and try to add devextreme. I guess if you don't know anything about spfx this is true, but you could probably not help me with my problem if that is the case either. I could probably edit the question itself to be more clear. – Rudy Garcia Nov 01 '18 at 17:19

2 Answers2

0

So I found a potential solution, of course the only problem is I have to stop using devextreme-react and use just plain jquery.

Basically if I put in the config this:

"jquery": {
  "path": "https://code.jquery.com/jquery-2.1.1.min.js",
  "globalName": "jQuery"
},
"devextreme/bundles/dx.all": {
  "path": "https://cdn3.devexpress.com/jslib/18.1.6/js/dx.all.js",
  "globalName": "DevExpress",
  "globalDependencies": ["jquery"]
}

And then anywhere that requires a devextreme component I would have to create a wrapper and import devextreme like this:

import * as React from 'react';
import * as $ from 'jquery';
import DevExpress from 'devextreme/bundles/dx.all'; DevExpress;

export default class DxButton extends React.Component<DevExpress.ui.dxButtonOptions> {
    private el: HTMLElement;
    private $el: JQuery<HTMLElement>;
    public constructor(props: DevExpress.ui.dxButtonOptions) {
        super(props);
    }
    public componentDidMount() {
        this.$el = $(this.el);
        (this.$el as any).dxButton({
            ...this.props as any
        } as DevExpress.ui.dxButtonOptions);
    }

    public componentWillUnmount() {
        (this.$el as any).dxButton('dispose');
        this.$el.remove();
    }

    public render(): React.ReactElement<DevExpress.ui.dxButtonOptions> {
        return <div ref={el => this.el = el} />;
    }
}

The reason I can't use devextreme-react is because it uses the modules of devextreme and forces the package to be bundled no matter what.

Not the ideal solution but seems like the only possible way to do it in the end.

Rudy Garcia
  • 522
  • 1
  • 6
  • 19
0

Be aware to not use imports from the devextreme-react as straight forward.

//wrong import 
 import { TextBox } from 'devextreme-react';

You must specify import for each component you have.

//Correct import
import { TextBox } from 'devextreme-react/text-box';