Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
57 changes: 8 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,59 +69,22 @@ sf plugins link .
sf plugins
```

## LWR Sites Development Environment
## Debugging

Follow these instructions if you want to setup a dev environment for the `sf lightning dev site` command.

## Setup

1. [Enable Local Development](https://developer.salesforce.com/docs/platform/lwc/guide/get-started-test-components.html#enable-local-dev)

2. Deploy some source files to your org from your SFDX project

```bash
sf org login web --alias dev --instance-url ${orgfarmUrl}

```

3. Add those source files to an LWR site in the Experience Builder and Publish the site (basePath: '/')

4. Follow the [Build the plugin locally](#build) instructions

5. [optional] Linking / Debugging LWR Source
To debug the plugin, you can use the Node.js debugger:

```bash
# build and link lwr source
cd lwr
yarn && yarn link-lwr

# build and link plugin-lightning-dev source
cd plugin-lightning-dev
yarn && yarn build
yarn link-lwr

# SFDX Project
cd sfdx-project

# Login to your org
sf org login web --alias dev --instance-url https://login.test1.pc-rnd.salesforce.com/ (orgfarm needs instance url)

# run/debug the sf cli command (attach to the CLI from the LWR repo in VS Code)
NODE_OPTIONS="--inspect-brk" sf lightning dev site --target-org dev
# Run with debugger attached
NODE_OPTIONS="--inspect-brk" sf lightning dev site --target-org <your-org>
```

Now you can Remote Attach to the CLI from the vscode debugger:

- Use the "Attach" launch configuration
- Run launch config from LWR repo if you want to debug LWR source
- Run launch config from plugin-lightning-dev source if you want to debug the SFDX plugin source specifically
Now you can attach to the process from your IDE's debugger using the "Attach" launch configuration.

If this doesn't work for whatever reason, you can always alias the build output directly like so:
Alternatively, you can alias the build output directly:

```bash
alias sfdev="/{pathToGitDir}/plugin-lightning-dev/bin/run.js"
# SFDX Project
NODE_OPTIONS="--inspect-brk" sfdev lightning dev site --target-org dev
NODE_OPTIONS="--inspect-brk" sfdev lightning dev site --target-org <your-org>
```

6. Make changes to your c-namespace components and you should see the browser refresh with those changes!
Expand Down Expand Up @@ -256,17 +219,13 @@ _See code: [src/commands/lightning/dev/component.ts](https://github.com/salesfor

```
USAGE
$ sf lightning dev site -o <value> [--flags-dir <value>] [-n <value>] [-l] [--guest] [--ssr]
$ sf lightning dev site -o <value> [--flags-dir <value>] [-n <value>]

FLAGS
-l, --get-latest Download the latest version of the specified site from your org, instead of using any local
cache.
-n, --name=<value> Name of the Experience Builder site to preview. It has to match a site name from the current
org.
-o, --target-org=<value> (required) Username or alias of the target org. Not required if the `target-org`
configuration variable is already set.
--guest Preview the site as a guest user (rather than an authenticated user).
--ssr Preview the SSR bundle

GLOBAL FLAGS
--flags-dir=<value> Import flag values from a directory.
Expand Down
78 changes: 53 additions & 25 deletions command-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,54 @@
[
{
"alias": [],
"command": "lightning:dev:app",
"flagAliases": [],
"flagChars": ["i", "n", "o", "t"],
"flags": ["device-id", "device-type", "flags-dir", "name", "target-org"],
"plugin": "@salesforce/plugin-lightning-dev"
},
{
"alias": [],
"command": "lightning:dev:component",
"flagAliases": [],
"flagChars": ["c", "n", "o"],
"flags": ["client-select", "flags-dir", "json", "name", "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"],
"plugin": "@salesforce/plugin-lightning-dev"
}
]
{
"alias": [],
"command": "lightning:dev:app",
"flagAliases": [],
"flagChars": [
"i",
"n",
"o",
"t"
],
"flags": [
"device-id",
"device-type",
"flags-dir",
"name",
"target-org"
],
"plugin": "@salesforce/plugin-lightning-dev"
},
{
"alias": [],
"command": "lightning:dev:component",
"flagAliases": [],
"flagChars": [
"c",
"n",
"o"
],
"flags": [
"client-select",
"flags-dir",
"json",
"name",
"target-org"
],
"plugin": "@salesforce/plugin-lightning-dev"
},
{
"alias": [],
"command": "lightning:dev:site",
"flagAliases": [],
"flagChars": [
"n",
"o"
],
"flags": [
"flags-dir",
"name",
"target-org"
],
"plugin": "@salesforce/plugin-lightning-dev"
}
]
14 changes: 0 additions & 14 deletions messages/lightning.dev.site.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,9 @@ For more considerations and limitations, see the Lightning Web Components Develo

