-
-
Notifications
You must be signed in to change notification settings - Fork 399
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
How to configure volar so that it resolves global / auto-imported components when they are not explicitly imported inside <script>
tag?
#889
Comments
<script>
tag?<script>
tag?
One thing I just tried is adding a declare module '@vue/runtime-core' {
export interface GlobalComponents {
FancyButton: typeof import('components/FancyButton.vue').default
}
}
export {} But there are two issues I still have:
|
Actually I'm not familiar with nuxt and I'm not sure about nuxt best practices. But I see that in your screenshot: I guess this file will be create when you run build command, and it may have types that volar needed. If you already have this file but global component types still missing, you may need to define If it still not working, nuxt discord server is better to ask for help: https://discord.com/invite/ps2h6QT |
Nuxt (v2) doesn't auto-generate types for |
I have created a package that generates global component type definitions by specifying a directory. |
@johnsoncodehk do you think it would be possible to dynamically generate those types in memory through the plugin infrastructure in the future (or now already)? Or it's not likely? |
Cool! But you said in that PR:
Which is a bit of a roadblock for me because I wouldn't want to use that mode necessarily. |
If TypeScript Plugin or Takeover mode is not enabled, Volar cannot make the type generated in memory affect *.ts, but only affect *.vue. On the other hand, when Nuxt is starting the dev server, it generates real .d.ts files instead of memory files, so there are no such limitations. |
Nuxt 3 generates types but not Nuxt 2. The intention here is to have type augmentations added for local Vue components so that those are recognized when used in other local Vue components. So there are no *.ts files involved in that (unless you are talking about internal, virtual *.ts files). |
This actually works (without takeover mode): /** @type {import('@volar/language-core').LanguageModule} */
module.exports = {
createFile() {
return undefined;
},
updateFile() {},
proxyLanguageServiceHost(host) {
const ts = host.getTypeScriptModule();
const vueTypesScript = {
projectVersion: '',
fileName: host.getCurrentDirectory() + '/generated-component-types.d.ts',
_version: 0,
_snapshot: ts?.ScriptSnapshot.fromString(''),
get version() {
this.update();
return this._version;
},
get snapshot() {
this.update();
return this._snapshot;
},
update() {
if (!this._snapshot) {
return
}
if (!host.getProjectVersion || host.getProjectVersion() !== this.projectVersion) {
this.projectVersion = host.getProjectVersion?.() ?? '';
const newText = this.generateText();
console.error({newText})
if (newText !== this._snapshot.getText(0, this._snapshot.getLength())) {
this._version++;
this._snapshot = ts?.ScriptSnapshot.fromString(newText);
}
}
},
generateText() {
const projectFileNames = host.getScriptFileNames().map(fileName => fileName.replace(host.getCurrentDirectory() + '/', ''));
const vueFiles = projectFileNames.filter(fileName => (fileName.startsWith('pages/') || fileName.startsWith('components/')) && fileName.endsWith('.vue'));
const components = vueFiles
.map(path => {
const filename = path.split('/').pop()
if (!filename) {
return
}
const [basename, _] = filename.split('.')
return {
name: basename,
path,
}
})
.filter(Boolean)
return `
declare module '@vue/runtime-core' {
export interface GlobalComponents {
${components.map(component => `${component.name}: typeof import('${component.path}').default`).join(('\n'))}
${components.map(component => `Lazy${component.name}: typeof import('${component.path}').default`).join(('\n'))}
}
}
`;
},
};
return {
getScriptFileNames() {
return [
...host.getScriptFileNames(),
vueTypesScript.fileName,
];
},
getScriptVersion(fileName) {
if (fileName === vueTypesScript.fileName) {
return String(vueTypesScript.version);
}
return host.getScriptVersion(fileName);
},
getScriptSnapshot(fileName) {
if (fileName === vueTypesScript.fileName) {
return vueTypesScript.snapshot;
}
return host.getScriptSnapshot(fileName);
},
}
},
}; The only issue I see is that the "go to definition" doesn't work. Is that something that can be made to work with some extra code in the module? |
This is possible, but I can't check it for now. Can you open a feature request? |
Hello,
I'm using Nuxt v2 (
"nuxt-edge": "^2.16.0-27335535.777a4b7f"
) with Composition API so I'm also using Volar v0.31.1.Unfortunately, since today it seems that a lot of my (own) components, as well as components from libraries (e.g.
<NuxtImg>
), seem to not be resolved which results in them shown red and related IntelliSense not working.All those vue components are auto-imported via the
components
property ofnuxt.config.js
which is a built-in feature of nuxt and everyone is using it by default.Some other components are also auto-imported via
unplugin-auto-import/nuxt
Is there a way to configure volar so that it resolves those imports when they are not explicitly specified inside
<script>
?To be more specific, if the following code is all that I put in a .vue file (without even using a
<script>
tag), vue and nuxt compile and show it just fine on the page, but Volar cannot resolve the import of mycomponents/FancyButton.vue
.Thank you so much for this amazing extension!
The text was updated successfully, but these errors were encountered: