Subscribe on changes!

Injection symbol not found in imported component when running "vite dev"

avatar
Oct 28th 2022

Vue version

3.2.41

Link to minimal reproduction

https://github.com/bauer00/vue3-module-provide-test

Steps to reproduce

  1. Checkout https://github.com/bauer00/vue3-module-provide-test (It's a clean install with npm init vue@latest and only added Typescript)
  2. npm install (this should also install the module @test/module which is provided by a local package test-mdoule-0.0.1.tgz
  3. npm run dev
  4. Open browser

General description of what I try to do:

I have a plugin which on install() adds a value via provide to the app. Then I have a component which injects this value again and displays them. Both, the plugin and the component are in an imported module which is installed via npm. I also added both the plugin and the component directly into the app, to show that it only happens when I use the imported plugin and component.

What is expected?

Under Module Test Component it should output

Module inject: MODULE TEST

like it does under Local Test Component.

There should be no warning in the browser console.

What is actually happening?

The injection symbol can't be found and nothing is displayed in the imported component.

In the browser console this warning is visible:

[Vue warn]: injection "Symbol(module provide test)" not found. 
  at <ModuleTestComponent> 
  at <App>

Using the exact same injection symbol in a local component correctly injects the value.

System Info

No response

Any additional comments?

  • The imported module is not pre-built in any way, it just contains the source code. The project which imports the module should be in charge of building and bundling everything.
  • It works correct when building the project and running it.
  • It also works when I exclude the imported module in optimizeDeps, but I'm not sure if that's the expected behavior. (I've commented this in the provided vite.config.ts, so you can test it by just uncommenting this)
  • I've also done a quick test without typescript and without an injection key, just a normal string and it also seems to work.
avatar
Oct 30th 2022

Make sure to externalise vue when bundling a library using Vue. It cannot be a dependency

Remember to use the forum or the Discord chat to ask questions!

avatar
Nov 1st 2022

Thanks for your response, but externalise should only make a difference if the imported library is pre-built. As I'm not doing that, so basically normally importing the components, just from node_modules and build everything at the end, externalising shouldn't have any effects.

To test, I've updated my example code and put the vue dependency in the imported test library as peer- and devDependecy, but as expected there was no change in behavior.

avatar
Nov 21st 2022

Hello! I'm facing the same problem. I am importing a component from node_modules (which is presented as source code, not a build). It implements provide based on Symbol(). And in the main component, I do an inject() on the same symbol, but the attempt fails. At the same time, if the imported component is not in node_modules, but in src, then such a problem does not arise. What could this be related to?

avatar
Nov 22nd 2022

I think I understand what the problem is. Let's modify the module_test_plugin file.ts in @test/module and add console.log() to it:

import type { InjectionKey } from "vue";

console.log('Look at me!') // Added

export const moduleProvideTestKey = Symbol("module provide test") as InjectionKey<string>;

export const moduleTestPlugin = {
    install(app) {
        console.log("moduleTestPlugin::install()");
        app.provide(moduleProvideTestKey, "MODULE TEST");
    },
};

After launching the dev server in the browser console, a message from console.log() will be output 2 times. That is, the moduleProvideTestKey symbol will be defined 2 times. In this case, the first definition of the symbol will be used for provide() in the module files @test/module, and the second definition will be used for inject() in the main project. But since in fact two different symbols will be used, it will not be possible to establish a connection between provide() in @test/mode and inject() in the main project.

How would it be possible to formulate the problem in detail for a bug report in the vite repository?

avatar
Nov 23rd 2022

@PurpleTape you get two console logs because your setup includes two vue copies. use Vite's dedupeoption to make it ensure that the same Vue copy is used for all modules in your app.

avatar
Nov 24th 2022

I've also tested that and I can reproduce this behaviour. I've added a log to both the module_test_plugin.ts and test_plugin.ts. Adding vue or the @test/module to resolve.dedupe didn't help.

When I looked at the location where the logs were executed I saw this behaviour: grafik grafik

In the network tab I see only one file loaded, it contains to cache buster like the 1st one, but the path is the 2nd one. grafik

It's likely that this is a vite "problem".