-
-
Notifications
You must be signed in to change notification settings - Fork 6.1k
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
JavaScript API InlineConfig Loader/Callback/Provider #17543
Comments
I've sent a PR to support this before #10326, but rightfully, the plugins should be managing state that can work in this scenario. They can base their state on the |
I thought of that. But there's nothing available to all hooks that you can use to maintain multiple states. If you used something like a weak map with the resolved config as key, then subsequent hooks would need to be passed the resolved config to do the lookup, and not all of them are. Same goes for any other potential key/reference option. Also, you were addressing restarts (rebuilds?). You mentioned using the build start hook. This isn't that. For that, mutating the current state is acceptable, because (re)builds/starts are serial/non-parallel within a single command invocation, and therefore part of a single lifecycle (though a bit of an edge case, and just squeaking by). I'm talking about running two commands, in parallel, one as a side effect of the other. Even if there turns out to be a way to handle all cases of plugin reuse that I haven't thought of, the methods for handling them would definitely be outside the expectations for plugin design. It's not something a plugin writer would reasonably be expected to handle. The plugin factory closure is expected (assumed) to be a de facto "pre-command-start" hook. To simplify the scenario: if someone were to instantiate (configure) a plugin once, capturing the returned plugin instance, and then use the JavaScript API to pass it into two parallel build commands, and that caused the plugin to behave incorrectly, I would expect the plugin author to tell the user that they used the plugin incorrectly. The solution would be to please reconfigure (recall the plugin factory function) for each build invocation. But, in the scenario I'm positing, where a plugin wants to run a JavaScript API command that inherits config (plugins) from the parent command, there's no way to currently reinstantiate the inherited plugins. |
Description
Problem: Reusing resolved configuration (specifically
plugins
) in a "child command" will result in unexpected plugin behavior if the "parent command" was invoked using the JavaScript API with an inline config (InlineConfig
) that includesplugins
. A child command is used here to mean a Vite command, called from the JavaScript API, invoked by a plugin hook, which was invoked by the parent command.I encountered this while writing the vite-live-preview plugin that runs the JavaScript API
preview()
command in a plugincloseBundle
hook. It wants to inherit the configuration from the build command that uses the plugin.In my plugin, the
preview()
command should use the same configuration as the build command. To achieve this, the pluginconfigResolved
hook captures the resolvedinlineConfig
andconfigFile
values. Those values are used as the seed for thepreview()
command config.The above
inlineConfig
should be that which was passed to a JavaScript API command, for examplebuild(inlineConfig)
. The Vite executable translates command line parameters into this inline config. They are treated as overrides for any file configuration (UserConfig
) that is loaded.The above
configFile
should be the absolute path to the config file loaded by the command. It will beundefined
if theinlineConfig.configFile
wasfalse
, or if it wasundefined
and no config file was auto-detected.When a Vite command is invoked from the command line, there is no way (currently) to specify plugins via command line options. Therefore, the
inlineConfig
will never contain a non-emptyplugins
array when a command is invoked from the command line, and this problem will not exist for immediate child commands invoked via the JavaScript API according to the problem pattern.When a Vite command is invoked from the JavaScript API,
plugins
can be provided in the inline config, and the problem may exist if a plugin uses a plugin factory function (command/recommended pattern) as a closure to share state between hooks. Because there is no way to get a new instance of a plugin in the inline configplugins
array, the same plugin instance would be passed to the child command. Hooks that are only expected to be invoked once (eg.config
,configResolved
) will be invoked again, any shared state will not be set to initial values, and the state may be mutated by hooks that are being invoked by more than one command. This would be solved if we could instead callgetInlineConfig()
to get a newly generated inline config, containing new instances of plugins. Using an inline config factory actually mimics the config loading pattern that avoids this problem when commands are invoked via the Vite command line.Suggested solution
Short Term (minor):
InlineConfig
values, to also accept functions (factories). The factory type would be() => InlineConfig | Promise<InlineConfig>
getInlineConfig(): Promise<InlineConfig>
method to theResolvedConfig
type, which can be called to get the inline config.inlineConfig
property ofResolvedConfig
would continue to return the inline config instance used by the command.Long Term (major):
ResolvedConfig.inlineConfig
property. It might be useful to keep access to the instance used by a command, though it could lead to plugin developers following my path inheriting parent config incorrectly.Alternative
In my plugin, I explicitly set the
InlineConfig.plugins
toundefined
when I inherit it, to disable inheriting "inline" plugins. This is not ideal because it makes the plugin behave differently when used inline vs in a config file.There is no other solution that allows plugin inheritance that I can find. I can't even find a way to design a stateful plugin that would work when shared.
One potential alternative would be to remove
InlineConfig
properties likeplugins
, that are not aligned with command line options, making the JavaScript API limited to equivalency with the command line.Another alternative might be to provide a purpose built way of sharing states between hooks, that is not dependent on a plugin factory function closure.
Additional context
No response
Validations
The text was updated successfully, but these errors were encountered: