diff --git a/.changeset/serious-hats-clap.md b/.changeset/serious-hats-clap.md new file mode 100644 index 00000000..466c279d --- /dev/null +++ b/.changeset/serious-hats-clap.md @@ -0,0 +1,5 @@ +--- +"@ladle/react": minor +--- + +Reload the page if there was a new story added or removed. diff --git a/packages/ladle/lib/cli/vite-dev.js b/packages/ladle/lib/cli/vite-dev.js index c4d17097..ab06857c 100644 --- a/packages/ladle/lib/cli/vite-dev.js +++ b/packages/ladle/lib/cli/vite-dev.js @@ -4,6 +4,7 @@ import getPort from "get-port"; import globby from "globby"; import boxen from "boxen"; import open from "open"; +import chokidar from "chokidar"; import debug from "./debug.js"; import getBaseViteConfig from "./vite-base.js"; import { getMetaJsonObject } from "./vite-plugin/generate/get-meta-json.js"; @@ -36,6 +37,7 @@ const bundler = async (config, configFolder) => { }, }); const vite = await createServer(viteConfig); + const { moduleGraph, ws } = vite; app.head("*", async (_, res) => res.sendStatus(200)); app.get("/meta.json", async (_, res) => { const entryData = await getEntryData(await globby([config.stories])); @@ -64,6 +66,46 @@ const bundler = async (config, configFolder) => { ); } }); + + // trigger full reload when new stories are added or removed + const watcher = chokidar.watch(config.stories, { + persistent: true, + }); + let checkSum = ""; + const getChecksum = async () => { + try { + const entryData = await getEntryData(await globby([config.stories])); + const jsonContent = getMetaJsonObject(entryData); + // loc changes should not grant a full reload + Object.keys(jsonContent.stories).forEach((storyId) => { + jsonContent.stories[storyId].locStart = 0; + jsonContent.stories[storyId].locEnd = 0; + }); + return JSON.stringify(jsonContent); + } catch (e) { + return checkSum; + } + }; + checkSum = await getChecksum(); + const invalidate = async () => { + const newChecksum = await getChecksum(); + if (checkSum === newChecksum) return; + checkSum = newChecksum; + const module = moduleGraph.getModuleById("\0virtual:generated-list"); + if (module) { + moduleGraph.invalidateModule(module); + if (ws) { + ws.send({ + type: "full-reload", + path: "*", + }); + } + } + }; + watcher + .on("add", invalidate) + .on("change", invalidate) + .on("unlink", invalidate); } catch (e) { console.log(e); } diff --git a/packages/ladle/lib/cli/vite-plugin/generate/get-meta-json.js b/packages/ladle/lib/cli/vite-plugin/generate/get-meta-json.js index a30b5e11..721522b5 100644 --- a/packages/ladle/lib/cli/vite-plugin/generate/get-meta-json.js +++ b/packages/ladle/lib/cli/vite-plugin/generate/get-meta-json.js @@ -25,7 +25,7 @@ const getMetaJson = (entryData) => { version: 1, }, stories: - /** @type {{[key: string]: {name: string; levels: string[]; meta: any}}} */ ({}), + /** @type {{[key: string]: {name: string; levels: string[]; meta: any, locStart: number; locEnd: number;}}} */ ({}), }; storyIds.forEach((storyId) => { result.stories[storyId] = { diff --git a/packages/ladle/lib/cli/vite-plugin/get-ast.js b/packages/ladle/lib/cli/vite-plugin/get-ast.js index c9808941..0320026a 100644 --- a/packages/ladle/lib/cli/vite-plugin/get-ast.js +++ b/packages/ladle/lib/cli/vite-plugin/get-ast.js @@ -64,7 +64,7 @@ const getAst = (code, filename) => { ), ); console.log(""); - process.exit(1); + throw e; } }; diff --git a/packages/ladle/package.json b/packages/ladle/package.json index 028a6464..d49e734f 100644 --- a/packages/ladle/package.json +++ b/packages/ladle/package.json @@ -40,6 +40,7 @@ "@vitejs/plugin-react": "^1.3.0", "axe-core": "^4.4.1", "boxen": "^5.1.2", + "chokidar": "^3.5.3", "classnames": "^2.3.1", "commander": "^8.3.0", "debug": "^4.3.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1216c9cb..eb4c25a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -201,6 +201,7 @@ importers: axe-core: ^4.4.1 babel-jest: ^28.0.2 boxen: ^5.1.2 + chokidar: ^3.5.3 classnames: ^2.3.1 commander: ^8.3.0 debug: ^4.3.4 @@ -237,6 +238,7 @@ importers: "@vitejs/plugin-react": 1.3.2 axe-core: 4.4.1 boxen: 5.1.2 + chokidar: 3.5.3 classnames: 2.3.1 commander: 8.3.0 debug: 4.3.4 @@ -6390,6 +6392,8 @@ packages: raw-body: 2.5.1 type-is: 1.6.18 unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color dev: false /bonjour-service/1.0.12: @@ -7598,6 +7602,11 @@ packages: { integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.0.0 dev: false @@ -8933,6 +8942,8 @@ packages: type-is: 1.6.18 utils-merge: 1.0.1 vary: 1.1.2 + transitivePeerDependencies: + - supports-color dev: false /extend-shallow/2.0.1: @@ -9163,6 +9174,8 @@ packages: parseurl: 1.3.3 statuses: 2.0.1 unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color dev: false /find-babel-config/1.2.0: @@ -15020,6 +15033,8 @@ packages: on-finished: 2.4.1 range-parser: 1.2.1 statuses: 2.0.1 + transitivePeerDependencies: + - supports-color dev: false /serialize-javascript/6.0.0: @@ -15071,6 +15086,8 @@ packages: escape-html: 1.0.3 parseurl: 1.3.3 send: 0.18.0 + transitivePeerDependencies: + - supports-color dev: false /set-blocking/2.0.0: