Skip to content

Commit 569117a

Browse files
authored
JS import fallbacks (#482)
* WIP: cdn fallbacks * Fallback for dynamic-importmap * Version bump
1 parent cd044c9 commit 569117a

File tree

2 files changed

+87
-9
lines changed

2 files changed

+87
-9
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "vitessce"
7-
version = "3.7.6"
7+
version = "3.7.7"
88
authors = [
99
{ name="Mark Keller", email="[email protected]" },
1010
]

src/vitessce/widget.py

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,84 @@ def get_uid_str(uid):
155155

156156
# lang: js
157157
ESM = """
158-
import { importWithMap } from 'https://unpkg.com/[email protected]';
158+
let importWithMap;
159+
try {
160+
importWithMap = (await import('https://unpkg.com/[email protected]')).importWithMap;
161+
} catch(e) {
162+
console.warn("Import of dynamic-importmap failed, trying fallback.");
163+
importWithMap = (await import('https://cdn.vitessce.io/[email protected]/dist/index.js')).importWithMap;
164+
}
165+
166+
const successfulImportMap = {
167+
imports: {
168+
169+
},
170+
};
159171
const importMap = {
160172
imports: {
161173
"react": "https://esm.sh/[email protected]?dev",
162174
"react-dom": "https://esm.sh/[email protected]?dev",
163175
"react-dom/client": "https://esm.sh/[email protected]/client?dev",
164176
},
165177
};
178+
const fallbackImportMap = {
179+
imports: {
180+
"react": "https://cdn.vitessce.io/[email protected]/index.js",
181+
"react-dom": "https://cdn.vitessce.io/[email protected]/index.js",
182+
"react-dom/client": "https://cdn.vitessce.io/[email protected]/es2022/client.mjs",
183+
// Replaced with version-specific URL below.
184+
"vitessce": "https://cdn.vitessce.io/[email protected]/dist/index.min.js",
185+
},
186+
};
187+
/*
188+
const fallbackDevImportMap = {
189+
imports: {
190+
"react": "https://cdn.vitessce.io/[email protected]/index_dev.js",
191+
"react-dom": "https://cdn.vitessce.io/[email protected]/index_dev.js",
192+
"react-dom/client": "https://cdn.vitessce.io/[email protected]/es2022/client.development.mjs",
193+
// Replaced with version-specific URL below.
194+
"vitessce": "https://cdn.vitessce.io/@vitessce/[email protected]/dist/index.js",
195+
},
196+
};
197+
*/
198+
199+
async function importWithMapAndFallback(moduleName, importMap, fallbackMap) {
200+
let result = null;
201+
if (!fallbackMap) {
202+
// fallbackMap is null, user may have provided custom JS URL.
203+
result = await importWithMap(moduleName, {
204+
imports: {
205+
...importMap.imports,
206+
...successfulImportMap.imports,
207+
},
208+
});
209+
successfulImportMap.imports[moduleName] = importMap.imports[moduleName];
210+
} else {
211+
try {
212+
result = await importWithMap(moduleName, {
213+
imports: {
214+
...importMap.imports,
215+
...successfulImportMap.imports,
216+
},
217+
});
218+
successfulImportMap.imports[moduleName] = importMap.imports[moduleName];
219+
} catch (e) {
220+
console.warn(`Importing ${moduleName} failed with importMap`, importMap, "trying fallback", fallbackMap, successfulImportMap);
221+
result = await importWithMap(moduleName, {
222+
imports: {
223+
...fallbackMap.imports,
224+
...successfulImportMap.imports,
225+
},
226+
});
227+
successfulImportMap.imports[moduleName] = fallbackMap.imports[moduleName];
228+
}
229+
}
230+
return result;
231+
}
232+
166233
167-
const React = await importWithMap("react", importMap);
168-
const { createRoot } = await importWithMap("react-dom/client", importMap);
234+
const React = await importWithMapAndFallback("react", importMap, fallbackImportMap);
235+
const { createRoot } = await importWithMapAndFallback("react-dom/client", importMap, fallbackImportMap);
169236
170237
const e = React.createElement;
171238
@@ -268,10 +335,21 @@ def get_uid_str(uid):
268335
269336
const pkgName = (jsDevMode ? "@vitessce/dev" : "vitessce");
270337
271-
importMap.imports["vitessce"] = (customJsUrl.length > 0
338+
const hasCustomJsUrl = customJsUrl.length > 0;
339+
340+
importMap.imports["vitessce"] = (hasCustomJsUrl
272341
? customJsUrl
273342
: `https://unpkg.com/${pkgName}@${jsPackageVersion}`
274343
);
344+
let fallbackImportMapToUse = null;
345+
if (!hasCustomJsUrl) {
346+
fallbackImportMapToUse = fallbackImportMap;
347+
if (jsDevMode) {
348+
fallbackImportMapToUse.imports["vitessce"] = `https://cdn.vitessce.io/vitessce@${jsPackageVersion}/dist/index.min.js`;
349+
} else {
350+
fallbackImportMapToUse.imports["vitessce"] = `https://cdn.vitessce.io/@vitessce/dev@${jsPackageVersion}/dist/index.js`;
351+
}
352+
}
275353
276354
const {
277355
Vitessce,
@@ -292,7 +370,7 @@ def get_uid_str(uid):
292370
useComplexCoordinationSecondary,
293371
useCoordinationScopes,
294372
useCoordinationScopesBy,
295-
} = await importWithMap("vitessce", importMap);
373+
} = await importWithMapAndFallback("vitessce", importMap, fallbackImportMapToUse);
296374
297375
let pluginViewTypes = [];
298376
let pluginCoordinationTypes = [];
@@ -651,7 +729,7 @@ class VitessceWidget(anywidget.AnyWidget):
651729

652730
next_port = DEFAULT_PORT
653731

654-
js_package_version = Unicode('3.8.3').tag(sync=True)
732+
js_package_version = Unicode('3.8.5').tag(sync=True)
655733
js_dev_mode = Bool(False).tag(sync=True)
656734
custom_js_url = Unicode('').tag(sync=True)
657735
plugin_esm = List(trait=Unicode(''), default_value=[]).tag(sync=True)
@@ -664,7 +742,7 @@ class VitessceWidget(anywidget.AnyWidget):
664742

665743
store_urls = List(trait=Unicode(''), default_value=[]).tag(sync=True)
666744

667-
def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=False, js_package_version='3.8.3', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, prefer_local=True, invoke_timeout=300000, invoke_batched=True, page_mode=False, page_esm=None, prevent_scroll=True, server_host=None):
745+
def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=False, js_package_version='3.8.5', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, prefer_local=True, invoke_timeout=300000, invoke_batched=True, page_mode=False, page_esm=None, prevent_scroll=True, server_host=None):
668746
"""
669747
Construct a new Vitessce widget. Not intended to be instantiated directly; instead, use ``VitessceConfig.widget``.
670748
@@ -798,7 +876,7 @@ def _plugin_command(self, params, buffers):
798876
# Launch Vitessce using plain HTML representation (no ipywidgets)
799877

800878

801-
def ipython_display(config, height=600, theme='auto', base_url=None, host_name=None, uid=None, port=None, proxy=False, js_package_version='3.8.3', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, page_mode=False, page_esm=None, server_host=None):
879+
def ipython_display(config, height=600, theme='auto', base_url=None, host_name=None, uid=None, port=None, proxy=False, js_package_version='3.8.5', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, page_mode=False, page_esm=None, server_host=None):
802880
from IPython.display import display, HTML
803881
uid_str = "vitessce" + get_uid_str(uid)
804882

0 commit comments

Comments
 (0)