news 2026/9/14 19:22:51

Jupyter Notebook 7 扩展开发指南:基于 JupyterLab 生态的前端扩展与服务端扩展体系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Jupyter Notebook 7 扩展开发指南:基于 JupyterLab 生态的前端扩展与服务端扩展体系

Jupyter Notebook 7 扩展开发指南:基于 JupyterLab 生态的前端扩展与服务端扩展体系

【免费下载链接】notebookJupyter Interactive Notebook项目地址: https://gitcode.com/GitHub_Trending/no/notebook

Notebook 7 的扩展机制与经典 Notebook 6.x 相比发生了根本性变化:前端扩展基于 JupyterLab 的扩展体系构建,服务端扩展则沿用 Jupyter Server 的扩展系统。本文基于本仓库的 docs/source/extending/index.md 与 docs/source/extending/frontend_extensions.md,结合仓库源码与配置,讲解 Notebook 7 可扩展子系统的架构、前端 TypeScript 扩展的编写路径,以及如何在当前仓库中验证扩展加载机制。

概览:Notebook 7 的扩展体系发生了怎样的变化

从 Notebook 7 开始,notebook 前端完全构建在 JupyterLab 之上:JupyterNotebookApp直接继承自 Jupyter Server 的LabServerApp(见 notebook/app.py),这意味着 Notebook 7 的扩展系统与 JupyterLab 完全同源。

官方文档 docs/source/extending/index.md 明确了两条核心结论:

  • 前端扩展系统:与 JupyterLab 使用同一套扩展系统;
  • 服务端扩展系统:与 Jupyter Server 使用同一套扩展系统。

因此,Notebook 7 可以原样复用 JupyterLab 生态中大量现成的扩展。如果你仍在使用 Notebook 6.5.x 及更早版本并需要扩展经典 Notebook,请参考 NbClassic 的文档(注意:旧版基于notebook.nbextensionscustom.jsconfig.js的扩展机制在 Notebook 7 中已不再适用)。

Notebook 中设计为可扩展/可覆盖的子系统包括:仪表盘(tree 页面,即文件浏览页)、notebook 页面、文本编辑器、控制台、终端等页面。文档中给出的扩展入口分为两部分:

  • Extending the Jupyter Server:服务端扩展的开发者文档;
  • Custom front-end extensions(即 docs/source/extending/frontend_extensions.md):前端扩展的编写指引,这是本篇的核心内容。

前置知识:Notebook 7 的组件分层

在深入扩展开发之前,需要理解 Notebook 7 的架构分层。整个项目是典型的 monorepo(见 package.json 的workspaces配置),所有业务逻辑被打散到packages/目录下,并与 JupyterLab 的包协同工作:

  • @jupyter-notebook/application:应用外壳(NotebookApp)与 shell 实现,位于 packages/application/src/app.ts;
  • @jupyter-notebook/application-extension:为不同页面提供核心插件,如菜单、命令面板、设置等;
  • @jupyter-notebook/notebook-extension:notebook 页面的扩展逻辑(检查点、关闭标签页、全宽模式、滚动输出等),见 packages/notebook-extension/schema 下的 schema 文件;
  • @jupyter-notebook/tree@jupyter-notebook/tree-extension:文件树页面及其扩展;
  • @jupyter-notebook/console-extension@jupyter-notebook/terminal-extension@jupyter-notebook/documentsearch-extension@jupyter-notebook/docmanager-extension@jupyter-notebook/help-extension:控制台、终端、文档搜索、文档管理、帮助等页面的扩展;
  • @jupyter-notebook/lab-extension:在 JupyterLab 中打开 Notebook 的桥接扩展,同时包含"接口切换器"等自定义工具条组件(见 packages/lab-extension/src/index.ts);
  • @jupyter-notebook/ui-components:UI 组件与图标。

