Skip to content

Commit

Permalink
Add --base and --mode options (#202)
Browse files Browse the repository at this point in the history
* Refactor triplicate CLI config application code

* Remove unused BuildParams type, rename DevParams to CLIParams

* Explicitly name CLI ladle

* Update CLI examples in docs

* Add --base and --mode options

This allows doing `ladle build --base=/my-project/`, for e.g. building Ladle storybooks to GitHub Pages,
as well as overriding `--mode`, if needed (see #201).
  • Loading branch information
akx committed Aug 2, 2022
1 parent 688acdf commit 7fcdc97
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 85 deletions.
5 changes: 5 additions & 0 deletions .changeset/purple-gorillas-do.md
@@ -0,0 +1,5 @@
---
"@ladle/react": minor
---

Add `--base` and `--mode` options à la `vite build`
31 changes: 31 additions & 0 deletions packages/ladle/lib/cli/apply-cli-config.js
@@ -0,0 +1,31 @@
import debug from "./debug.js";
import path from "path";
import loadConfig from "./load-config.js";

/**
* @param params {import("../shared/types").CLIParams}
*/
export default async function applyCLIConfig(params) {
debug(`CLI theme: ${params.theme}`);
debug(`CLI stories: ${params.stories}`);
debug(`CLI port: ${params.port || "undefined"}`);
debug(`CLI out: ${params.outDir || "undefined"}`);
params.config = params.config || ".ladle";
const configFolder = path.isAbsolute(params.config)
? params.config
: path.join(process.cwd(), params.config);
const config = await loadConfig(configFolder);
config.addons.theme.defaultState =
params.theme || config.addons.theme.defaultState;
config.stories = params.stories || config.stories;
config.viteConfig = params.viteConfig || config.viteConfig;
config.outDir = params.outDir || config.outDir;
config.port = params.port || config.port;
config.previewPort = params.previewPort || config.previewPort;
config.base = params.base || config.base;
config.mode = params.mode || config.mode;
debug(`Final config:\n${JSON.stringify(config, null, " ")}`);
process.env["VITE_PUBLIC_LADLE_THEME"] = config.addons.theme.defaultState;
process.env["VITE_PUBLIC_STORIES"] = config.stories;
return { configFolder, config };
}
24 changes: 3 additions & 21 deletions packages/ladle/lib/cli/build.js
Expand Up @@ -4,37 +4,19 @@ import path from "path";
import { promises as fs } from "fs";
import { globby } from "globby";
import viteProd from "./vite-prod.js";
import loadConfig from "./load-config.js";
import debug from "./debug.js";
import { getMetaJsonString } from "./vite-plugin/generate/get-meta-json.js";
import { getEntryData } from "./vite-plugin/parse/get-entry-data.js";
import getFolderSize from "./get-folder-size.js";
import applyCLIConfig from "./apply-cli-config.js";

/**
* @param params {import("../shared/types").BuildParams}
* @param params {import("../shared/types").CLIParams}
*/
const build = async (params = {}) => {
const startTime = performance.now();
debug("Starting build command");
debug(`CLI theme: ${params.theme}`);
debug(`CLI stories: ${params.stories}`);
debug(`CLI out: ${params.outDir ? params.outDir : "undefined"}`);
params.config = params.config || ".ladle";
const configFolder = path.isAbsolute(params.config)
? params.config
: path.join(process.cwd(), params.config);
const config = await loadConfig(configFolder);

// CLI flags override default and custom config files
config.addons.theme.defaultState = params.theme
? params.theme
: config.addons.theme.defaultState;
config.stories = params.stories ? params.stories : config.stories;
config.viteConfig = params.viteConfig ? params.viteConfig : config.viteConfig;
config.outDir = params.outDir ? params.outDir : config.outDir;
debug(`Final config:\n${JSON.stringify(config, null, " ")}`);
process.env["VITE_PUBLIC_LADLE_THEME"] = config.addons.theme.defaultState;
process.env["VITE_PUBLIC_STORIES"] = config.stories;
const { configFolder, config } = await applyCLIConfig(params);
await viteProd(config, configFolder);
const entryData = await getEntryData(await globby([config.stories]));
const jsonContent = getMetaJsonString(entryData);
Expand Down
14 changes: 9 additions & 5 deletions packages/ladle/lib/cli/cli.js
@@ -1,5 +1,5 @@
#!/usr/bin/env node
import { program } from "commander";
import { Command } from "commander";
import serve from "./serve.js";
import build from "./build.js";
import preview from "./preview.js";
Expand All @@ -9,6 +9,7 @@ import preview from "./preview.js";
*/
const strToInt = (n) => parseInt(n, 10);

const program = new Command("ladle");
program.showHelpAfterError().showSuggestionAfterError();

program
Expand All @@ -18,11 +19,10 @@ program
.option("-p, --port [number]", "port to serve the application", strToInt)
.option("--stories [string]", "glob to find stories")
.option("--theme [string]", "theme light, dark or auto")
.option(
"--config [string]",
"folder where Ladle configs are located, default .ladle",
)
.option("--config [string]", "folder where config is located, default .ladle")
.option("--viteConfig [string]", "file with Vite configuration")
.option("--base [string]", "base URL path for build output")
.option("--mode [string]", "Vite mode")
.action(async (params) => {
await serve({ ...params, serve: params });
});
Expand All @@ -35,6 +35,8 @@ program
.option("--theme [string]", "theme light, dark or auto")
.option("--config [string]", "folder where config is located, default .ladle")
.option("--viteConfig [string]", "file with Vite configuration")
.option("--base [string]", "base URL path for build output")
.option("--mode [string]", "Vite mode")
.action(async (params) => {
const success = await build({ ...params, build: params });
if (success) {
Expand All @@ -50,6 +52,8 @@ program
.option("-p, --port [number]", "port to serve the application", strToInt)
.option("--config [string]", "folder where config is located, default .ladle")
.option("--viteConfig [string]", "file with Vite configuration")
.option("--base [string]", "base URL path for build output")
.option("--mode [string]", "Vite mode")
.action(async (params) => {
await preview({ ...params, previewPort: params.port });
});
Expand Down
18 changes: 3 additions & 15 deletions packages/ladle/lib/cli/preview.js
@@ -1,27 +1,15 @@
#!/usr/bin/env node

import path from "path";
import vitePreview from "./vite-preview.js";
import loadConfig from "./load-config.js";
import debug from "./debug.js";
import applyCLIConfig from "./apply-cli-config.js";

/**
* @param params {import("../shared/types").DevParams}
* @param params {import("../shared/types").CLIParams}
*/
const preview = async (params = {}) => {
debug("Starting preview command");
debug(`CLI port: ${params.port ? params.port : "undefined"}`);
params.config = params.config || ".ladle";
const configFolder = path.isAbsolute(params.config)
? params.config
: path.join(process.cwd(), params.config);
const config = await loadConfig(configFolder);
config.previewPort = params.previewPort
? params.previewPort
: config.previewPort;
config.outDir = params.outDir ? params.outDir : config.outDir;
config.viteConfig = params.viteConfig ? params.viteConfig : config.viteConfig;
debug(`Final config:\n${JSON.stringify(config, null, " ")}`);
const { configFolder, config } = await applyCLIConfig(params);
await vitePreview(config, configFolder);
};

Expand Down
24 changes: 3 additions & 21 deletions packages/ladle/lib/cli/serve.js
@@ -1,33 +1,15 @@
#!/usr/bin/env node

import path from "path";
import viteDev from "./vite-dev.js";
import loadConfig from "./load-config.js";
import debug from "./debug.js";
import applyCLIConfig from "./apply-cli-config.js";

/**
* @param params {import("../shared/types").DevParams}
* @param params {import("../shared/types").CLIParams}
*/
const serve = async (params = {}) => {
debug("Starting serve command");
debug(`CLI theme: ${params.theme}`);
debug(`CLI stories: ${params.stories}`);
debug(`CLI port: ${params.port ? params.port : "undefined"}`);
params.config = params.config || ".ladle";
const configFolder = path.isAbsolute(params.config)
? params.config
: path.join(process.cwd(), params.config);
const config = await loadConfig(configFolder);
// CLI flags override default and custom config files
config.addons.theme.defaultState = params.theme
? params.theme
: config.addons.theme.defaultState;
config.stories = params.stories ? params.stories : config.stories;
config.port = params.port ? params.port : config.port;
config.viteConfig = params.viteConfig ? params.viteConfig : config.viteConfig;
debug(`Final config:\n${JSON.stringify(config, null, " ")}`);
process.env["VITE_PUBLIC_LADLE_THEME"] = config.addons.theme.defaultState;
process.env["VITE_PUBLIC_STORIES"] = config.stories;
const { configFolder, config } = await applyCLIConfig(params);
await viteDev(config, configFolder);
};

Expand Down
1 change: 1 addition & 0 deletions packages/ladle/lib/cli/vite-base.js
Expand Up @@ -80,6 +80,7 @@ const getBaseViteConfig = async (ladleConfig, configFolder, viteConfig) => {
*/
const config = {
...viteConfig,
base: ladleConfig.base,
configFile: false,
cacheDir: userViteConfig.cacheDir
? userViteConfig.cacheDir
Expand Down
11 changes: 9 additions & 2 deletions packages/ladle/lib/cli/vite-dev.js
Expand Up @@ -28,7 +28,7 @@ const bundler = async (config, configFolder) => {
* @type {import('vite').InlineConfig}
*/
const viteConfig = await getBaseViteConfig(config, configFolder, {
mode: "development",
mode: config.mode || "development",
server: {
port: config.port,
hmr: {
Expand All @@ -48,10 +48,17 @@ const bundler = async (config, configFolder) => {
const jsonContent = getMetaJsonObject(entryData);
res.json(jsonContent);
});
// When `middlewareMode` is true, vite's own base middleware won't redirect requests,
// so we need to do that ourselves.
const { base } = viteConfig;
if (base && base !== "/") {
app.get("/", (_, res) => res.redirect(base));
app.get("/index.html", (_, res) => res.redirect(base));
}
app.use(vite.middlewares);
const serverUrl = `${vite.config.server.https ? "https" : "http"}://${
vite.config.server.host || "localhost"
}:${port}`;
}:${port}${vite.config.base || ""}`;
app.listen(port, async () => {
console.log(
boxen(`🥄 Ladle.dev served at ${serverUrl}`, {
Expand Down
2 changes: 1 addition & 1 deletion packages/ladle/lib/cli/vite-preview.js
Expand Up @@ -14,7 +14,7 @@ const vitePreview = async (config, configFolder) => {
* @type {import('vite').InlineConfig}
*/
const viteConfig = await getBaseViteConfig(config, configFolder, {
mode: "production",
mode: config.mode || "production",
build: {
outDir: path.join(process.cwd(), config.outDir),
emptyOutDir: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/ladle/lib/cli/vite-prod.js
Expand Up @@ -12,7 +12,7 @@ const viteProd = async (config, configFolder) => {
* @type {import('vite').InlineConfig}
*/
const viteConfig = await getBaseViteConfig(config, configFolder, {
mode: "production",
mode: config.mode || "production",
build: {
outDir: path.join(process.cwd(), config.outDir),
emptyOutDir: true,
Expand Down
1 change: 1 addition & 0 deletions packages/ladle/lib/shared/default-config.js
Expand Up @@ -8,6 +8,7 @@ export default {
port: 61000,
previewPort: 8080,
outDir: "build",
base: undefined,
// enable/disable addons and their default state
addons: {
control: {
Expand Down
8 changes: 3 additions & 5 deletions packages/ladle/lib/shared/types.ts
Expand Up @@ -122,11 +122,7 @@ export type GeneratedStories = {
};
};

export type DevParams = Partial<Config> & {
theme?: ThemeState;
config?: string;
};
export type BuildParams = Partial<Config> & {
export type CLIParams = Partial<Config> & {
theme?: ThemeState;
config?: string;
};
Expand All @@ -143,6 +139,8 @@ export type Config = {
port: number;
previewPort: number;
outDir: string;
base?: string;
mode?: string;
addons: {
control: {
enabled: boolean;
Expand Down
37 changes: 23 additions & 14 deletions packages/website/docs/cli.md
Expand Up @@ -14,24 +14,27 @@ Options:
Commands:
serve|dev [options] start developing
build [options] build static production app
preview [options] start a server to preview the build
preview [options] start a server to preview the build in outDir
help [command] display help for command
```

## Serve command

```bash
Usage: ladle serve [options]
Usage: ladle serve|dev [options]

start developing

Options:
-p, --port [number] port to serve the application
--stories [string] glob to find stories
--theme [string] theme light, dark or auto
--config [string] folder where Ladle configs are located, default .ladle
--viteConfig [string] file with Vite configuration
-h, --help display help for command
-p, --port [number] port to serve the application
--stories [string] glob to find stories
--theme [string] theme light, dark or auto
--config [string] folder where config is located, default .ladle
--viteConfig [string] file with Vite configuration
--base [string] base URL path for build output
--mode [string] Vite mode
-h, --help display help for command

```

## Build command
Expand All @@ -42,12 +45,15 @@ Usage: ladle build [options]
build static production app

Options:
-o, --outDir <path> output directory
--stories [string] glob to find stories
--theme [string] theme light, dark or auto
--config [string] folder where config is located, default .ladle
--viteConfig [string] file with Vite configuration
-h, --help display help for command
-o, --outDir <path> output directory
--stories [string] glob to find stories
--theme [string] theme light, dark or auto
--config [string] folder where config is located, default .ladle
--viteConfig [string] file with Vite configuration
--base [string] base URL path for build output
--mode [string] Vite mode
-h, --help display help for command

```

## Preview command
Expand All @@ -62,5 +68,8 @@ Options:
-p, --port [number] port to serve the application
--config [string] folder where config is located, default .ladle
--viteConfig [string] file with Vite configuration
--base [string] base URL path for build output
--mode [string] Vite mode
-h, --help display help for command

```
22 changes: 22 additions & 0 deletions packages/website/docs/config.md
Expand Up @@ -79,6 +79,28 @@ export default {
};
```

### base

Base path for building the output; useful for e.g. hosting your project's storybook on GitHub Pages:

```tsx
export default {
base: "/my-project/",
};
```

### mode

Vite [mode](https://vitejs.dev/guide/env-and-mode.html#modes). If not set, defaults to `development` when developing and `production` for building static output.

This also affects [Vite's .env file loading](https://vitejs.dev/guide/env-and-mode.html#env-files), as well as anything else setting `mode` affects.

```tsx
export default {
mode: "my-custom-mode",
};
```

### addons

You can enable or disable all Ladle addons (the buttons in the left bottom corner). You can also control their default state.
Expand Down

1 comment on commit 7fcdc97

@vercel
Copy link

@vercel vercel bot commented on 7fcdc97 Aug 2, 2022

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

ladle – ./

ladle-git-master-miksu.vercel.app
ladle.vercel.app
ladle-miksu.vercel.app
ladle.dev

Please sign in to comment.