Skip to content

Commit

Permalink
Vite: Don't prefix story import with @fs
Browse files Browse the repository at this point in the history
  • Loading branch information
tobiasdiez committed Aug 22, 2024
1 parent 4bbfb14 commit e23fef9
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 16 deletions.
4 changes: 3 additions & 1 deletion code/builders/builder-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,16 @@
"express": "^4.19.2",
"find-cache-dir": "^3.0.0",
"fs-extra": "^11.1.0",
"knitwork": "^1.1.0",
"magic-string": "^0.30.0",
"pathe": "^1.1.2",
"slash": "^5.0.0",
"ts-dedent": "^2.0.0"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^22.0.0",
"glob": "^10.0.0",
"slash": "^5.0.0",
"typescript": "^5.3.2",
"vite": "^4.0.4"
},
Expand Down
56 changes: 56 additions & 0 deletions code/builders/builder-vite/src/codegen-importfn-script.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { toImportFn } from './codegen-importfn-script';

describe('toImportFn', () => {
it('should correctly map story paths to import functions for absolute paths on Linux', async () => {
const root = '/absolute/path';
const stories = ['/absolute/path/to/story1.js', '/absolute/path/to/story2.js'];

const result = await toImportFn(root, stories);

expect(result).toMatchInlineSnapshot(`
"const importers = {
"./to/story1.js": () => import("/absolute/path/to/story1.js"),
"./to/story2.js": () => import("/absolute/path/to/story2.js")
};
export async function importFn(path) {
return await importers[path]();
}"
`);
});

it('should correctly map story paths to import functions for absolute paths on Windows', async () => {
const root = 'C:\\absolute\\path';
const stories = ['C:\\absolute\\path\\to\\story1.js', 'C:\\absolute\\path\\to\\story2.js'];

const result = await toImportFn(root, stories);

expect(result).toMatchInlineSnapshot(`
"const importers = {
"./to/story1.js": () => import("C:/absolute/path/to/story1.js"),
"./to/story2.js": () => import("C:/absolute/path/to/story2.js")
};
export async function importFn(path) {
return await importers[path]();
}"
`);
});

it('should handle an empty array of stories', async () => {
const root = '/absolute/path';
const stories: string[] = [];

const result = await toImportFn(root, stories);

expect(result).toMatchInlineSnapshot(`
"const importers = {};
export async function importFn(path) {
return await importers[path]();
}"
`);
});
});
31 changes: 16 additions & 15 deletions code/builders/builder-vite/src/codegen-importfn-script.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { relative } from 'node:path';

import type { Options } from 'storybook/internal/types';

import { genDynamicImport, genImport, genObjectFromRawEntries } from 'knitwork';
import { normalize, relative } from 'pathe';
import { dedent } from 'ts-dedent';

import { listStories } from './list-stories';

/**
Expand All @@ -21,34 +23,33 @@ function toImportPath(relativePath: string) {
/**
* This function takes an array of stories and creates a mapping between the stories' relative paths
* to the working directory and their dynamic imports. The import is done in an asynchronous
* function to delay loading. It then creates a function, `importFn(path)`, which resolves a path to
* an import function and this is called by Storybook to fetch a story dynamically when needed.
* function to delay loading and to allow Vite to split the code into smaller chunks. It then
* creates a function, `importFn(path)`, which resolves a path to an import function and this is
* called by Storybook to fetch a story dynamically when needed.
*
* @param stories An array of absolute story paths.
*/
async function toImportFn(stories: string[]) {
const { normalizePath } = await import('vite');
export async function toImportFn(root: string, stories: string[]) {
const objectEntries = stories.map((file) => {
const relativePath = normalizePath(relative(process.cwd(), file));
const relativePath = relative(root, file);

return ` '${toImportPath(relativePath)}': async () => import('/@fs/${file}')`;
return [toImportPath(relativePath), genDynamicImport(normalize(file))] as [string, string];
});

return `
const importers = {
${objectEntries.join(',\n')}
};
return dedent`
const importers = ${genObjectFromRawEntries(objectEntries)};
export async function importFn(path) {
return importers[path]();
return await importers[path]();
}
`;
}

export async function generateImportFnScriptCode(options: Options) {
export async function generateImportFnScriptCode(options: Options): Promise<string> {
// First we need to get an array of stories and their absolute paths.
const stories = await listStories(options);

// We can then call toImportFn to create a function that can be used to load each story dynamically.
return (await toImportFn(stories)).trim();
// eslint-disable-next-line @typescript-eslint/return-await
return await toImportFn(options.root || process.cwd(), stories);
}
9 changes: 9 additions & 0 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5696,7 +5696,9 @@ __metadata:
find-cache-dir: "npm:^3.0.0"
fs-extra: "npm:^11.1.0"
glob: "npm:^10.0.0"
knitwork: "npm:^1.1.0"
magic-string: "npm:^0.30.0"
pathe: "npm:^1.1.2"
slash: "npm:^5.0.0"
ts-dedent: "npm:^2.0.0"
typescript: "npm:^5.3.2"
Expand Down Expand Up @@ -18677,6 +18679,13 @@ __metadata:
languageName: node
linkType: hard

"knitwork@npm:^1.1.0":
version: 1.1.0
resolution: "knitwork@npm:1.1.0"
checksum: 10c0/e23c679d4ded01890ab2669ccde2e85e4d7e6ba327b1395ff657f8067c7d73dc134fc8cd8188c653de4a687be7fa9c130bd36c3e2f76d8685e8b97ff8b30779c
languageName: node
linkType: hard

"language-subtag-registry@npm:^0.3.20":
version: 0.3.22
resolution: "language-subtag-registry@npm:0.3.22"
Expand Down

0 comments on commit e23fef9

Please sign in to comment.