devtools-setting-migration
GitHub指导将旧的 SettingRegistration 重构为 SettingDescriptor 和 SettingUIDescriptor,明确分层存储规则以优化模块边界和懒加载。
Trigger Scenarios
Install
npx skills add ChromeDevTools/devtools-frontend --skill devtools-setting-migration -g -y
SKILL.md
Frontmatter
{
"name": "devtools-setting-migration",
"description": "Workflow for splitting an existing SettingRegistration into a SettingDescriptor (placed in the lowest layer where used: core\/, models\/, or ui\/settings\/) and SettingUIDescriptor (registered in a higher-level -meta.ts file, outside of core\/ and models\/)."
}
DevTools Setting Migration Guide
This skill guide describes how to migrate an existing legacy SettingRegistration in DevTools by splitting it into a SettingDescriptor (non-UI descriptor) and a SettingUIDescriptor (UI descriptor).
Key Principles & Layer Boundaries
1. SettingDescriptor Location ("Lowest Layer")
- Lowest Layer Rule: A
SettingDescriptorMUST be placed in the lowest architectural layer where the setting is used.- Core / Model Settings: If a setting is used by
core/sdk(ormodels/), itsSettingDescriptorshould be located incore/sdk(ormodels/). - Panel / UI Settings: If a setting is only used by UI components or a specific panel (e.g.
panels/console/), itsSettingDescriptorMUST GO INTOui/settings/FooSettings.ts(e.g.ui/settings/ConsoleSettings.tswhereFoois the panel name).
- Core / Model Settings: If a setting is used by
- CRITICAL RULE — PANEL DESCRIPTORS MUST NOT BE PLACED IN
panels/:- A
SettingDescriptorMUST NOT be placed inside apanels/directory (e.g.panels/console/ConsoleSettings.ts). - Reason: Panel
-meta.tsfiles (e.g.panels/console/console-meta.ts) need to import theSettingDescriptorto callSettingsUI.SettingUIRegistration.register(descriptor, uiDescriptor).-meta.tsfiles are loaded early and MUST NOT import frompanels/(which would break lazy-loading of panel bundles). Sinceui/settings/is in theui/layer belowpanels/,-meta.tsfiles can safely import fromui/settings/.
- A
- CRITICAL RULE — MUST NOT BE IN A
-meta.tsFILE:- A
SettingDescriptorMUST NOT be placed in a-meta.tsfile. - Reason: Actual runtime code (e.g. models, panels, SDKs) needs to import the descriptor directly to call
Settings.instance().resolve(descriptor). Preload-meta.tsfiles are meant for lazy-loaded extension registrations and must not be imported by runtime code to avoid circular dependencies and module boundary violations.
- A
2. SettingUIDescriptor Location (Higher-Level -meta.ts File)
- A
SettingUIDescriptordefines UI-specific properties (category, title, tags, options, reload requirement, etc.). - Higher-Level Meta File Rule: UI registrations MUST BE PLACED IN A
-meta.tsFILE ON A HIGHER LEVEL (e.g.,entrypoints/main/main-meta.ts,entrypoints/inspector_main/inspector_main-meta.ts,panels/settings/settings-meta.ts, or the specific panel's-meta.tsfile). - CRITICAL RULE — MUST NOT REMAIN IN
core/ORmodels/:- UI descriptors MUST NOT remain in or be added to
-meta.tsfiles undercore/ormodels/(such ascore/sdk/sdk-meta.tsormodels/*/*-meta.ts). - Goal: A major goal of this migration is to completely eliminate
-meta.tsfiles incore/andmodels/.
- UI descriptors MUST NOT remain in or be added to
3. Resolving Settings vs moduleSetting(name)
- Legacy code retrieves settings using string identifiers:
Settings.instance().moduleSetting('setting-name'). - Refactored code should replace
moduleSetting('setting-name')withSettings.instance().resolve(settingDescriptor).
Step-by-Step Migration Workflow
Given a setting name (e.g., 'preserve-console-log' or 'network-messages'):
Step 1: Locate Existing Registration & Analyze Use-Sites
- Search for the setting name in
-meta.tsfiles to find itsCommon.Settings.registerSettingExtensionblock. - Search for all occurrences of
'setting-name'ormoduleSetting('setting-name')across the codebase to identify all use-sites. - Determine the lowest layer among all use-sites:
- If used in
core/sdk-> Target directory iscore/sdk/. - If used in
models/-> Target directory ismodels/<module>/. - If used in a panel (
panels/foo) or UI -> Target directory isui/settings/(file:ui/settings/FooSettings.ts). NEVER place descriptors inpanels/.
- If used in
Step 2: Extract & Define SettingDescriptor in the Lowest Layer
Decision Strategy: Create vs. Update File
When placing a SettingDescriptor in the target directory, decide whether to create or update a file using these rules:
-
For Panel / UI Settings (Target is
ui/settings/):- UPDATE: Check if
ui/settings/FooSettings.tsalready exists (e.g.,ui/settings/ConsoleSettings.ts). If so, add and export theSettingDescriptorthere. - CREATE: If
ui/settings/FooSettings.tsdoes not exist:- Create
ui/settings/FooSettings.ts. - Add
FooSettings.tstosourcesinui/settings/BUILD.gn. - Export
FooSettings.tsfromui/settings/settings.ts.
- Create
- UPDATE: Check if
-
For Core / Model Settings (Target is
core/ormodels/):- UPDATE: Check if a module-wide settings file exists in that directory (e.g.
core/sdk/SDKSettings.ts,models/workspace/WorkspaceSettings.ts). If so, add and export theSettingDescriptorthere. - UPDATE: If no module settings file exists and the setting is strictly used inside a single file (e.g.,
ResourceTreeModel.ts), update that.tsfile by exporting theSettingDescriptorat the top. - CREATE: Otherwise, create
<Module>Settings.ts(e.g.,core/sdk/SDKSettings.ts), add it tosourcesinBUILD.gn, and export it from the module's entrypoint (sdk.ts).
- UPDATE: Check if a module-wide settings file exists in that directory (e.g.
Code Definition Example:
Define and export the SettingDescriptor in the target file:
import type * as Common from '../core/common/common.js';
export const preserveConsoleLogSettingDescriptor: Common.Settings.SettingDescriptor<boolean> = {
name: 'preserve-console-log',
type: Common.Settings.SettingType.BOOLEAN,
defaultValue: false,
storageType: Common.Settings.SettingStorageType.SYNCED,
};
Note: For conditional settings (dependent on hostConfig), use Common.Settings.ConditionalSettingDescriptor<ValueT, ReasonT> with an isAvailable function.
Step 3: Move UI Registration to a Higher-Level -meta.ts File
If the original registration was in a core/ or models/ -meta.ts file (e.g., core/sdk/sdk-meta.ts), MOVE the UI registration to a higher-level -meta.ts file (e.g., entrypoints/main/main-meta.ts or panels/console/console-meta.ts).
In the higher-level -meta.ts file:
- Import
SettingsUIfromui/settings/settings.js(e.g.,import * as SettingsUI from '../../ui/settings/settings.js';). - Import the
SettingDescriptor(fromcore/sdk/,models/, orui/settings/). - Register using
SettingsUI.SettingUIRegistration.register(...):
import * as SettingsUI from '../../ui/settings/settings.js';
import * as SDK from '../../core/sdk/sdk.js';
SettingsUI.SettingUIRegistration.register(SDK.SDKSettings.preserveConsoleLogSettingDescriptor, {
category: Common.Settings.SettingCategory.CONSOLE,
title: i18nLazyString(UIStrings.preserveLogUponNavigation),
options: [
{
value: true,
title: i18nLazyString(UIStrings.preserveLogUponNavigation),
},
{
value: false,
title: i18nLazyString(UIStrings.doNotPreserveLogUponNavigation),
},
],
});
- Delete the old
Common.Settings.registerSettingExtensioncall from thecore/ormodels/-meta.tsfile. (If the-meta.tsfile becomes empty, delete the file and clean up its build references).
Step 4: Update Call Sites (moduleSetting to resolve)
Find all call sites referencing the setting via moduleSetting:
// BEFORE:
const setting = Common.Settings.Settings.instance().moduleSetting('preserve-console-log');
// AFTER:
import { preserveConsoleLogSettingDescriptor } from './SDKSettings.js';
...
const setting = Common.Settings.Settings.instance().resolve(preserveConsoleLogSettingDescriptor);
For conditional settings, use Common.Settings.Settings.instance().maybeResolve(descriptor) instead of resolve(descriptor).
Step 5: Update BUILD.gn Files and Module Entrypoints
- If a new
.tsfile was created (e.g.,SDKSettings.tsorui/settings/ConsoleSettings.ts):- Add the file to
sourcesin its module'sBUILD.gn. - Export the file from the module's entrypoint (
sdk.ts,settings.ts, etc.).
- Add the file to
- If a
core/ormodels/-meta.tsfile was deleted, remove it fromBUILD.gnanddevtools_grd_files.gni. - Verify module imports strictly follow DevTools import rules (refer to
devtools-importsskill).
Step 6: Verify Changes
- Run
autoninja -C out/Defaultto check GN build. - Run
npm run lintto check style and formatting rules. - Run relevant unit tests for the modified module.
Concrete Examples
Example 1: Core/SDK Setting Migration (preserve-console-log)
Before Migration
Setting registered in front_end/core/sdk/sdk-meta.ts (Legacy core meta file):
Common.Settings.registerSettingExtension({
category: Common.Settings.SettingCategory.CONSOLE,
storageType: Common.Settings.SettingStorageType.SYNCED,
title: i18nLazyString(UIStrings.preserveLogUponNavigation),
settingName: 'preserve-console-log',
settingType: Common.Settings.SettingType.BOOLEAN,
defaultValue: false,
options: [...],
});
Setting used in front_end/core/sdk/ResourceTreeModel.ts:
const setting = Common.Settings.Settings.instance().moduleSetting('preserve-console-log');
After Migration
front_end/core/sdk/SDKSettings.ts(Lowest Layer in Core — NOT a-meta.tsfile):
import type * as Common from '../common/common.js';
export const preserveConsoleLogSettingDescriptor: Common.Settings.SettingDescriptor<boolean> = {
name: 'preserve-console-log',
type: Common.Settings.SettingType.BOOLEAN,
defaultValue: false,
storageType: Common.Settings.SettingStorageType.SYNCED,
};
front_end/entrypoints/main/main-meta.ts(Higher-Level Meta File — NOT incore/ormodels/):
import * as SDK from '../../core/sdk/sdk.js';
import * as SettingsUI from '../../ui/settings/settings.js';
SettingsUI.SettingUIRegistration.register(SDK.SDKSettings.preserveConsoleLogSettingDescriptor, {
category: Common.Settings.SettingCategory.CONSOLE,
title: i18nLazyString(UIStrings.preserveLogUponNavigation),
options: [...],
});
front_end/core/sdk/ResourceTreeModel.ts(Call Site incore/sdk):
import { preserveConsoleLogSettingDescriptor } from './SDKSettings.js';
const setting = Common.Settings.Settings.instance().resolve(preserveConsoleLogSettingDescriptor);
front_end/core/sdk/sdk-meta.ts: Registration for'preserve-console-log'removed.
Example 2: Panel UI Setting Migration (network-messages)
Before Migration
Setting registered in front_end/panels/console/console-meta.ts:
Common.Settings.registerSettingExtension({
category: Common.Settings.SettingCategory.CONSOLE,
storageType: Common.Settings.SettingStorageType.SYNCED,
title: i18nLazyString(UIStrings.networkMessages),
settingName: 'network-messages',
settingType: Common.Settings.SettingType.BOOLEAN,
defaultValue: true,
options: [...],
});
Setting used in front_end/panels/console/ConsoleView.ts:
const setting = Common.Settings.Settings.instance().moduleSetting('network-messages');
After Migration
front_end/ui/settings/ConsoleSettings.ts(Lowest Layer for UI/Panel Descriptor — NOT inpanels/console/!):
import type * as Common from '../../core/common/common.js';
export const networkMessagesSettingDescriptor: Common.Settings.SettingDescriptor<boolean> = {
name: 'network-messages',
type: Common.Settings.SettingType.BOOLEAN,
defaultValue: true,
storageType: Common.Settings.SettingStorageType.SYNCED,
};
front_end/panels/console/console-meta.ts(Panel Meta File — Imports Descriptor fromui/settings/):
import * as SettingsUI from '../../ui/settings/settings.js';
SettingsUI.SettingUIRegistration.register(SettingsUI.ConsoleSettings.networkMessagesSettingDescriptor, {
category: Common.Settings.SettingCategory.CONSOLE,
title: i18nLazyString(UIStrings.networkMessages),
options: [...],
});
front_end/panels/console/ConsoleView.ts(Call Site inpanels/console):
import * as SettingsUI from '../../ui/settings/settings.js';
const setting = Common.Settings.Settings.instance().resolve(SettingsUI.ConsoleSettings.networkMessagesSettingDescriptor);
Interface Reference Summary
SettingDescriptor<T>
Defined in core/common/Settings.ts:
name: string: Unique setting name (kebab-case).type: SettingType:BOOLEAN,ENUM,ARRAY, orREGEX.defaultValue: ValueT | ((hostConfig: HostConfig) => ValueT): Default setting value.storageType?: SettingStorageType:SYNCED,LOCAL,GLOBAL, orSESSION.
SettingUIDescriptor
Defined in ui/settings/SettingUIRegistration.ts:
category?: SettingCategory: Category under which setting is listed in Settings UI.order?: number: Sorting order.title?: () => LocalizedString: Title string displayed in Settings UI.tags?: Array<() => LocalizedString>: Search tags for Command Menu.options?: SettingExtensionOption[]: Enum / boolean option descriptions.reloadRequired?: boolean: Whether setting change requires DevTools reload.deprecationNotice?: { disabled: boolean, warning: () => LocalizedString, experiment?: string }: Deprecation notice.learnMore?: LearnMore: Help link or tooltip info.
Version History
- 678d19c Current 2026-08-20 15:20


