From a2d17d9a3df2ceb666b723306fccee99e95c3a63 Mon Sep 17 00:00:00 2001 From: Aditya Ramesh Mac Date: Tue, 13 May 2025 15:16:25 -0700 Subject: [PATCH] fixed library target for nbclassic nbextension for graph_notebook_widget --- pyproject.toml | 2 +- requirements.txt | 2 +- src/graph_notebook/start_notebook.py | 1 + src/graph_notebook/widgets/webpack.config.js | 28 +++++++++++++++----- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 84912b27..e7a95ccf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ dependencies = [ 'nbclient>=0.7.3', 'nbconvert>=6.3.0,<=7.2.8', 'notebook>=7.0.0,<8.0.0', - 'nbclassic>=1.0.0', + 'nbclassic>=1.3.0', # Data processing and visualization 'itables>=2.0.0,<=2.1.0', diff --git a/requirements.txt b/requirements.txt index 3b751d45..a80fd44e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ jupyterlab-widgets>=3.0.0,<4.0.0 nbclient>=0.7.3 nbconvert>=6.3.0,<=7.2.8 notebook>=7.0.0,<8.0.0 -nbclassic>=1.0.0 +nbclassic>=1.3.0 # Data processing and visualization itables>=2.0.0,<=2.1.0 diff --git a/src/graph_notebook/start_notebook.py b/src/graph_notebook/start_notebook.py index b01f64a8..173ad0c8 100644 --- a/src/graph_notebook/start_notebook.py +++ b/src/graph_notebook/start_notebook.py @@ -71,6 +71,7 @@ def main(): # Starting with Notebook 7.0+, the classic notebook interface was rewritten to use JupyterLab's architecture. # This means traditional nbextensions (which rely on requirejs and jQuery) are not directly supported. # We use nbclassic package to maintain compatibility + # Reference: https://jupyter-notebook.readthedocs.io/en/latest/migrating/multiple-interfaces.html#simultaneous-usage-of-different-versions-of-notebook-7-and-the-classic-notebook-ui kernel_manager_option = "--NotebookApp.kernel_manager_class=notebook.services.kernels.kernelmanager.AsyncMappingKernelManager" notebooks_dir = '~/notebook/destination/dir' if args.notebooks_dir == '' else args.notebooks_dir os.system(f'''jupyter nbclassic {kernel_manager_option} {notebooks_dir}''') diff --git a/src/graph_notebook/widgets/webpack.config.js b/src/graph_notebook/widgets/webpack.config.js index c9fc7805..31f235c1 100644 --- a/src/graph_notebook/widgets/webpack.config.js +++ b/src/graph_notebook/widgets/webpack.config.js @@ -85,14 +85,17 @@ const labModuleFederationConfig = { // Export array of webpack configurations module.exports = [ - // 1. Notebook extension AMD module + // 1. Notebook extension AMD module - Used by NBClassic (Jupyter Notebook < 7.0) { mode, entry: "./src/extension.js", output: { filename: "extension.js", path: path.resolve(__dirname, "nbextension"), - libraryTarget: "amd", + // libraryTarget: "var" exposes the library by creating a global variable + // Example: var graph_notebook_widgets = { ... } + // This is the classic way NBClassic loads extensions through RequireJS + libraryTarget: "var", library: "graph_notebook_widgets", publicPath: "nbextensions/graph_notebook_widgets/", }, @@ -104,15 +107,22 @@ module.exports = [ watchOptions, }, - // 2. Notebook extension + // 2. Notebook extension - Used by NBClassic (Jupyter Notebook < 7.0) { mode, entry: "./src/extension.ts", output: { filename: "index.js", path: path.resolve(__dirname, "nbextension"), + // libraryTarget: "amd" creates an AMD module that can be loaded by RequireJS + // AMD (Asynchronous Module Definition) allows modules to be loaded asynchronously + // Example: define(['dependency'], function(dependency) { ... }) + // NBClassic uses RequireJS to load extensions in this format libraryTarget: "amd", - library: "graph_notebook_widgets", + // This creates a "named define" module without a global variable + // It allows the module to be imported by name in RequireJS + // Example: define('graph_notebook_widgets', ['dependency'], function(dependency) { ... }) + library: undefined, publicPath: "nbextensions/graph_notebook_widgets/", }, module: { rules }, @@ -123,7 +133,7 @@ module.exports = [ watchOptions, }, - // 3. Lab extension with Module Federation + // 3. Lab extension with Module Federation - Used by JupyterLab 4.x and Notebook 7+ { mode, entry: "./src/index.ts", @@ -132,6 +142,9 @@ module.exports = [ chunkFilename: '[name].[contenthash].js', path: path.resolve(__dirname, 'labextension/static'), publicPath: 'static/', + // AMD format is used as the base format for JupyterLab extensions + // Module Federation builds on top of this to enable dynamic loading + // This configuration creates a JupyterLab 4.x compatible extension libraryTarget: 'amd' }, devtool: "source-map", @@ -143,18 +156,21 @@ module.exports = [ resolve, plugins: [ ...basePlugins, + // ModuleFederationPlugin enables the extension to be loaded dynamically + // by JupyterLab 4.x and Notebook 7+ which both use this architecture new ModuleFederationPlugin(labModuleFederationConfig), ], watchOptions }, - // 4. Documentation widget bundle + // 4. Documentation widget bundle - Used for documentation examples { mode, entry: "./src/index.ts", output: { filename: "embed-bundle.js", path: path.resolve(__dirname, "docs", "source", "_static"), + // AMD format used for documentation examples to match JupyterLab format libraryTarget: "amd", }, module: { rules },