-
-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vite: Don't prefix story import with @fs
#28941
base: next
Are you sure you want to change the base?
Conversation
☁️ Nx Cloud ReportCI is running/has finished running commands for commit 36636ec. As they complete they will appear below. Click to see the status, the terminal output, and the build insights. 📂 See all runs for this CI Pipeline Execution ✅ Successfully ran 1 targetSent with 💌 from NxCloud. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9 file(s) reviewed, 4 comment(s)
Edit PR Review Bot Settings
|
||
import { generateModernIframeScriptCodeFromPreviews } from './codegen-modern-iframe-script'; | ||
|
||
const projectRoot = 'projectRoot'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Consider using a more descriptive variable name, such as mockProjectRoot
console.log( | ||
'Deprecated: Preview annotations should be strings, not objects. Use the `absolute` property instead.' | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Consider using a logger instead of console.log for consistency
d8f53d5
to
e23fef9
Compare
Tests are passing, so this should be good to go. |
Do these changes relate/interfere with the changes proposed in #26010 ? |
Apart from the obvious merge conflicts there is no interference. The changes in #26010 related to the story index involve virtual modules (prefixed with |
@JReinhold could we please get this in? It's blocking support for v8 in the vue plugin. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm very sorry for taking so long to look at this, it slipped between the cracks! 🙇
I'm fine with the changes to remove @fs
, but not a fan of the new dependencies as they seem unnecessary to me. But as I say, there might just be some context I'm missing.
@@ -194,6 +194,7 @@ export interface BuilderOptions { | |||
ignorePreview?: boolean; | |||
cache?: FileSystemCache; | |||
configDir: string; | |||
projectRoot?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you elaborate on why this is needed now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not strictly necessary, but before the paths were relative to cwd
(which might not be the project root). I've actually extracted the root directory actually only to make testing of the toImportFn
simpler - but then thought that I would make sense to propagate this upwards and add a proper handling of the project root.
https://github.com/storybookjs/storybook/pull/28941/files#diff-a4ade24974a8c7f082261c73f22be07ec54ad61a3f9683b20035955a50fa1a8bR54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little concerned that this doesn't actually solve the issue, but appears to. I wouldn't be surprised if there were hundreds of other places that assumed that process.cwd() === projectRoot
, that would break if anyone attempted to use a project root different from the CWD. So then they'd set this explicitly, thinking that that would solve the issue, when it would just cause breakage somewhere else.
It's just my experience with the code base that makes me slightly defensive about this. We would need to set up an actual minimal reproduction with a case where CWD is not project root and see that it worked, before I'd feel confident in this.
I do like your thinking behind this though, on the surface it makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really a user-facing option? That was not my intention. I only set it once to be the parent of the config dir.
But sure, there might be other problems with not using the root as cwd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unsure about it being user-facing, it's at least readable by users, but I don't think it's writable.
Would still be great to confirm it works.
import type { Options } from 'storybook/internal/types'; | ||
|
||
import { genDynamicImport, genImport, genObjectFromRawEntries } from 'knitwork'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of using this package for multiple reasons:
- With our recent focus on slimming down Storybook, we're trying to ensure that every KB counts, and to me it doesn't look like this improves the code in any way. The library covers a lot of edge cases/options which I don't think is relevant to us - but maybe I'm missing something?
- I feel like the readability suffers here, because now to understand what the code does, you need to dig into what
knitwork
is and does. Before it was just simple string concatenations, which you could understand by understanding basic JS.
But again, maybe this adds compatibility for edge cases that users are experiencing which I don't know about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This library just makes it easier to create safe javascript. Under the hood it's also only string concatenation. To address your points:
With our recent focus on slimming down Storybook, we're trying to ensure that every KB counts
The package size of the builder should be the same (or actually slightly goes down since its shorter to write the code using knitwork over manual string concats). I also don't quite understand why the builder size would matter much, since it is never deployed to any server.
I feel like the readability suffers here
I would argue this is very subjective. Personally, I find genDynamicImport(path)
more readable than
`async () => import('${path})`
and it is less prone to make a small mistake (i.e. don't close '
as I did above).
adds compatibility for edge cases
It mostly adds proper handling of special characters in the import path similar to https://github.com/rollup/rollup/blob/master/src/utils/escapeId.ts.
In #28798 I also use it to generate a correct variable name based on a string, which is also somewhat non-trivial.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The package size of the builder should be the same (or actually slightly goes down since its shorter to write the code using knitwork over manual string concats).
From a bundled perspective yes, but not when you take into account that the extra dependencies need to be downloaded and installed.
I also don't quite understand why the builder size would matter much, since it is never deployed to any server.
I'm sorry I didn't make this clear in the original comment, but for us it's not just about the size of the final bundle of a built Storybook, it's about the whole Storybook experience, which includes how fast it installs, how many dependencies it adds to your project, how many MBs it adds to your node_modules
.
By far the biggest complaint about Storybook today is that it's "bloated" and people don't want to add the bloat to their projects.
You can very rightfully interpret that complaint however you like, but it doesn't change the fact that our users are loud and clear about caring about this, and so do we.
This is why the team has decided that every new dependency will be scrutinized.
You can read more about the ethos at https://e18e.dev/guide/cleanup.html and our perspective on it in #29038.
I would argue this is very subjective. Personally, I find
genDynamicImport(path)
more readable
Subjective yes. IMO genDynamicImport
is only more readable if you understand what it does, which most don't.
and it is less prone to make a small mistake
I can 100% agree with that.
It doesn't make sense to me to replace `async () => import('${path}')`
with a dependency.
import type { Options } from 'storybook/internal/types'; | ||
|
||
import { genDynamicImport, genImport, genObjectFromRawEntries } from 'knitwork'; | ||
import { normalize, relative } from 'pathe'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar to above, how does this improve over the current combination of Node and Vite APIs, to justify the extra dependency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know, there is no easy way to normalize windows paths in Node to always use forward-slash, which is what vite needs to handle the import correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But isn't that what we did already with normalizePath
from Vite at the old line 30-32 below?
"magic-string": "^0.30.0", | ||
"pathe": "^1.1.2", | ||
"slash": "^5.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why move slash
to a dependency
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually used in a few instances in the builder, eg
import slash from 'slash'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point of it being a devDependency
is so that it gets bundled in (and minimized, optimized, tree-shaken) automatically when we build the package for publication.
Ideally we want to do this with all our dependencies, but some are incompatible with this and some pacakges we just haven't gotten around to test if they can be bundled in, which is why some are still regular dependencies
. But devDependencies
is the default unless it's not possible.
I understand how that is not obvious from your point of view, because that's usually not how projects use dependencies
and devDependencies
. We might someday move to a more explicit version of this pattern.
Closes tobiasdiez/storybook-vue-addon#103
What I did
Currently, the generated imports in
storybook-stories.js
use the prefix@fs
. This prefix is generally used by vite to mark certain imports at the end of the resolution (eg files that outside of the root dir). Adding the prefix already at the beginning yields problems when plugins are modifying the story import resolution (which is the case for the vue plugin).This is fixed by simplying using the full absolute path of the story (after normalizing Windows paths).
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal
,ci:merged
orci:daily
GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli/src/sandbox-templates.ts
Make sure this PR contains one of the labels below:
Available labels
bug
: Internal changes that fixes incorrect behavior.maintenance
: User-facing maintenance tasks.dependencies
: Upgrading (sometimes downgrading) dependencies.build
: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup
: Minor cleanup style change. Will not show up in release changelog.documentation
: Documentation only changes. Will not show up in release changelog.feature request
: Introducing a new feature.BREAKING CHANGE
: Changes that break compatibility in some way with current major version.other
: Changes that don't fit in the above categories.🦋 Canary release
This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/core
team here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>
Greptile Summary
This PR removes the '@fs' prefix from story imports in the Vite builder for Storybook, addressing issues with plugins modifying story import resolution.
toImportFn
incodegen-importfn-script.ts
to use absolute paths and improve dynamic importsgenerateModernIframeScriptCode
incodegen-modern-iframe-script.ts
for better preview annotation handling and HMR supportprocessPreviewAnnotation
inprocess-preview-annotation.ts
to normalize paths using the 'pathe' librarycodegen-importfn-script.test.ts
andcodegen-modern-iframe-script.test.ts
to ensure correct functionalitypackage.json
to include 'knitwork', 'pathe', and 'slash' for improved path handling