Name of the Experience Builder site to preview. It has to match a site name from the current org.

# flags.get-latest.summary

Download the latest version of the specified site from your org, instead of using any local cache.

# flags.guest.summary

Preview the site as a guest user (rather than an authenticated user).

# flags.ssr.summary

Preview the SSR bundle

# examples

- Select a site to preview from the org "myOrg":
<%= config.bin %> <%= command.id %> --target-org myOrg
- Preview the site "Partner Central" from the org "myOrg":
<%= config.bin %> <%= command.id %> --name "Partner Central" --target-org myOrg
- Get and preview the latest version of the "Partner Central" site from the org "myOrg"
<%= config.bin %> <%= command.id %> --name "Partner Central" --target-org myOrg --get-latest
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
"@inquirer/select": "^2.4.7",
"@lwc/lwc-dev-server": "~13.2.19",
"@lwc/sfdc-lwc-compiler": "~13.2.19",
"@lwrjs/api": "0.18.3",
"@oclif/core": "^4.5.6",
"@salesforce/core": "^8.23.3",
"@salesforce/kit": "^3.2.4",
"@salesforce/lwc-dev-mobile-core": "4.0.0-alpha.14",
"@salesforce/sf-plugins-core": "^11.2.4",
"axios": "^1.13.2",
"glob": "^10.4.5",
"glob": "^10.5.0",
"lwc": "~8.24.0",
"node-fetch": "^3.3.2",
"open": "^10.2.0",
Expand Down Expand Up @@ -96,15 +95,13 @@
"fix-license": "eslint src test --fix --rule \"header/header: [2]\"",
"format": "wireit",
"link-check": "wireit",
"link-lwr": "yarn link @lwrjs/api @lwrjs/app-service @lwrjs/asset-registry @lwrjs/asset-transformer @lwrjs/auth-middleware @lwrjs/base-view-provider @lwrjs/base-view-transformer @lwrjs/client-modules @lwrjs/config @lwrjs/core @lwrjs/dev-proxy-server @lwrjs/diagnostics @lwrjs/esbuild @lwrjs/everywhere @lwrjs/fs-asset-provider @lwrjs/fs-watch @lwrjs/html-view-provider @lwrjs/instrumentation @lwrjs/label-module-provider @lwrjs/lambda @lwrjs/legacy-npm-module-provider @lwrjs/loader @lwrjs/lwc-module-provider @lwrjs/lwc-ssr @lwrjs/markdown-view-provider @lwrjs/module-bundler @lwrjs/module-registry @lwrjs/npm-module-provider @lwrjs/nunjucks-view-provider @lwrjs/o11y @lwrjs/resource-registry @lwrjs/router @lwrjs/security @lwrjs/server @lwrjs/shared-utils @lwrjs/static @lwrjs/tools @lwrjs/types @lwrjs/view-registry lwr",
"lint": "wireit",
"postpack": "sf-clean --ignore-signing-artifacts",
"prepack": "sf-prepack",
"prepare": "sf-install",
"test": "wireit",
"test:nuts": "nyc mocha \"**/*.nut.ts\" --slow 4500 --timeout 600000 --parallel",
"test:only": "wireit",
"unlink-lwr": "yarn unlink @lwrjs/api @lwrjs/app-service @lwrjs/asset-registry @lwrjs/asset-transformer @lwrjs/auth-middleware @lwrjs/base-view-provider @lwrjs/base-view-transformer @lwrjs/client-modules @lwrjs/config @lwrjs/core @lwrjs/dev-proxy-server @lwrjs/diagnostics @lwrjs/esbuild @lwrjs/everywhere @lwrjs/fs-asset-provider @lwrjs/fs-watch @lwrjs/html-view-provider @lwrjs/instrumentation @lwrjs/label-module-provider @lwrjs/lambda @lwrjs/legacy-npm-module-provider @lwrjs/loader @lwrjs/lwc-module-provider @lwrjs/lwc-ssr @lwrjs/markdown-view-provider @lwrjs/module-bundler @lwrjs/module-registry @lwrjs/npm-module-provider @lwrjs/nunjucks-view-provider @lwrjs/o11y @lwrjs/resource-registry @lwrjs/router @lwrjs/security @lwrjs/server @lwrjs/shared-utils @lwrjs/static @lwrjs/tools @lwrjs/types @lwrjs/view-registry lwr",
"update-snapshots": "node --loader ts-node/esm --no-warnings=ExperimentalWarning \"./bin/dev.js\" snapshot:generate",
"version": "oclif readme"
},
Expand Down Expand Up @@ -265,7 +262,7 @@
"exports": "./lib/index.js",
"type": "module",
"volta": {
"node": "20.11.0",
"node": "20.18.0",
"yarn": "1.22.22"
}
}
82 changes: 1 addition & 81 deletions src/commands/lightning/dev/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import fs from 'node:fs';
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { Connection, Logger, Messages, SfProject } from '@salesforce/core';
import { Platform } from '@salesforce/lwc-dev-mobile-core';
import { expDev, SitesLocalDevOptions, setupDev } from '@lwrjs/api';
import open from 'open';
import { OrgUtils } from '../../../shared/orgUtils.js';
import { PromptUtils } from '../../../shared/promptUtils.js';
Expand All @@ -41,28 +39,13 @@ export default class LightningDevSite extends SfCommand<void> {
char: 'n',
}),
'target-org': Flags.requiredOrg(),
'get-latest': Flags.boolean({
summary: messages.getMessage('flags.get-latest.summary'),
char: 'l',
}),
guest: Flags.boolean({
summary: messages.getMessage('flags.guest.summary'),
default: false,
}),
ssr: Flags.boolean({
summary: messages.getMessage('flags.ssr.summary'),
default: false,
}),
};

