Skip to content

Commit eace279

Browse files
Merge pull request #60 from bollwyvl/perf/async-load-again
Re-apply load performance and bundle size/content changes
2 parents 67fd5eb + 2129fda commit eace279

File tree

6 files changed

+77
-16
lines changed

6 files changed

+77
-16
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ lib/
33
node_modules/
44
*.egg-info/
55
.ipynb_checkpoints
6-
tsconfig.tsbuildinfo
6+
tsconfig.tsbuildinfo
7+
*.tgz

binder/environment.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
name: jupyterlab-drawio
2+
23
channels:
3-
- conda-forge
4+
- conda-forge
5+
46
dependencies:
5-
- jupyterlab=1.0
7+
- jupyterlab >=2,<3.0.0a0
8+
- nodejs >=10

binder/postBuild

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1-
jupyter labextension install jupyterlab-drawio
1+
#!/usr/bin/env bash
2+
set -eux
3+
npm install
4+
npm run build
5+
npm pack
6+
jupyter labextension install ./jupyterlab-drawio-*.tgz --no-build --debug
7+
jupyter lab build --dev-build=False --minimize=True --debug
8+
jupyter labextension list

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@
2727
"scripts": {
2828
"build": "node scripts/copyfiles.js && tsc",
2929
"clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
30-
"watch": "tsc -w",
31-
"prepublish": "npm run clean && npm run build"
30+
"watch": "tsc -w"
3231
},
3332
"dependencies": {
3433
"@jupyterlab/application": "^2.0.0",

scripts/copyfiles.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
var fs = require('fs-extra');
2-
fs.copySync('src/mxgraph/', 'lib/mxgraph/');
2+
3+
fs.copySync('src/mxgraph/javascript/src/', 'lib/mxgraph/javascript/src/');
4+
fs.copySync('src/mxgraph/javascript/examples/grapheditor/www/', 'lib/mxgraph/javascript/examples/grapheditor/www/');
35
// fs.copySync('src/mxgraph/javascript/examples/grapheditor/www/resources/grapheditor.txt',
46
// 'lib/mxgraph/javascript/examples/grapheditor/www/resources/grapheditor.md');
57
// fs.copySync('src/mxgraph/javascript/examples/grapheditor/www/resources/grapheditor.txt',
6-
// 'src/mxgraph/javascript/examples/grapheditor/www/resources/grapheditor.md');
8+
// 'src/mxgraph/javascript/examples/grapheditor/www/resources/grapheditor.md');

src/editor.ts

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ w.OPEN_FORM = web_path + 'open.html';
2828
w.mxLoadStylesheets = false; // disable loading stylesheets
2929
w.mxLoadResources = false;
3030

31-
import * as mx from './mxgraph/javascript/examples/grapheditor/www/modulated.js';
31+
/* This is a typing-only import. If you use it directly, the mxgraph content
32+
will be included in the main JupyterLab js bundle.
33+
*/
34+
import * as MXModuleType from './mxgraph/javascript/examples/grapheditor/www/modulated.js';
3235

3336
import {
3437
ABCWidgetFactory, DocumentRegistry, DocumentWidget,
@@ -69,21 +72,29 @@ class DrawioWidget extends DocumentWidget<Widget> {
6972
constructor(options: DocumentWidget.IOptions<Widget>) {
7073
super({ ...options });
7174
this.context = options['context'];
75+
void Private.ensureMx().then((mx) => this.onMxLoaded(mx));
76+
}
7277

78+
protected async onMxLoaded(mx: Private.MX) {
79+
this.mx = mx;
7380
this._onTitleChanged();
7481
this.context.pathChanged.connect(this._onTitleChanged, this);
7582

76-
this.context.ready.then(() => { this._onContextReady(); });
77-
this.context.ready.then(() => { this._handleDirtyStateNew(); });
83+
await this.context.ready;
84+
85+
this._onContextReady();
86+
this._handleDirtyStateNew();
7887
}
7988

80-
protected onAfterShow(msg: Message): void {
81-
this._loadEditor(this.node);
82-
this._onContentChanged();
89+
onAfterShow(msg: Message): void {
90+
Private.ensureMx().then(() => {
91+
this._loadEditor(this.node);
92+
this._onContentChanged();
93+
});
8394
}
8495

8596
public getSVG() : string {
86-
return mx.mxUtils.getXml(this._editor.editor.graph.getSvg());
97+
return this.mx.mxUtils.getXml(this._editor.editor.graph.getSvg());
8798
}
8899

89100
private _onContextReady() : void {
@@ -116,6 +127,7 @@ class DrawioWidget extends DocumentWidget<Widget> {
116127
}
117128

118129
private _loadEditor(node: HTMLElement, contents?: string): void {
130+
const {mx} = this;
119131
// Adds required resources (disables loading of fallback properties, this can only
120132
// be used if we know that all keys are defined in the language specific file)
121133
mx.mxResources.loadDefaultBundle = false;
@@ -145,6 +157,7 @@ class DrawioWidget extends DocumentWidget<Widget> {
145157
}
146158

147159
private _onContentChanged() : void {
160+
const {mx} = this;
148161
if (this._editor === undefined)
149162
{
150163
return;
@@ -167,7 +180,7 @@ class DrawioWidget extends DocumentWidget<Widget> {
167180
{
168181
this._editor.editor.graph.stopEditing();
169182
}
170-
let xml = mx.mxUtils.getXml(this._editor.editor.getGraphXml());
183+
let xml = this.mx.mxUtils.getXml(this._editor.editor.getGraphXml());
171184
this.context.model.fromString(xml);
172185
}
173186

@@ -198,6 +211,7 @@ class DrawioWidget extends DocumentWidget<Widget> {
198211
readonly context: DocumentRegistry.Context;
199212
private _editor : any;
200213
private _ready = new PromiseDelegate<void>();
214+
protected mx: Private.MX;
201215
}
202216

203217
/**
@@ -216,3 +230,38 @@ class DrawioFactory extends ABCWidgetFactory<DrawioWidget, DocumentRegistry.IMod
216230
return new DrawioWidget({context, content: new Widget()});
217231
}
218232
}
233+
234+
235+
/**
236+
* A namespace for module-level concerns like loading mxgraph
237+
*/
238+
239+
namespace Private {
240+
export type MX = typeof MXModuleType;
241+
242+
let _mx: typeof MXModuleType;
243+
let _mxLoading: PromiseDelegate<MX>;
244+
245+
/**
246+
* Asynchronously load the mx bundle, or return it if already available
247+
*/
248+
export async function ensureMx(): Promise<MX> {
249+
if (_mx)
250+
{
251+
return _mx;
252+
}
253+
254+
if (_mxLoading)
255+
{
256+
return await _mxLoading.promise;
257+
}
258+
259+
_mxLoading = new PromiseDelegate();
260+
_mx = await import(
261+
/* webpackChunkName: "mxgraph" */
262+
'./mxgraph/javascript/examples/grapheditor/www/modulated.js'
263+
);
264+
_mxLoading.resolve(_mx);
265+
return _mx;
266+
}
267+
}

0 commit comments

Comments
 (0)