---
# System prepended metadata

title: Notebook / Extensions / 總覽
tags: [Notebook, Elyra, Extension, JupyterLab, Jupyter]

---

Notebook / Extensions / 總覽
===
> #ipython, jupyter notebook, python notebook, jupyterlab, elyra
###### tags: `Jupyter`
###### tags: `Jupyter`, `JupyterLab`, `Notebook`, `Elyra`, `Extension`



<br>

[TOC]

<br>

## 官方文件
- ### [Extensions](https://jupyterlab.readthedocs.io/en/1.2.x/user/extensions.html)
- ### [Extension Developer Guide](https://jupyterlab.readthedocs.io/en/stable/extension/extension_dev.html)
    > /en/stable/extension/**extension_dev.html**
- ### [Extension Tutorial](https://jupyterlab.readthedocs.io/en/stable/extension/extension_tutorial.html)
    > /en/stable/extension/**extension_tutorial.html**
    
    ⇨ 前往：[重點整理](/OMBeTZYqS0W7fs9hdy2-kA) (#example, hello-world, getting started)
    ⇨ 前往：[跟著官方手冊開發 JupyterLab Extension](https://qrtt1.medium.com/jupyterlab-extension-677ab218ea2f)

- ### [The JupyterLab Interface](https://jupyterlab.readthedocs.io/en/stable/user/interface.html)
    > /en/stable/user/interface.html
    > - JupyterLab 的 UI 元件
    > - Diatango 的圖示
    >   ![](https://i.imgur.com/ATDMWxS.png)

- ### [Common Extension Points](https://jupyterlab.readthedocs.io/en/stable/extension/extension_points.html)
    > /en/stable/extension/extension_points.html
    > UI 元件對應的擴充用法

<br>

## 推薦文件
- ### [[slide] JupyterLab / Elyra](https://docs.google.com/presentation/d/136w0pgrbbbuEZ_OFY7kJkSIfLfS3ZMRPwdZ5ahLV0xU/edit?usp=sharing)
- ### [10 Jupyter Lab Extensions to Boost Your Productivity](https://towardsdatascience.com/4b3800b7ca2a)
    - [JupyterLab-DrawIO](https://github.com/QuantStack/jupyterlab-drawio)
        ```
        conda install -c conda-forge jupyterlab-drawio
        ```
        - [用JupyterLab-drawio画模型图](https://zhuanlan.zhihu.com/p/70908238)
- ### [19 Best JupyterLab Extensions for Machine Learning](https://neptune.ai/blog/jupyterlab-extensions-for-machine-learning)
    11. [JupyterLab Voyager](https://github.com/altair-viz/jupyterlab_voyager)
        > A JupyterLab MIME renderer extension to view CSV and JSON data in Voyager 2.
- ### [Awesome JupyterLab Extensions](https://towardsdatascience.com/awesome-jupyterlab-extensions-90c2d64d244)
    - [jupyterlab / jupyterlab-google-drive](https://github.com/jupyterlab/jupyterlab-google-drive)
        ![](https://i.imgur.com/SkkgThq.png)
- ### [99 ways to extend the Jupyter ecosystem](https://blog.jupyter.org/99-ways-to-extend-the-jupyter-ecosystem-11e5dab7c54)
    ![](https://i.imgur.com/Lzj5X5J.png)
    #letex, context menu
- ### [5 Must Have JupyterLab extension for data science!](https://www.analyticsvidhya.com/blog/2021/05/5-must-have-jupyterlab-extension-for-data-science/)
- ### [5 Extensions That Will Make You Switch to Jupyter Lab](https://towardsdatascience.com/5-extensions-that-will-make-you-switch-to-jupyter-lab-32c6b66ac755)
- ### 口袋名單
    - from Diatango
        - https://github.com/jtpio/jupyterlab-topbar
        - https://github.com/jtpio/jupyterlab-system-monitor
        - https://github.com/dask/dask-labextension
            這個是用來管理與查看 Dask Cluster 運算資
    - [GPU Dashboards in Jupyter Lab](https://medium.com/rapids-ai/gpu-dashboards-in-jupyter-lab-757b17aae1d5)
        ![](https://i.imgur.com/Gzmv0LD.png)
        - [[github] rapidsai / jupyterlab-nvdashboard
](https://github.com/rapidsai/jupyterlab-nvdashboard)


<br>

<hr>

<br>

## [Extension Developer Guide](https://jupyterlab.readthedocs.io/en/stable/extension/extension_dev.html)

### [官方列舉](https://jupyterlab.readthedocs.io/en/stable/extension/extension_dev.html#extension-developer-guide)
- notebooks
- document editors and viewers
- code consoles
- terminals
- themes
- file browser
- contextual help system
- debugger
- settings editor.
- [各種實作範例](https://github.com/jupyterlab/extension-examples)
    1. [Commands](https://github.com/jupyterlab/extension-examples#commands)
    2. [Command Palette](https://github.com/jupyterlab/extension-examples#command-palette)
    3. [Context Menu](https://github.com/jupyterlab/extension-examples#context-menu)
    4. [Custom Log Console](https://github.com/jupyterlab/extension-examples#custom-log-console)
    5. [Datagrid](https://github.com/jupyterlab/extension-examples#datagrid)
    6. [Hello World](https://github.com/jupyterlab/extension-examples#hello-world)
    7. [Kernel Messaging](https://github.com/jupyterlab/extension-examples#kernel-messaging)
    8. [Kernel Output](https://github.com/jupyterlab/extension-examples#kernel-output)
    9. [Launcher](https://github.com/jupyterlab/extension-examples#launcher)
    10. [Log Messages](https://github.com/jupyterlab/extension-examples#log-messages)
    11. [Main Menu](https://github.com/jupyterlab/extension-examples#main-menu)
    12. [React Widget](https://github.com/jupyterlab/extension-examples#react-widget)
    13. [Server Hello World](https://github.com/jupyterlab/extension-examples#server-hello-world)
    14. [Settings](https://github.com/jupyterlab/extension-examples#settings)
    15. [Signals](https://github.com/jupyterlab/extension-examples#signals)
    16. [State](https://github.com/jupyterlab/extension-examples#state)
    17. [Toolbar Item](https://github.com/jupyterlab/extension-examples#toolbar-item)
    18. [Widgets](https://github.com/jupyterlab/extension-examples#widgets)

### 1. Preface
- A JupyterLab extension is a package that contains a number of JupyterLab plugins.
    一個 extension 是一個套件，包含多個 plugin

### 2. Cookiecutters
- **提供 app 模板**
    - 有 TypeScript 或 JavaScript 腳本，兩種選擇
- **提供 mimerender 模板**
- **提供 theme 模板**

### 3. Overview of Extensions
- **發布方式**
    - source extension 
        - 缺點：需要 Node.js 協助，會耗費大量時間與記憶體
    - prebuilt extension (JupyterLab 3.0 才支援)
        - pip 套件
        - conda 套件
    :::info
    :bulb: **備註**：
    - source 和 prebuilt 可並行發布
    - 亦可直接將 prebuilt bundle 複製到適當目錄，優點是免去轉成 python 套件
    - 建議使用 pip 套件發布 
    :::

### 4. Plugins
- ### plugin 類型
    - **Application plugins**
        - app <-> JupyterLab
        - app <-> service <-> 其他 plugin
            - plugin 需提供 service
        - 可用於：
            - main menu, file browser, notebook, console, file editor 等
    - **Mime renderer plugins**
        - 被載入時，會被 JupyterLab 轉成 Application plugins
        - 內建：pdf viewer, JSON viewer, [Vega](https://vega.github.io/vega/usage/) viewer.
            [![](https://i.imgur.com/FhBJ3vg.png)](https://i.imgur.com/FhBJ3vg.png)
    - **Theme plugins**
        - 內建：淺色和深色主題外掛
        - 可變更 css 變數值、font、graphic 等

- ### Application plugins
    - Application plugin 是一個 JS 物件
        - [Plugins Interacting with Each Other](https://jupyterlab.readthedocs.io/en/stable/extension/extension_dev.html#services)
    - **plugin 基本架構**
        ```typescript=
        import {
          JupyterFrontEnd,
          JupyterFrontEndPlugin
        } from '@jupyterlab/application';

        const plugin: JupyterFrontEndPlugin<MyToken> = {
          id: 'my-extension:plugin',
          activate: activateFunction
        };

        export default plugin;
        ```
        - `id`
            - **類型**：`string`，須唯一
            - **值**：`{npm_extension_name}`:`{plugin_name}`
                - 一個套件可以包含多個 plugin
                    - `my_ext:plugin1`
                    - `my_ext:plugin2`
                    - `my_ext:plugin3`
        - `activate`
            - **類型**：`function`, 啟動入口
            - **呼叫時間**：plugin 被啟用時
            - **參數**：第一個參數固定為 [application object](https://jupyterlab.readthedocs.io/en/stable/extension/extension_dev.html#application-object)
                類型：`@jupyterlab/application`:`JupyterFrontEnd`
                印出物件：
                [![](https://i.imgur.com/iuW471q.png)](https://i.imgur.com/iuW471q.png)
                
    - **plugin 基本架構 - 具體實作**
        ```typescript=
        import {
          JupyterFrontEnd,
          JupyterFrontEndPlugin
        } from '@jupyterlab/application';

        const plugin: JupyterFrontEndPlugin<void> = {
          id: 'my-extension:plugin',
          autoStart: true,
          activate: (app: JupyterFrontEnd) => {
            console.log('calling main()')
          } 
        };

        export default plugin;
        ```

    - **需要跟其他元件互動的 plugin 架構**
        ```typescript=
        const plugin: JupyterFrontEndPlugin<MyToken> = {
          id: 'my-extension:plugin',
          autoStart: true,
          requires: [ILabShell, ITranslator],
          optional: [ICommandPalette],
          provides: MyToken,
          activate: activateFunction
        };
        ```
        - `autoStart`
            - **說明**：在 JupyterLab 起來後，要不要自動載入 plugin ?
            - **類型**：`boolean`
            - **值**
                - `true`
                    - 在 JupyterLab 起來後，就會呼叫該入口點`activate()`
                - `false` 或是沒定義該屬性
                    - 當其他 plugin 請求你的 token 時，才會呼叫的入口點`activate()`
        - `provides`
            - **說明**：plugin 自己的 token 名稱
            - **類型**：`interface` 名稱(?)
        - `requires`
            - **說明**：需要互動的 service token 清單
            - **類型**：`interface` 清單，作為 token 清單
        - `optional`
            - **說明**：選擇性互動的 service token 清單
            - **類型**：`interface` 清單，作為 token 清單
- ### Application Object
    - 類型：JupyterFrontEnd
    - 用途：作為 activate() 的第一個參數
    - 方法：
        - commands
            用於註冊指令＆執行指令
        - docRegistry
        - restored
            應用程式完成載入時，會呼叫此 promise 物件
        - serviceManager
            > low-level manager for talking to the Jupyter REST API.
        - shell
            跟應用程式的內容做互動

- ### Plugins Interacting with Each Other
    - **術語**
        - provider plugin
            - 提供 service 給系統的 plugin
            - 一個服務可以是任何 JS 值，但通常是 JS 物件
        - consumer plugin
            請求服務和使用服務的 plugin
    - **Token**
        - plugin 所提供的 service 由 token 來識別
        - **token 類型**
            - Lumino Token 類別的實例
        - **provider plugin**
            - 在 `provide` 屬性定義 token
            - 並透過 `activate()` 函數回傳所提供的 service
        - **consumer plugin**
            - 在 `requires` 或 `optional` 屬性中引用 token
            - 當 JupyterLab 透過 `activate()` 實體化 consumer plugin 時，
                - 與 token 關聯的服務將被當作參數傳入
                - 當 service 不可用時
                    - 如果在 `requires` 中引用 token ，則會拋出錯誤
                    - 如果在 `optional` 中引用 token ，則會帶入 `null`  進入
            - **何時在 `optional` 中引用 token？**
                - 可有可無的 service，例如 status bar，當然擁有會是最好
        - **啟動順序**
            - JupyterLab 會確保 provider plugin 在 consumer plugin 啟動前先啟動
        :::info
        :bulb: **token 不使用字串的原因**
        - 使用識別字(identifier) 會產生衝突
        - 使用 class 名稱因有 package name 當作 namespace 不易產生衝突
        - 使用 TypeScript 可啟用類型檢查
        :::

    - ### Publishing Tokens
        - Tokens will need to be deduplicated in JupyterLab—see Deduplication of Dependencies for more details.
        - Token 的最佳實作方式
            - 一個套件定義 token
            - 另一個套件實作 token
                - 這麼一來，可以使用相同 token 、不同實作方式，可以用自己的 service 來取代原始 service

- ### Mime Renderer Plugins
    - [pdf extension](https://github.com/jupyterlab/jupyterlab/tree/3.2.x/packages/pdf-extension)
    - [mp4 extension](https://github.com/jupyterlab/jupyterlab-mp4)
    - [cookiecutter for mime renderer extensions](https://github.com/jupyterlab/mimerender-cookiecutter-ts)
- ### Theme plugins
    - 暫略


### 5. Source Extensions

### 6. Prebuilt Extensions
- ### 何謂 Prebuilt
    - [預編譯頭](https://zh.wikipedia.org/wiki/%E9%A2%84%E7%BC%96%E8%AF%91%E5%A4%B4)
        > 以節約在開發過程中編譯器反覆編譯該標頭檔的開銷
    - [Android 概念](http://www.powenko.com/wordpress/android-編譯android原始碼到模擬器上執行/)
        > 在編譯的部份，要先編譯kernel完後再編android。如果你沒動到kernel，則不需要再重新編譯，可以去prebuilt/android-arm/kernel/ 下找到 kernel-qemu 這個映像檔來用。
- ### package.json metadata
    - Output Directory
        ```json=
        "jupyterlab": {
          "outputDir": "mypackage/labextension" <-- 相對路徑
        }
        ```
        ```
        - ${outputDir}
          - package.json
          - static
            - *.js
            - other files
        ```
    - Custom webpack config
        略
- ### Developing a prebuilt extension
    - **指令**
        `jupyter labextension build`
    - **主要入口點(main entry point): `remoteEntry.<hash>.js`**
        ```
        <sys-prefix>/share/jupyter/labextensions/<package-name>
        - static
          - remoteEntry.<hash>.js
        ```
        - `<sys-prefix>`: `/home/tj/miniconda3/envs/jupyterlab-ext/`
    - **開發模式**
        - 在 JupyterLab 套建中，建立一個 symbolic link 指向正在開發的套件
            ```
            <sys-prefix>/share/jupyter/labextensions/<package-name>
            ->
            <your_package_name>/<your_package_name>/labextension
            ```
            其中 `labextension` 會包含 `package.json` 那層
            ```
            labextension
            + static/
            + package.json
            ```
            效果同(範例)：
            ```bash=
            $ ln -s \
            /home/tj/Asus/workplace/jupyter/myextension2/myextension2/labextension \
            /home/tj/miniconda3/envs/jupyterlab-ext/share/jupyter/labextensions/myextension2
            ```
        - 指令
            ```bash=
            $ jupyter labextension develop . --overwrite
            or
            $ pip install -e
            # <sys-prefix>/lib/python3.9/site-packages/xxx-link
            ```
        - 隨後
            - 改 code + re-build + 更新 JupyterLab, 變更就會生效
- ### Distributing a prebuilt extension
-

### 7. Development workflow for source extensions

<br>

<hr>
<hr>

<br>

## [Common Extension Points](https://jupyterlab.readthedocs.io/en/stable/extension/extension_points.html)




### [Jupyter Front-End Shell](https://jupyterlab.readthedocs.io/en/stable/extension/extension_points.html#jupyter-front-end-shell)
可掛載區域如下：
![](https://i.imgur.com/jGIaytU.png)
- ### top (頂層工具列)
    ![](https://i.imgur.com/oAur5To.png)
    <br>
    ![](https://i.imgur.com/PD4bWN8.png)
    - 透過 rank 控制
        ```
        app.shell.add(terminal, 'top', {rank: 0});
        ```
- ### menu (頂層工具列一種，具有選單的工具列)
    ![](https://i.imgur.com/nWJRttf.png)
- ### left & right (左側 & 右側邊欄)
    ![](https://i.imgur.com/d4licaQ.png)
    - 放置在側邊欄的目的：
        - 提供比 main 更持久的使用者界面
    - 右側邊欄
        - debug
        - contextual help
            - [contextual help broken for R docs #6928](https://github.com/jupyterlab/jupyterlab/issues/6928)
                [![](https://i.imgur.com/r3NjJeO.png)](https://i.imgur.com/r3NjJeO.png)
            - [[Feature Request] Contextual Help menu #1468](https://github.com/microsoft/vscode-jupyter/issues/1468)
                [![](https://i.imgur.com/ETadLaR.png)](https://i.imgur.com/ETadLaR.png)

- ### main (用戶活動的主要工作區域)
    ![](https://i.imgur.com/b1v0J8n.png)
- ### down (像是 log 輸出區域, 文件顯示區域)
    ![](https://i.imgur.com/btDpzYU.png)
- ### bottom (底部區域；狀態列之類的)
    ![](https://i.imgur.com/YJuosBN.png)
- ### header (標題區域；橫幅之類的)
    ![](https://i.imgur.com/KqmygUW.png)
- ### header, down, bottom 三種一起出現的機會非常低
    [![](https://i.imgur.com/ehryFof.png)](https://i.imgur.com/ehryFof.png)
    - window10
- 範例程式
    - 簡易版
        ```typescript=
            Promise.all([app.restored]).then(() => {
              app.commands
                .execute('terminal:create-new')
                .then((terminal) => {
                  app.shell.add(terminal, 'header');
                });
            });
        ```
    - 完整版
        ```typescript=
        import * as WidgetModuleType from '@jupyterlab/terminal/lib/widget';
        // need to do: $jlpm add @jupyterlab/terminal

        ...
            Promise.all([app.restored]).then(() => {
              app.commands
                .execute('terminal:create-new')
                .then((terminal: WidgetModuleType.Terminal) => {
                  app.shell.add(terminal, 'header');
                });
            });
        ```

<br>

<hr>
<hr>

<br>

## 擴充元件測試
- ### [Menus](https://github.com/jupyterlab/extension-examples/tree/master/main-menu)
    ⇨ 前往：[重點整理](/OMBeTZYqS0W7fs9hdy2-kA) (#example, hello-world, getting started)
- ### [Settings](https://github.com/jupyterlab/extension-examples/tree/master/settings)
    - [schema/settings-example.json](https://github.com/jupyterlab/extension-examples/blob/master/settings/schema/settings-example.json)
    - [src/index.ts](https://github.com/jupyterlab/extension-examples/blob/master/settings/src/index.ts)


<br>
