-
-
Notifications
You must be signed in to change notification settings - Fork 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
[feat] install adapters on demand #7462
Conversation
🦋 Changeset detectedLatest commit: 40ac2af The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
packages/adapter-auto/index.js
Outdated
); | ||
try { | ||
execSync( | ||
`echo "Installing ${candidate.module}" && npm install ${candidate.module} --no-save --no-package-lock`, |
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.
TIL --no-package-lock
— if that allows this to work across package managers, that'd be pretty sweet.
Should we add a message along the lines of 'you should add this to your package.json for faster build times in future?'
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.
That'd only help people who look at the build logs, right? I wonder how many people that is.
Also, is there a reason for the echo
to be part of the exec
as well, instead of just a regular console.log
?
If we get rid of that, can we do something with execFileSync
like what we're doing here so we can completely avoid the shell's processing and escaping?
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.
What's the advantage to that? The current approach forwards the output to the main shell, so it could help in case something goes wrong.
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.
That'd only help people who look at the build logs, right? I wonder how many people that is.
a small number, but larger than zero
What's the advantage to that? The current approach forwards the output to the main shell
We'd still pipe stderr
and stdout
. The advantage is that there's no caveats around candidate.module
being some weird string that we need to deal with — npm package names should be fine, but for an example of the category of bugs it prevents, see https://github.com/sveltejs/kit/pull/6129/files.
Also execFileSync
should be slightly faster as it doesn't involve a shell
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.
tried switching to it, can't switch because windows can't execute npm without the .cmd
ending in this case
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 we have process.platform === 'win32' ? 'npm.cmd' : 'npm'
as the first argument of execFileSync
? Does that work?
packages/adapter-auto/index.js
Outdated
@@ -10,31 +13,39 @@ for (const candidate of adapters) { | |||
|
|||
try { | |||
module = await import(candidate.module); |
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.
am suddenly wondering if we should actually be importing the module from the app directory rather than the adapter-auto directory. in most cases it should Just Work, but you can imagine a situation where adapter-auto
is installed in the workspace root while adapter-foo
is installed inside the app
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.
Doesn't candidate.module
just contain the name of the package, and the resolution algorithm should start at the adapter-auto
directory and look for node_modules there, and if it's there, look for that module there? At least I (try to) use this fact by installing the package into the adapter-auto
directory by running npm install
inside its directory.
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.
If the adapter is a dependency of the app (which it would be, if you'd already installed it) then surely resolution should start from there? (Until import.meta.resolve
is stable, this would need import-meta-resolve)
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 feel like this overcomplicates things for no good reason. In what world are you using adapter-auto, but have installed a more specific adapter in another place? You either have them in the same place or switched to the one you actually want to use a long time ago.
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 so hard to imagine a situation where shared dependencies are installed in the workspace root but someone installs a one-off dependency in a package — this very repo used to work that way, until we decided to move all dependencies into packages. I also wonder if 'dependencies of x
can import all other dependencies of x
' is guaranteed across all package managers now and in the future. It's a side-effect of the resolution algorithm plus the way package managers populate node_modules
, but it's the sort of thing that feels changeable, the same way pnpm prevents the npm 3+ behaviour of allowing x
to directly import all indirect dependencies
The approach here seems to work when it comes to installing, but for some reason it
will continue to tinker around. Update: Can't reproduce the first point anymore, so ... it works? Things that are not ideal with this solution:
Things we could add:
|
goddammit, why is this so unreliable to test? Other options:
|
I don't love solving problems by adding dependencies, but we could experiment with https://github.com/antfu/ni |
I'm all for finding a better way to do this, but I think that can happen incrementally, and for right now, pretty much anything would be better than utterly flabbergasting dependency tree that I see that Some other options might be to |
I thought about the 'install in some other directory option' but I think with npm you'd end up with a flat directory containing the adapter and all its dependencies, and then you wouldn't be able to move them into the real |
The solution right now already install things in a separate node_modules folder, namely that inside of |
@Rich-Harris how did you test this PR? Did you use |
I'm completely lost as to why running an install command from |
I'm just looking at the normal build logs. I didn't think there'd be any need to do anything funky since we're not making any changes to the package we're trying to lazily install |
I still don't know why using |
packages/adapter-auto/index.js
Outdated
execSync( | ||
`${process.platform === 'win32' ? 'set' : ''} NODE_ENV=ignore_me && npm install ${ | ||
candidate.module | ||
} --no-save --omit=dev --no-package-lock`, | ||
{ | ||
stdio: 'inherit', | ||
cwd: dirname(fileURLToPath(import.meta.url)) | ||
} | ||
); |
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.
We should be able to manually pass env vars with the env
option https://nodejs.org/dist/latest-v19.x/docs/api/child_process.html#child_processexecsynccommand-options
If we do that, we can also avoid involving the shell at all, and we can use execFileSync
here 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.
execFileSync
needs .cmd
endings for the npm/pnpm/yarn
command on windows last time I tested this. So we either have to prepend that on windows or keep using execSync
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.
Yeah I saw your comment in that thread after I commented here. I responded over on that thread. Even if we can't make execFileSync
work, it would be nice to avoid the manual setting of the env var using shell commands.
I'm actually not even sure that FOO=bar && do-something
would call do-something
with FOO
set to bar
. I don't think environment variables automatically inherit that way in shell scripts without an export
.
Still don't understand why running |
I think the various |
I think so, too, but this wouldn't help you in case of a monorepo, where you run |
… adapter-auto-on-demand
Closes #5123
Marking as draft because I still need to test this on one of the providers, with npm/pnpm/yarn
Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm test
and lint the project withpnpm lint
andpnpm check
Changesets
pnpm changeset
and following the prompts. All changesets should bepatch
until SvelteKit 1.0