Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 3 additions & 3 deletions command-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
"alias": [],
"command": "lightning:dev:component",
"flagAliases": [],
"flagChars": ["c", "n", "o"],
"flags": ["client-select", "flags-dir", "json", "name", "target-org"],
"flagChars": ["c", "n", "o", "p"],
"flags": ["client-select", "flags-dir", "json", "name", "performance", "target-org"],
"plugin": "@salesforce/plugin-lightning-dev"
},
{
"alias": [],
"command": "lightning:dev:site",
"flagAliases": [],
"flagChars": ["l", "n", "o"],
"flags": ["flags-dir", "get-latest", "guest", "name", "target-org", "ssr"],
"flags": ["flags-dir", "get-latest", "guest", "name", "ssr", "target-org"],
"plugin": "@salesforce/plugin-lightning-dev"
}
]
10 changes: 10 additions & 0 deletions messages/lightning.dev.component.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Name of a component to preview.

Launch component preview without selecting a component

# flags.performance.summary

@lesya7 lesya7 Aug 26, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if I don't pass the "performance" flag? Would I be able to see the "performance" link by clicking on the "Performance" link?

@bpbuch bpbuch Aug 26, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The same operation is available in the header of the default page in the preview application.

This flag would save the user the extra step of navigating into "performance" mode" if that is their target destination.


Open the component preview in performance mode

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the short term, I would prefer to not codify performance mode in the CLI flags. I'm not in love with the name for performance mode and I don't know that its intuitive why I would run in performance mode vs not. This seems like more of an app metadata conversation - if we are previewing a root component for an app, we should show the preview in full screen mode.

Would you be ok with just using an environment variable for now (which would still allow us to support the hackathon)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to other names for the flag. This name stems from the nav item in the header of the default application page(which can also change). cc @marcelinollano

I believe the CLI should be able to perform the same actions as the default application view. Today, the CLI can launch into the preview application with and without a selected component, but it cannot launch into the "performance" view.

I agree the naming is a bit unintuitive, but there is value in being able to preview a component without the "preview application chrome", especially for large components.


# error.directory

Unable to find components
Expand All @@ -40,9 +44,15 @@ Failed to parse component metadata at: %s

Unable to find component with name: %s

# error.performance-client-select-conflict

Cannot use --performance flag when --client-select is enabled

# examples

- Select a component and launch the component preview:
<%= config.bin %> <%= command.id %>
- Launch component preview for "myComponent":
<%= config.bin %> <%= command.id %> --name myComponent
- Launch component preview for "myComponent" in performance mode:
<%= config.bin %> <%= command.id %> --name myComponent --performance
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
],
"target": {
"versionNumber": "66.0",
"matchingDevServerVersion": "~13.0.27"
"matchingDevServerVersion": "~13.2.2"
},
"versionToTagMappings": [
{
Expand Down
13 changes: 12 additions & 1 deletion src/commands/lightning/dev/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export default class LightningDevComponent extends SfCommand<void> {
char: 'c',
default: false,
}),
performance: Flags.boolean({
summary: messages.getMessage('flags.performance.summary'),
char: 'p',
default: false,
}),
'target-org': Flags.requiredOrg(),
};