public async run(): Promise<void> {
const { flags } = await this.parse(LightningDevSite);

try {
const org = flags['target-org'];
const getLatest = flags['get-latest'];
const guest = flags.guest;
const ssr = flags.ssr;
let siteName = flags.name;

const connection = org.getConnection(undefined);
Expand All @@ -82,76 +65,13 @@ export default class LightningDevSite extends SfCommand<void> {

const selectedSite = new ExperienceSite(org, siteName);

if (!ssr) {
return await this.openPreviewUrl(selectedSite, connection);
}
await this.serveSSRSite(selectedSite, getLatest, siteName, guest);
return await this.openPreviewUrl(selectedSite, connection);
} catch (e) {
this.spinner.stop('failed.');
this.log('Local Development setup failed', e);
}
}

private async serveSSRSite(
selectedSite: ExperienceSite,
getLatest: boolean,
siteName: string,
guest: boolean
): Promise<void> {
let siteZip: string | undefined;

// If the site is not setup / is not based on the current release / or get-latest is requested ->
// generate and download a new site bundle from the org based on latest builder metadata
if (!selectedSite.isSiteSetup() || getLatest) {
const startTime = Date.now();
this.log(`[local-dev] Initializing: ${siteName}`);
this.spinner.start('[local-dev] Downloading site (this may take a few minutes)');
siteZip = await selectedSite.downloadSite();

// delete oldSitePath recursive
const oldSitePath = selectedSite.getExtractDirectory();
if (fs.existsSync(oldSitePath)) {
fs.rmSync(oldSitePath, { recursive: true });
}
const endTime = Date.now();
const duration = (endTime - startTime) / 1000; // Convert to seconds
this.spinner.stop('done.');
this.log(`[local-dev] Site setup completed in ${duration.toFixed(2)} seconds.`);
}

this.log(`[local-dev] launching browser preview for: ${siteName}`);

// Establish a valid access token for this site
const authToken = guest ? '' : await selectedSite.setupAuth();

// Start the dev server
const port = parseInt(process.env.PORT ?? '3000', 10);

// Internal vs external mode
const internalProject = !fs.existsSync('sfdx-project.json') && fs.existsSync('lwr.config.json');
const logLevel = process.env.LOG_LEVEL ?? 'error';

const startupParams: SitesLocalDevOptions = {
sfCLI: !internalProject,
authToken,
open: process.env.OPEN_BROWSER === 'false' ? false : true,
port,
logLevel,
mode: 'dev',
siteZip,
siteDir: selectedSite.getSiteDirectory(),
};

// Environment variable used to setup the site rather than setup & start server
if (process.env.SETUP_ONLY === 'true') {
await setupDev(startupParams);
this.log('[local-dev] setup complete!');
} else {
await expDev(startupParams);
this.log('[local-dev] watching for file changes... (CTRL-C to stop)');
}
}

private async openPreviewUrl(selectedSite: ExperienceSite, connection: Connection): Promise<void> {
let sfdxProjectRootPath = '';
try {
Expand Down
Loading
Loading