Skip to content

fixed library target for nbclassic nbextension for graph_notebook_widget #739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/graph_notebook/start_notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}''')
Expand Down
28 changes: 22 additions & 6 deletions src/graph_notebook/widgets/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/",
},
Expand All @@ -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 },
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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 },
Expand Down