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.
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?
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.