页面侧的模板文件位于 app/templates(consoles_template.htmledit_template.htmlnotebooks_template.htmlterminals_template.htmltree_template.htmlerror_template.html),由 app/rspack.config.js 通过HtmlWebpackPlugin在构建时生成实际的notebook/*.html页面。

理解这一分层后,你会发现扩展 Notebook 7 的前端,本质上就是编写一个能被这些页面加载的 JupyterLab 插件。

服务端扩展:复用 Jupyter Server 的扩展机制

文档指出服务端扩展基于 Jupyter Server 的扩展系统。在本仓库中可以验证这一结论:

  • Notebook 7 本身就是一个 Jupyter Server 扩展,其启用配置见 jupyter-config/jupyter_server_config.d/notebook.json,其中jpserver_extensions.notebook被设置为true
  • JupyterNotebookApp继承LabServerApp并实现了server_extension_is_enabled()方法来检查如nbclassic等服务端扩展是否启用(见 notebook/app.py);
  • 服务端各页面的 URL 路由(/tree/notebooks/edit/consoles/terminals/custom/custom.css)在initialize_handlers()中注册(见 notebook/app.py)。

因此,要扩展 Notebook 7 的服务端行为,请遵循 Jupyter Server 开发者文档中的方式:编写一个实现load_jupyter_server_extension()的 Python 包,并通过jupyter server extension enable或在jupyter_server_config.d/目录下放置配置文件来启用它。

前端扩展:编写 TypeScript 扩展

前端扩展的开发是这篇文档的核心。从 Notebook 7 开始,前端扩展以预构建(prebuilt)JupyterLab 扩展的形式开发

为什么是"预构建"扩展

预构建扩展在发布时就已经完成了前端构建(产出 JS 与 schema),用户安装后无需在前端运行时重新编译,直接由 Jupyter Server 在启动时发现并加载。这正是 Notebook 7 能够直接复用 JupyterLab 生态扩展的关键。

在本仓库中,@jupyter-notebook/lab-extension本身就是这种形态的典型样例。查看其 packages/lab-extension/package.json:

  • "jupyterlab": { "extension": true, ... }标记这是一个 JupyterLab 扩展;
  • outputDir指向../../notebook/labextension,即构建产物输出到 notebook 包内;
  • schemaDir指向schema,扩展的 JSON Schema 设置文件被打包发布。

这意味着你的自定义扩展最终也要遵循同样的元数据规范,才能在 Notebook 7 中被识别。

扩展如何被加载:页面级插件白名单

在预构建扩展之上,Notebook 7 还通过app/package.json中的jupyterlab.plugins字段为每个页面精确声明启用的插件(见 app/package.json)。例如:

  • 根路径/加载@jupyter-notebook/application-extension@jupyter-notebook/notebook-extension以及一大批@jupyterlab/*-extension
  • /tree页面加载@jupyter-notebook/tree-extension与文件浏览器、扩展管理器、设置编辑器等插件;
  • /notebooks页面加载调试器(debugger)、目录(toc)、工具提示(tooltip)等插件;
  • /edit页面加载文件编辑器与 markdown 查看器插件。

在构建阶段,app/rspack.config.js 会从该字段提取每个页面的插件清单,并通过 Handlebars 模板list_pluginshelper 生成按页面过滤的require()调用,最终由ModuleFederationPlugin做模块联邦共享配置(见 app/rspack.config.js)。singletonPackages列表(见 app/package.json)则保证如@jupyterlab/applicationreact等核心包在扩展间以单例共享,避免版本冲突。

因此,如果你的扩展希望出现在某个特定页面,需要对照该页面的插件白名单确认自己的插件 id 与激活条件。

官方推荐的入门资源

文档给出了两条官方学习路径:

  1. JupyterLab 扩展教程:讲解如何编写一个最简单的 JupyterLab 扩展(从脚手架、package.jsonjupyterlab字段配置、到插件对象JupyterFrontEndPlugin的编写与注册);
  2. JupyterLab 扩展示例仓库:收录了大量完成不同任务的扩展示例,包括添加命令、添加新 widget、处理用户设置、添加菜单项、在状态栏显示内容等。

虽然这些资源以 JupyterLab 为目标环境,但正如文档强调的,Notebook 7 复用同一套扩展系统,因此其中的方法可以直接迁移到 Notebook 7。

从源码看插件编写范式:以 interface-switcher 为例

为了让"编写 JupyterLab 插件"这件事落到仓库实处,我们以 packages/lab-extension/src/index.ts 中的interfaceSwitcher插件为例,剖析一个可运行的插件具备哪些要素。

插件对象的基本结构

JupyterFrontEndPlugin是插件的基本单元,其核心字段包括:

  • id:全局唯一的插件标识(如'@jupyter-notebook/lab-extension:interface-switcher');
  • description:插件说明;
  • autoStart:是否随应用启动自动激活;
  • requires:必选依赖的 token(如ITranslator);
  • optional:可选依赖的 token(如INotebookTrackerICommandPaletteIToolbarWidgetRegistry),用null注入;
  • activate:激活函数,接收应用实例app与所有依赖,返回插件注册的业务逻辑。

利用 token 进行依赖注入

activate内部,插件通过app.commandsapp.shell等应用级 API 以及注入的 token 来扩展行为:

const { commands, shell } = app; const baseUrl = app.serviceManager.serverSettings.baseUrl;

例如interfaceSwitcher使用IToolbarWidgetRegistry为 "Notebook" 面板注册自定义工具条组件(toolbarRegistry.addFactory<NotebookPanel>('Notebook', 'interfaceSwitcher', ...)),使用ICommandPalette将命令添加到命令面板,使用INotebookTracker定位当前 notebook 以决定命令是否可用(isEnabled判断notebookTracker.currentWidget === shell.currentWidget)。

注册命令与菜单

插件通过commands.addCommand(command, { label, caption, execute, isEnabled, ... })注册命令,再通过switcher.addItem({ command })把命令挂到 Lumino 菜单上;如果只有一个可切换的目标,则退化为单个工具条按钮(CommandToolbarButton),否则渲染为带下拉菜单的MenuBar。这一模式完整演示了"命令 → 菜单/工具条 → 命令面板"的标准 JupyterLab 扩展链路。

通过 schema 扩展菜单

除了在代码中编程式注册菜单,还可以用 JSON Schema 声明式扩展菜单。查看 packages/lab-extension/schema/launch-tree.json,它通过jupyter.lab.menus.main字段把jupyter-notebook:launch-tree命令以 rank 1 插入jp-mainmenu-view(View 菜单)。这与 JupyterLab 的 settings/schema 机制完全一致:扩展目录下的schema/*.json会被 Jupyter Server 加载,用户可在设置界面中调整。

各页面配置的底层支撑

页面级插件白名单最终由服务端拼入 page config。NotebookBaseHandler.get_page_config()(见 notebook/app.py)会把应用版本、baseUrl、token、labextensions 路径、nbclassic_enabled、JupyterHub 元数据等写入page_config,前端NotebookApp再通过PageConfig.getOption(...)读取(见 packages/application/src/app.ts)。这解释了预构建扩展从"服务端发现"到"前端激活"的完整数据通路。

在本地仓库验证与调试扩展

查看当前构建的扩展清单

  • 服务端是否发现扩展:jupyter labextension list
  • 服务端扩展是否启用:jupyter server extension list(应能看到notebook已启用,配置来源即 jupyter-config/jupyter_server_config.d/notebook.json)

仓库自身的开发模式

如果要在本仓库中进行扩展相关开发,项目提供了完整脚本(见 package.json):

  • jlpm build:构建全部组件(buildutils → lib → lab-extension → app);
  • jlpm watch:同时监听 lib 与 app 的变化(watch:libwatch:app),app 侧通过rspack --watch实现(见 app/package.json);
  • jlpm develop:执行jupyter-builder develop . --overwrite后运行 buildutils/src/develop.ts,将notebook/schemas/@jupyter-notebook符号链接到当前 Python 环境的share/jupyter/lab/schemas/@jupyter-notebook,使 schema 修改即时生效。

修改 schema 或插件代码后,在应用页面上刷新即可看到变更;修改 Python 侧 handler 则需要重启 notebook 服务。

扩展开发的调试提示

  1. 注意插件白名单:即使插件成功构建,如果其id不在对应页面的plugins白名单(app/package.json)中,也不会被激活——这与 JupyterLab 的自动发现机制不同,是 Notebook 7 页面定制化带来的差异;
  2. 善用命令面板与浏览器控制台autoStart: true的插件会在启动时执行,可在activate中打印日志;命令是否被注册可通过命令面板搜索验证;
  3. schema 修改即时生效:在jlpm develop模式下 schema 采用符号链接,改完刷新页面即可,无需重新安装。

常见问题

Q:Notebook 6 时代的custom.jsnbextensions还能用吗?不能。Notebook 7 的扩展机制与此前的经典 Notebook 完全不同,旧扩展需要迁移到 JupyterLab 插件体系(参考 NbClassic 文档了解经典 Notebook 6 的扩展方式)。

Q:我的 JupyterLab 扩展能直接在 Notebook 7 中运行吗?在多数情况下可以。因为两者共享同一套前端扩展系统与服务端扩展系统;但最终能否在特定页面生效,取决于该页面的插件白名单配置。

Q:在哪里查看服务端如何加载扩展?参考 jupyter-config/jupyter_server_config.d/notebook.json(本仓库自身的扩展启用配置)以及 notebook/app.py 中server_extension_is_enabledinitialize_handlers的实现。

Q:如何确定扩展的 schema 会被前端读取?扩展的jupyterlab.schemaDir指向的目录会被打包,服务端get_page_config()会把这些 labextensions 路径合并进 page config(见 notebook/app.py),前端由此读取对应 schema 与用户设置。

延伸阅读

  • 前端扩展的编写细节:docs/source/extending/frontend_extensions.md
  • 服务端扩展总览:docs/source/extending/index.md
  • Notebook 7 其他架构文档:docs/source/migrate_to_notebook7.md、docs/source/notebook_7_features.md
  • 仓库中可对照的扩展实现: packages/lab-extension/src/index.ts、packages/lab-extension/package.json、app/package.json、app/rspack.config.js

【免费下载链接】notebookJupyter Interactive Notebook项目地址: https://gitcode.com/GitHub_Trending/no/notebook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 19:22:38

10分钟扫一遍Czkawka:Rust写的重复文件与垃圾清理指南

10分钟扫一遍Czkawka&#xff1a;Rust写的重复文件与垃圾清理指南 【免费下载链接】czkawka Multi functional app to find duplicates, empty folders, similar images etc. 项目地址: https://gitcode.com/GitHub_Trending/cz/czkawka 你的电脑里一定有不少这样的文件…

作者头像 李华
网站建设 2026/9/14 19:19:58

Flutter跨平台开发:OpenHarmony个人理财App实战

1. 项目概述与核心价值这个Flutter for OpenHarmony个人理财管理App的月度报告页面&#xff0c;本质上是一个数据可视化与财务分析功能的集合体。作为个人理财应用的核心模块&#xff0c;它解决了传统记账软件"只记录不分析"的痛点。想象一下&#xff0c;你坚持记账一…

作者头像 李华