Skip to content

Commit 2a09441

Browse files
committed
CLI: Add --build-only option
1 parent 131dea7 commit 2a09441

File tree

5 files changed

+48
-27
lines changed

5 files changed

+48
-27
lines changed

docs/api/cli-options.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Usage: start-storybook [options]
2525
| --ssl-cert `<cert>` | Provide an SSL certificate. (Required with --https) | `start-storybook --ssl-cert my-ssl-certificate` |
2626
| --ssl-key `<key>` | Provide an SSL key. (Required with --https) | `start-storybook --ssl-key my-ssl-key` |
2727
| --smoke-test | Exit after successful start | `start-storybook --smoke-test` |
28+
| --build-only | Only build, don’t start the server (useful to warm up the cache) | `start-storybook --build-only` |
2829
| --ci | CI mode (skip interactive prompts, don't open browser) | `start-storybook --ci` |
2930
| --quiet | Suppress verbose build output | `start-storybook --quiet` |
3031
| --no-dll | Do not use dll reference (no-op) | `start-storybook --no-dll` |

lib/core/docs/standalone.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ sslCa <ca> Provide an SSL certificate authority. (Optional with "ht
6464
sslCert <cert> Provide an SSL certificate. (Required with "https")
6565
sslKey <key> Provide an SSL key. (Required with "https")
6666
smokeTest Exit after successful start
67+
buildOnly Only build, don’t start the server (useful to warm up the cache)
6768
ci CI mode (skip interactive prompts, don't open browser)
6869
quiet Suppress verbose build output
6970
```

lib/core/src/server/build-dev.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,13 @@ export async function buildDevStandalone(
254254
: Promise.resolve(getReleaseNotesFailedState(version)),
255255
]);
256256

257-
if (!options.ci && !options.smokeTest && options.port != null && port !== options.port) {
257+
if (
258+
!options.buildOnly &&
259+
!options.ci &&
260+
!options.smokeTest &&
261+
options.port != null &&
262+
port !== options.port
263+
) {
258264
const { shouldChangePort } = await prompts({
259265
type: 'confirm',
260266
initial: true,
@@ -283,12 +289,17 @@ export async function buildDevStandalone(
283289

284290
if (options.smokeTest) {
285291
await outputStats(previewStats, managerStats);
292+
286293
const hasManagerWarnings = managerStats && managerStats.toJson().warnings.length > 0;
287294
const hasPreviewWarnings = previewStats && previewStats.toJson().warnings.length > 0;
288295
process.exit(hasManagerWarnings || (hasPreviewWarnings && !options.ignorePreview) ? 1 : 0);
289296
return;
290297
}
291298

299+
if (options.buildOnly) {
300+
process.exit(0);
301+
}
302+
292303
outputStartupInformation({
293304
updateInfo,
294305
version,

lib/core/src/server/cli/dev.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface DevCliOptions {
1313
sslCert?: string;
1414
sslKey?: string;
1515
smokeTest?: boolean;
16+
buildOnly?: boolean;
1617
ci?: boolean;
1718
loglevel?: string;
1819
quiet?: boolean;
@@ -50,6 +51,7 @@ export async function getDevCli(packageJson: {
5051
.option('--ssl-cert <cert>', 'Provide an SSL certificate. (Required with --https)')
5152
.option('--ssl-key <key>', 'Provide an SSL key. (Required with --https)')
5253
.option('--smoke-test', 'Exit after successful start')
54+
.option('--build-only', 'Only build, don’t start the server (useful to warm up the cache)')
5355
.option('--ci', "CI mode (skip interactive prompts, don't open browser)")
5456
.option('--loglevel [level]', 'Control level of logging during build')
5557
.option('--quiet', 'Suppress verbose build output')

lib/core/src/server/dev-server.ts

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -365,45 +365,51 @@ export function getServerAddresses(port: number, host: string, proto: string) {
365365

366366
export async function storybookDevServer(options: any) {
367367
const app = express();
368-
const server = await getServer(app, options);
369368

370369
const configDir = path.resolve(options.configDir);
371370
const outputDir = options.smokeTest
372371
? resolvePathInStorybookCache('public')
373372
: path.resolve(options.outputDir || resolvePathInStorybookCache('public'));
374373
const configType = 'DEVELOPMENT';
375374
const startTime = process.hrtime();
375+
const prebuiltDir = await getPrebuiltDir({ configDir, options });
376+
let address;
377+
let networkAddress;
376378

377-
if (typeof options.extendServer === 'function') {
378-
options.extendServer(server);
379-
}
379+
if (!options.buildOnly) {
380+
const server = await getServer(app, options);
380381

381-
app.use((req, res, next) => {
382-
res.header('Access-Control-Allow-Origin', '*');
383-
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
384-
next();
385-
});
382+
if (typeof options.extendServer === 'function') {
383+
options.extendServer(server);
384+
}
386385

387-
// User's own static files
388-
await useStatics(router, options);
386+
app.use((req, res, next) => {
387+
res.header('Access-Control-Allow-Origin', '*');
388+
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
389+
next();
390+
});
389391

390-
getMiddleware(configDir)(router);
391-
app.use(router);
392+
// User's own static files
393+
await useStatics(router, options);
392394

393-
const { port, host } = options;
394-
const proto = options.https ? 'https' : 'http';
395-
const { address, networkAddress } = getServerAddresses(port, host, proto);
395+
getMiddleware(configDir)(router);
396+
app.use(router);
396397

397-
await new Promise((resolve, reject) => {
398-
// FIXME: Following line doesn't match TypeScript signature at all 🤔
399-
// @ts-ignore
400-
server.listen({ port, host }, (error: Error) => (error ? reject(error) : resolve()));
401-
});
398+
const { port, host } = options;
399+
const proto = options.https ? 'https' : 'http';
400+
const serverAddresses = getServerAddresses(port, host, proto);
401+
networkAddress = serverAddresses.networkAddress;
402+
address = serverAddresses.address;
402403

403-
const prebuiltDir = await getPrebuiltDir({ configDir, options });
404+
await new Promise((resolve, reject) => {
405+
// FIXME: Following line doesn't match TypeScript signature at all 🤔
406+
// @ts-ignore
407+
server.listen({ port, host }, (error: Error) => (error ? reject(error) : resolve()));
408+
});
404409

405-
// Manager static files
406-
router.use('/', express.static(prebuiltDir || outputDir));
410+
// Manager static files
411+
router.use('/', express.static(prebuiltDir || outputDir));
412+
}
407413

408414
// Build the manager and preview in parallel.
409415
// Start the server (and open the browser) as soon as the manager is ready.
@@ -413,14 +419,14 @@ export async function storybookDevServer(options: any) {
413419
startManager({ startTime, options, configType, outputDir, configDir, prebuiltDir })
414420
// TODO #13083 Restore this when compiling the preview is fast enough
415421
// .then((result) => {
416-
// if (!options.ci && !options.smokeTest) openInBrowser(address);
422+
// if (!options.ci && !options.smokeTest && !options.buildOnly) openInBrowser(address);
417423
// return result;
418424
// })
419425
.catch(bailPreview),
420426
]);
421427

422428
// TODO #13083 Remove this when compiling the preview is fast enough
423-
if (!options.ci && !options.smokeTest) openInBrowser(networkAddress);
429+
if (!options.ci && !options.smokeTest && !options.buildOnly) openInBrowser(networkAddress);
424430

425431
return { ...previewResult, ...managerResult, address, networkAddress };
426432
}

0 commit comments

Comments
 (0)