ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

nteract 2020 年 6 月版本解读:桌面端新 UI、Core SDK 破坏性变更与 mythic-configuration 配置体系

nteract 2020 年 6 月版本解读:桌面端新 UI、Core SDK 破坏性变更与 mythic-configuration 配置体系 开发工具数据科学【免费下载链接】archived-desktop-appThe old electron based nteract notebook项目地址https://gitcode.com/gh_mirrors/nt/archived-desktop-app点击查看免费下载本篇技术指南围绕 nteract 2020 年 6 月版本发布记录changelogs/06-2020.md展开梳理该月 nteract 桌面应用推出的全新用户界面以及nteract/corev15.0.0 引入的两项破坏性变更comms状态迁移、config状态废弃与全新的mythic-configuration配置体系。读者阅读本文后将能理解 nteract 桌面端新 UI 的组成与快捷键入口掌握迁移state.comms引用的方法并学会通过defineConfigOption、setConfigFile与自定义后端为基于 nteract 的笔记本应用接入一套类型安全、可持久化、可热加载的配置系统。一、发布总览nteract 桌面应用新 UI 与 Core SDK 更新2020 年 6 月nteract 桌面应用迎来一次以「全新用户体验」为核心的版本发布同时nteract/core、nteract/commutable、nteract/editor等 Core SDK 包也发布了新版本。对于使用桌面应用的终端用户本次更新带来了界面与交互上的直观变化对于以 nteract 作为底层框架的开发者Core SDK 的破坏性变更则意味着一次必要但不复杂的迁移。桌面应用全新的界面与交互本次桌面应用发布的核心是一套全新 UI由四大部分构成应用级工具栏app-level toolbar将常用操作如新建笔记本、保存、内核操作等提升到应用全局工具栏层级避免在单个笔记本内部重复堆砌功能入口文件侧边栏file sidebar在窗口一侧提供文件浏览能力方便在多个笔记本与文档之间切换全新的单元格cell交互体验围绕代码单元、Markdown 单元的重构改进编辑、执行与结果显示流程全新的命令面板command prompt通过快捷键唤出全局命令入口macOSCmdShiftPWindows及其他平台CtrlShiftP发布记录同时预告了后续数月将基于这套新 UX 继续扩展的能力在同一菜单中打开多个笔记本、支持自定义键盘快捷键等。值得一提的是桌面应用本次还修复了「配置更改无法跨会话持久化」的缺陷——即用户修改的配置在关闭并重新打开应用后丢失的问题。这一缺陷的修复与下文 Core SDK 中config状态废弃、迁移到mythic-configuration体系直接相关新的配置体系天然支持将配置写入磁盘文件并在启动时重新加载从根因上解决了会话内配置不持久的问题。Core SDK 更新概况桌面应用之外本次发布还同步向 Core SDK 输出了以下包更新如表所示包名版本变更要点nteract/commutablev7.3.0序列化笔记本文档时跳过对输出 bundle 的重格式化nteract/corev15.0.0破坏性变更comms实体迁移至core.entitiesconfig状态废弃改用mythic-configurationnteract/editorv10.1.0自动加载编程语言的 CodeMirror 模式语法高亮发布记录特别提示如果你通过「传递依赖」的方式间接使用上述包需要同步更新其父级包以保持依赖版本一致。关于具体包的迁移细节见下文。二、桌面应用新 UI 的源码落地与实现位置新 UI 并非停留在发布记录中的描述它在当前仓库中有着清晰的代码落地。以下从源码结构角度为「应用级工具栏」「文件侧边栏」「命令面板」「新单元格 UX」逐一给出对应实现位置应用级工具栏App Toolbar位于 packages/notebook-app-component/src/notebook-apps/app-toolbar.tsx以及其配套的 stateful-components 侧的应用工具栏组件。工具栏的样式由 packages/styles/toolbar.css 提供。文件侧边栏File Sidebar / App Sidebar应用侧边栏组件见 packages/notebook-app-component/src/notebook-apps/app-sidebar.tsx 与 packages/stateful-components/src/app-sidebar/app-sidebar.tsx样式位于 packages/styles/sidebar.css。命令面板Command Palette / Command Prompt命令面板是本次新 UI 的重要交互入口。其状态管理脚本位于 packages/presentational-components/src/components/command-palette含command-palette.tsx与command-palette.ts样式位于 packages/styles/command-palette.css。快捷键Cmd/CtrlShiftP的调用链路可以追溯到桌面端快捷键声明文件 applications/desktop/src/common/accelerators.ts。新单元格 UXCell / Cell Creator / Draggable桌面端组装了拖拽式单元格与单元格创建器组合入口见 packages/notebook-app-component/src/notebook-apps/draggable-with-cell-creator.tsx 与 draggable.tsx其装饰器实现分别位于 decorators/cell-creator、decorators/draggable 目录下。样式相关文件见 packages/styles/cell-menu.css。说明以上目录结构来自当前仓库 packages 与 applications/desktop 的实际代码布局可用于对照发布记录中的 UI 描述进行进一步探索具体渲染行为以源码实现为准。自动加载语法高亮CodeMirror 模式除了 UI 之外桌面应用还新增了「自动加载编程语言语法高亮」能力。其底层实现在nteract/editorv10.1.0 中当单元格的代码语言被识别后编辑器会按需加载对应的 CodeMirror 模式文件从而避免在应用启动时就全量加载所有语言模式兼顾了高亮能力与启动性能。与编辑器相关的实现集中在 packages/editor/src其 CodeMirror 定制入口见 packages/editor/src/vendored/codemirror.ts。三、nteract/commutablev7.3.0序列化时跳过输出重格式化nteract/commutable是 nteract 中负责笔记本文档.ipynb解析、转换与序列化的核心包。v7.3.0 的变更点是在序列化笔记本文档时跳过对输出 bundlemedia bundle的重格式化。理解这一变更需要先了解 commutable 的内存表示与磁盘表示之间的差异。在 packages/commutable/src/primitives.ts 中createOnDiskMediaBundle是负责将内存中的输出 bundle 转换为「磁盘形式」的函数。从源码可以看到其正文当前直接返回mediaBundle本身注释为// Return the bundle as is而早先版本中针对数组型、字符串型输出会调用remultiline等重格式化逻辑将多行文本重新拼接——该逻辑在数据负载较大时开销明显源码中保留了对应 TODO// The remultiline function in the code below is costly when the data payload is large // TODO: figure out a configurable way to reformat the string when needed.换句话说本次变更的收益是双重的性能大体积输出例如长文本、大型数据帧在保存笔记本时不再经历一次昂贵的重格式化遍历保真内存中的输出内容与落盘内容保持一致避免因多行字符串重新拼接引入意外差异如行尾空白、缩进变化。涉及同一逻辑的序列化路径还可在 packages/commutable/src/v4.tsnbformat v4 处理中看到对应的 TODO 注释表明该重构是系统性的为了磁盘可读性而重格式化已被「按需可配置」的更优方向取代。四、nteract/corev15.0.0 破坏性变更一comms实体迁移nteract/corev15.0.0 的第一项破坏性变更与状态树布局有关comms实体列表从旧位置移动到core.entities之下。迁移判断如果你通过 nteract 官方提供的selectors 与 epics访问comms状态无需迁移任何代码——因为 selectors 与 epics 内部已经同步更新为读取新位置如果你在代码中硬编码引用了state.comms则需要将其更新为state.core.entities.comms。源码佐证当前仓库中comms相关的 reducer 与实体定义位于 packages/reducers/src/core/entities目录下包含comms.ts等多个实体 reducer并通过 packages/reducers/src/core/entities/index.ts 汇入core.entities命名空间类型定义位于 packages/types/src/entities。这与发布记录描述的「comms进入core.entities」完全一致。也就是说state.core.entities.comms是当前且后续的稳定读取路径。迁移建议在仓库内搜索所有state.comms或.comms的直接状态访问点逐一改写为经由nteract/selectors提供的 selector推荐或直接替换为state.core.entities.comms运行项目的 reducer 测试参考 packages/reducers/tests/core/index.spec.ts验证状态树形状未破坏。五、nteract/corev15.0.0 破坏性变更二config状态废弃迁移到 mythic-configuration第二项破坏性变更影响面更大config状态被废弃取而代之的是全新的nteract/mythic-configuration包。这是一次从「内置于 core 的配置状态」到「独立 mythic 包 可插拔后端」的架构升级。其直接价值包括配置状态从nteract/core中解耦任何依赖方只需引入 mythic 包即可获得配置能力配置可持久化到文件并可监听文件变化热加载修复了此前「配置无法跨会话保存」的问题配置项通过defineConfigOption声明式注册天然具备类型安全与默认值管理。新包在仓库中的实现位于 packages/mythic-configuration/src包含类型定义types.ts、包定义package.ts、后端实现backends/filesystem.ts、backends/in-memory-transient.ts以及一组 mythsloadConfig、setConfig、setConfigAtKey、setConfigBackend、toggleConfigAtKey、saveConfig。以下按发布记录给出的路线逐一讲解接入方式。5.1 方式一用makeConfigureStore组装 Store最简接入方式是使用nteract/myths提供的makeConfigureStore工厂函数其实现见 packages/myths/src/store.ts将configuration包作为普通 mythic 包挂入 storeimport { configuration } from nteract/mythic-configuration; import { makeConfigureStore } from nteract/myths; type NonPrivateState { foo: string }; const configureStore makeConfigureStoreNonPrivateState()({ packages: [ configuration, ], // reducers, epics, etc. }); export const store configureStore({ foo: bar });从 packages/myths/src/store.ts 的实现可见其组装细节makeConfigureStore会将每个包通过combineReducers汇入__private__命名空间下reducers使用pkg.rootReducerepics 使用pkg.makeRootEpic()并合并用户自定义的 reducers 与 epics。因此 mythic 包的内部状态如配置统一存储在__private__下不会与业务状态命名冲突——这也解释了后文「配置状态位于__private__.configuration」的说法。5.2 方式二手动接入 reducer 与 epic如果你已有现成的 store 组装逻辑也可以不使用makeConfigureStore而是手动接入在你的 reducer 中调用configuration.rootReducer(state, action)将其结果合并进根 reducer在你的 epics 组装中将configuration.makeRootEpic()的返回值追加到 epics 列表。两种方式的接入效果等价配置包的状态与副作用例如初始化时读取文件都会被完整接管。5.3 定义配置项defineConfigOption配置项通过defineConfigOption(...)声明式注册返回一对「selector action」import { defineConfigOption } from nteract/mythic-configuration; export const { selector: tabSize, action: setTabSize, } defineConfigOption({ label: Tab Size, key: codeMirror.tabSize, values: [ { label: 2 Spaces, value: 2 }, { label: 3 Spaces, value: 3 }, { label: 4 Spaces, value: 4 }, ], defaultValue: 4, });使用方式// 读取通过 selector 从 store 取当前值 const currentTabSize tabSize(store.getState()); // 写入dispatch 由 action 生成的 action store.dispatch(setTabSize(4));底层原理在 packages/mythic-configuration/src/index.ts 中defineConfigOption会把注册项存入模块级options注册表并为其生成selector基于configuration.createSelector创建从state.current.getIn(key.split(.))读取当前值缺省时回落到defaultValueaction返回setConfigAtKey.create({ key, value })即通过setConfigAtKeymyth 写入配置。值得注意的是defineConfigOption的防重注册校验若同一key被重复注册且规格label、key、defaultValue、values 等不一致会抛出Duplicate configuration option错误并打印新旧规格对比帮助开发者在配置项命名冲突时第一时间定位问题。写路径的完整调用链setConfigAtKeymyth见 packages/mythic-configuration/src/myths/set-config-at-key.ts在 reducer 中执行state.setIn([current, ...key.split(.)], fromJS(value))更新当前配置随后thenDispatch触发saveConfig将最新配置交给后端持久化。因此selector 始终反映 store 中的最新值而改动会立即进入保存流程。5.4 按前缀聚合配置createConfigCollection如果一组配置项共享前缀如codeMirror....可以用createConfigCollection生成整个分组的 selectorimport { createConfigCollection } from nteract/mythic-configuration; const codeMirrorConfig createConfigCollection({ key: codeMirror, });之后codeMirrorConfig(store.getState())返回形如{ tabSize: 4, // ... other options starting with codeMirror., potentially nested if more than one dot }其实现packages/mythic-configuration/src/index.ts 中的createConfigCollection会遍历已注册的全部配置项凡key以codeMirror.开头的选项若当前状态中尚无对应值则自动以该选项的defaultValue补齐再合并返回。这意味着分组 selector 返回的对象既包含用户显式设置的值也包含按默认值推导的完整配置非常适合「把一整块编辑偏好如codeMirror.*整体传给编辑器」的场景。5.5 持久化与热加载setConfigFile 文件系统后端新配置体系解决「配置无法跨会话持久化」的关键是setConfigFile// 使配置系统加载 / 写入 / 监听指定配置文件 store.dispatch(setConfigFile(/path/to/config.json));setConfigFile在 packages/mythic-configuration/src/backends/filesystem.ts 中实现它基于setConfigBackendmyth 注入文件系统后端。后端三个生命周期的行为如下生命周期行为说明setup()先立即loadConfig随后对文件调用watchFileObservable文件每次变化再次触发loadConfig启动即加载 文件热更新load()readFileObservable(filename)读取文件并JSON.parse文件不存在ENOENT时以{}兜底解析中途写入导致的SyntaxError则跳过本次加载容错处理写入中的文件save()先mkdirpObservable确保父目录存在再以JSON.stringify(current.toJSON(), undefined, 2)格式化写入目录自动创建 2 空格缩进的可读 JSONsetConfigBackendmythpackages/mythic-configuration/src/myths/set-config-backend.ts在 reducer 中将新后端写入状态并在thenDispatch中立即调用backend.setup()从而完成后端的初始化。默认后端nteract/mythic-configuration的configuration包package.ts默认使用inMemoryConfigurationBackendbackends/in-memory-transient.ts其setup/load/save均为空 Observable——即「临时内存配置不持久化」。只有在调用setConfigFile(path)或注入自定义后端后配置才具备持久化能力。5.6 自定义持久化后端ConfigurationBackend接口如果文件不是理想的持久化介质例如配置需要存到远程服务、数据库或某些特殊存储可以自行实现ConfigurationBackend并注入。接口定义见 packages/mythic-configuration/src/types.tsinterface ConfigurationBackend { setup: () Observabletypeof loadConfig.action; load: () Observabletypeof setConfig.action; save: (current: Configuration) Observableany; }三个方法的语义setup()后端初始化时被调用通常返回一个「何时加载配置」的 Observable——典型做法是用loadConfig.create()指定加载时机load()负责读取配置返回的 Observable 通常用setConfig.create或setConfigAtKey把数据写入状态save(current)配置变更后被调用入参是当前完整配置Mapstring, any一般负责持久化返回值 Observable 通常为空除非保存后需要派发其他动作。发布记录中的「猫咪后端」示例完整展示了自定义后端的写法——用一个诙谐但结构完整的例子演示setup/load/save三个生命周期以下为略作格式整理的版本// Since the cats are typically lazing about the computer, lets utilize them to store our config... const catConfigurationBackend (whichCats: Cat[]) ({ setup: () // Is called when the config system initialises, should return an ObservableAction, // generally using the loadConfig myth to specify when the config should be loaded. concat( of(immediately), interval(10 * 60 * 1000), ).pipe( tap(_ wakeUpCats(whichCats)), mapTo(loadConfig.create()), ), load: () // Is called to load config, should return an ObservableAction, generally using // the setConfig and/or setConfigAtKey myths to determine the config. askTheCatsAboutTheirConfigOptions(whichCats).pipe( mapErrorTo(undefined, error error?.complaint HUNGRY), skipWhile(data data undefined), map(setConfig.create), ), save: (current: Mapstring, any) // Is called with the current config object to save it after it changed, should return an // ObservableAction, which should be empty unless you need to dispatch actions on save. tellTheCatsToRememberConfigOptions(current.toJSON(), whichCats).pipe( ignoreElements(), ), } as ConfigurationBackend); export const setConfigCats (whichCats: Cat[]) setConfigBackend.create(catConfigurationBackend(whichCats)); // Now just do store.dispatch(setConfigCats(...)) to start using it and hope the cats have good // memory and feel like cooperating...注入方式与文件后端完全一致store.dispatch(setConfigCats([...cats]))即会走setConfigBackendmyth 完成后端替换与初始化。注意其中current.toJSON()的用法入参current是 ImmutableMap保存前需要转换为普通 JSON 对象。5.7 内部状态位置与类型辅助配置状态存放在 store 的__private__.configuration之下__private__命名空间由makeConfigureStore统一管理见 packages/myths/src/store.ts日常使用中无需直接访问通过 selector 即可需要为 state/store 补充类型时使用类型HasPrivateConfigurationState定义于 packages/mythic-configuration/src/types.ts本质是RootStateconfiguration, ConfigurationStateConfigurationState的形态为{ backend: ConfigurationBackend; current: Configuration }其中current是 ImmutableMapstring, any用于承载所有已注册配置项的当前值。5.8 底层 myths加载、保存、切换与废弃迁移mythic-configuration是一组 myth 的集合理解这些 myth 有助于自定义后端时正确选用loadConfigmyths/load-config.tsthenDispatch中直接调用state.backend.load()是「触发后端读取配置」的入口setConfigmyths/set-config.ts以fromJS将整个配置对象写入state.current并自动执行废弃键迁移若传入配置中包含已注册的废弃键deprecated则先根据changeTo映射生成新键移除旧键后再写入setConfigAtKeymyths/set-config-at-key.ts按点分路径写入单个键并自动触发saveConfigtoggleConfigAtKeymyths/toggle-config-at-key.ts读取某配置项values列表在多个枚举值之间循环切换例如 2 → 3 → 4 → 2适合「三态/多态选项」的 UI 交互setConfigBackendmyths/set-config-backend.ts替换后端并调用新后端的setup()。setConfig中的废弃键迁移逻辑意味着从旧config状态迁移到新体系时若旧配置文件中存在废弃配置键加载时会被自动映射为新键减少了用户手动迁移配置数据的成本。六、nteract/editorv10.1.0CodeMirror 语言模式自动加载nteract/editorv10.1.0 为桌面应用的「自动加载语法高亮」提供了包级支撑根据单元格当前代码语言按需加载对应的 CodeMirror 模式而不是在应用初始化时一次性加载全部语言。相关实现位于 packages/editor/src其中模式相关逻辑集中在 packages/editor/src/mode如ipython.tsCodeMirror 的定制与 vendor 文件见 packages/editor/src/vendored/codemirror.ts编辑器主组件 packages/editor/src/index.tsx 将语言与模式绑定落实到单元格渲染。由于本次发布同时涉及桌面应用与 Core SDK若你以依赖方式使用nteract/editor建议升级到 v10.1.0 以同步获得语言模式自动加载能力。七、迁移清单与验证建议综合本月的破坏性变更为使用nteract/corev15.0.0 的应用整理迁移清单如下comms引用迁移将硬编码的state.comms改写为state.core.entities.comms或改用nteract/selectors提供的 selectorconfig状态废弃移除对旧state.config的直接依赖引入nteract/mythic-configuration用makeConfigureStore挂入configuration包或手动接入configuration.rootReducer与configuration.makeRootEpic()将原有配置项逐一改写为defineConfigOption({ label, key, values, defaultValue })需要持久化时 dispatchsetConfigFile(path)或注入自定义ConfigurationBackend传递依赖升级检查nteract/commutablev7.3.0、nteract/corev15.0.0、nteract/editorv10.1.0的父级包版本确保依赖树统一验证运行各包测试如 packages/mythic-configuration/tests/configuration.spec.ts、packages/reducers/tests/core/index.spec.ts并手动验证修改配置 → 重启应用 → 配置仍然生效。配置系统的完整测试用例位于 packages/mythic-configuration/tests/configuration.spec.ts其中覆盖了配置项定义、值读写、后端切换与持久化行为可作为接入后的回归参考。八、小结2020 年 6 月的 nteract 发布同时推进了面向用户与面向开发者的两条线终端用户获得应用级工具栏、文件侧边栏、命令面板Cmd/CtrlShiftP与全新单元格交互开发者则收到nteract/corev15.0.0 的破坏性变更——comms迁移至core.entities、config状态让位于nteract/mythic-configuration。后者并非简单的「换汤不换药」defineConfigOption提供了声明式、类型安全、带默认值与防重注册校验的配置项注册setConfigFile与文件系统后端赋予配置「启动加载 文件热更新 自动持久化」的能力ConfigurationBackend接口则让任意存储介质文件、网络、乃至猫咪内存都能成为配置的归宿。结合桌面端此前「配置无法跨会话保存」的缺陷修复这一新体系从架构上为 nteract 及其衍生应用提供了可持续演进的配置基础设施。赞分享开发工具数据科学【免费下载链接】archived-desktop-appThe old electron based nteract notebook项目地址https://gitcode.com/gh_mirrors/nt/archived-desktop-app点击查看免费下载相关推荐Android Auto 头单元解码卡死排查指南3 个标签精确定位视频冻结Android Auto 头单元解码卡死排查指南3 个标签精确定位视频冻结 Open Headunit 是一个把 Android 平板变成 Android A开发工具数据科学TypeSpec 2023年7月版本更新详解内置 Linter、Emitter 框架增强与破坏性变更TypeSpec 2023年7月版本更新详解内置 Linter、Emitter 框架增强与破坏性变更 导读 本文基于 TypeSpec 官方仓库 relea编程语言编译器后端Orchard Core 1.0.0-RC2 版本全解析破坏性变更、新特性与源码级解读Orchard Core 1.0.0 RC2 版本全解析破坏性变更、新特性与源码级解读 本文基于 src/docs/releases/1.0.0 rc2.mdCMS后端Web框架上一篇猫抓资源嗅探工具终极指南3分钟学会把网页视频音频一键存到本地下一篇用 Metaflow Client API 搭建流程监控仪表盘07-worldview 教程全解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表