Expand All @@ -53,8 +58,13 @@ export default class LightningDevComponent extends SfCommand<void> {

let componentName = flags['name'];
const clientSelect = flags['client-select'];
const performanceMode = flags['performance'];
const targetOrg = flags['target-org'];

if (performanceMode && clientSelect) {
throw new Error(messages.getMessage('error.performance-client-select-conflict'));
}

const { ldpServerId, ldpServerToken } = await PreviewUtils.initializePreviewConnection(targetOrg);

logger.debug('Determining the next available port for Local Dev Server');
Expand Down Expand Up @@ -126,7 +136,8 @@ export default class LightningDevComponent extends SfCommand<void> {
ldpServerUrl,
ldpServerId,
componentName,
targetOrgArg
targetOrgArg,
performanceMode
);

// Open the browser and navigate to the right page
Expand Down
7 changes: 6 additions & 1 deletion src/shared/previewUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,15 @@ export class PreviewUtils {
* @param ldpServerId Record ID for the identity token
* @param componentName The name of the component to preview
* @param targetOrg An optional org id
* @param performanceMode Whether to enable performance mode
* @returns Array of arguments to be used by Org:Open command for launching the component preview
*/
public static generateComponentPreviewLaunchArguments(
ldpServerUrl: string,
ldpServerId: string,
componentName?: string,
targetOrg?: string
targetOrg?: string,
performanceMode?: boolean
): string[] {
let appPath = `lwr/application/e/devpreview/ai/${encodeURIComponent(
'localdev%2Fpreview'
Expand All @@ -236,6 +238,9 @@ export class PreviewUtils {
// TODO: support other namespaces
appPath += `&specifier=c/${componentName}`;
}
if (performanceMode) {
appPath += '&mode=performance';
}

const launchArguments = ['--path', appPath];

Expand Down
27 changes: 20 additions & 7 deletions test/commands/lightning/dev/component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,34 @@
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { TestContext } from '@salesforce/core/testSetup';
// import { expect } from 'chai';
// import { stubSfCommandUx } from '@salesforce/sf-plugins-core';
import { Messages } from '@salesforce/core';
import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup';
import { stubUx } from '@salesforce/sf-plugins-core';
import { expect } from 'chai';
import LightningDevComponent from '../../../../src/commands/lightning/dev/component.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);

describe('lightning single component preview', () => {
const messages = Messages.loadMessages('@salesforce/plugin-lightning-dev', 'lightning.dev.component');
const $$ = new TestContext();
// let sfCommandStubs: ReturnType<typeof stubSfCommandUx>;
const testOrgData = new MockTestOrgData();

beforeEach(() => {
// sfCommandStubs = stubSfCommandUx($$.SANDBOX);
beforeEach(async () => {
stubUx($$.SANDBOX);
await $$.stubAuths(testOrgData);
});

afterEach(() => {
$$.restore();
});

it('todo add unit tests', async () => {});
it('should throw error when both client-select and performance flags are used', async () => {
try {
await LightningDevComponent.run(['--client-select', '--performance', '--target-org', testOrgData.orgId]);
expect.fail('Expected command to throw an error');
} catch (error) {
expect((error as Error).message).to.equal(messages.getMessage('error.performance-client-select-conflict'));
}
});
});
71 changes: 71 additions & 0 deletions test/shared/previewUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,77 @@ describe('previewUtils', () => {
expect(parsed.values['target-org']).to.be.undefined;
});

it('generateComponentPreviewLaunchArguments with performance mode enabled', async () => {
Comment thread
bpbuch marked this conversation as resolved.
const result = PreviewUtils.generateComponentPreviewLaunchArguments(
'https://localhost:3333',
testLdpServerId,
'myTestComponent',
'myTargetOrg',
true
);

const parsed = parseArgs({
args: result,
options: {
path: { type: 'string' },
'target-org': { type: 'string' },
},
});

expect(parsed.values.path).to.include('ldpServerUrl=https://localhost:3333');
expect(parsed.values.path).to.include(`ldpServerId=${testLdpServerId}`);
expect(parsed.values.path).to.include('specifier=c/myTestComponent');
expect(parsed.values.path).to.include('mode=performance');
expect(parsed.values['target-org']).to.equal('myTargetOrg');
});

it('generateComponentPreviewLaunchArguments with performance mode disabled', async () => {
const result = PreviewUtils.generateComponentPreviewLaunchArguments(
'https://localhost:3333',
testLdpServerId,
'myTestComponent',
'myTargetOrg',
false
);

const parsed = parseArgs({
args: result,
options: {
path: { type: 'string' },
'target-org': { type: 'string' },
},
});

expect(parsed.values.path).to.include('ldpServerUrl=https://localhost:3333');
expect(parsed.values.path).to.include(`ldpServerId=${testLdpServerId}`);
expect(parsed.values.path).to.include('specifier=c/myTestComponent');
expect(parsed.values.path).to.not.include('mode=performance');
expect(parsed.values['target-org']).to.equal('myTargetOrg');
});

it('generateComponentPreviewLaunchArguments with performance mode undefined (default)', async () => {
const result = PreviewUtils.generateComponentPreviewLaunchArguments(
'https://localhost:3333',
testLdpServerId,
'myTestComponent',
'myTargetOrg'
);

const parsed = parseArgs({
args: result,
options: {
path: { type: 'string' },
'target-org': { type: 'string' },
},
});

expect(parsed.values.path).to.include('ldpServerUrl=https://localhost:3333');
expect(parsed.values.path).to.include(`ldpServerId=${testLdpServerId}`);
expect(parsed.values.path).to.include('specifier=c/myTestComponent');
expect(parsed.values.path).to.not.include('mode=performance');
expect(parsed.values['target-org']).to.equal('myTargetOrg');
});

it('getTargetOrgFromArguments finds -o flag', async () => {
const args = ['command', '-o', 'myOrg', 'otherArg'];
const result = PreviewUtils.getTargetOrgFromArguments(args);
Expand Down
Loading