bootstrap.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) Jupyter Development Team.
  3. | Distributed under the terms of the Modified BSD License.
  4. |----------------------------------------------------------------------------*/
  5. // We copy some of the pageconfig parsing logic in @jupyterlab/coreutils
  6. // below, since this must run before any other files are loaded (including
  7. // @jupyterlab/coreutils).
  8. /**
  9. * Get global configuration data for the Jupyter application.
  10. *
  11. * @param name - The name of the configuration option.
  12. *
  13. * @returns The config value or an empty string if not found.
  14. *
  15. * #### Notes
  16. * All values are treated as strings. For browser based applications, it is
  17. * assumed that the page HTML includes a script tag with the id
  18. * `jupyter-config-data` containing the configuration as valid JSON.
  19. */
  20. let _CONFIG_DATA = null;
  21. function getOption(name) {
  22. if (_CONFIG_DATA === null) {
  23. let configData = {};
  24. // Use script tag if available.
  25. if (typeof document !== 'undefined' && document) {
  26. const el = document.getElementById('jupyter-config-data');
  27. if (el) {
  28. configData = JSON.parse(el.textContent || '{}');
  29. }
  30. }
  31. _CONFIG_DATA = configData;
  32. }
  33. return _CONFIG_DATA[name] || '';
  34. }
  35. // eslint-disable-next-line no-undef
  36. __webpack_public_path__ = getOption('fullStaticUrl') + '/';
  37. // Promise.allSettled polyfill, until our supported browsers implement it
  38. // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
  39. if (Promise.allSettled === undefined) {
  40. Promise.allSettled = promises =>
  41. Promise.all(
  42. promises.map(promise =>
  43. promise.then(
  44. value => ({
  45. status: 'fulfilled',
  46. value
  47. }),
  48. reason => ({
  49. status: 'rejected',
  50. reason
  51. })
  52. )
  53. )
  54. );
  55. }
  56. function loadScript(url) {
  57. return new Promise((resolve, reject) => {
  58. const newScript = document.createElement('script');
  59. newScript.onerror = reject;
  60. newScript.onload = resolve;
  61. newScript.async = true;
  62. document.head.appendChild(newScript);
  63. newScript.src = url;
  64. });
  65. }
  66. async function loadComponent(url, scope) {
  67. await loadScript(url);
  68. // From https://webpack.js.org/concepts/module-federation/#dynamic-remote-containers
  69. // eslint-disable-next-line no-undef
  70. await __webpack_init_sharing__('default');
  71. const container = window._JUPYTERLAB[scope];
  72. // Initialize the container, it may provide shared modules and may need ours
  73. // eslint-disable-next-line no-undef
  74. await container.init(__webpack_share_scopes__.default);
  75. }
  76. void (async function bootstrap() {
  77. // This is all the data needed to load and activate plugins. This should be
  78. // gathered by the server and put onto the initial page template.
  79. const extension_data = getOption('federated_extensions');
  80. // We first load all federated components so that the shared module
  81. // deduplication can run and figure out which shared modules from all
  82. // components should be actually used. We have to do this before importing
  83. // and using the module that actually uses these components so that all
  84. // dependencies are initialized.
  85. let labExtensionUrl = getOption('fullLabextensionsUrl');
  86. const extensions = await Promise.allSettled(
  87. extension_data.map(async data => {
  88. await loadComponent(
  89. `${labExtensionUrl}/${data.name}/${data.load}`,
  90. data.name
  91. );
  92. })
  93. );
  94. extensions.forEach(p => {
  95. if (p.status === 'rejected') {
  96. // There was an error loading the component
  97. console.error(p.reason);
  98. }
  99. });
  100. // Now that all federated containers are initialized with the main
  101. // container, we can import the main function.
  102. let main = (await import('./index.out.js')).main;
  103. window.addEventListener('load', main);
  104. })();