Versions:
When opening a .vue file that hasn't been opened then false errors will be reported.
Issues:
tsconfig.json but it is reported as though it is disabled.tsconfig.json) it reports module not foundThese issues do not occur in normal *.ts files and there aren't any compiler errors. The workaround is to restart VSCode with the file opened, and these issues no longer appear until it is closed and opened again.
home.vue (template and style tags removed)
<script lang="ts">
import Component from 'vue-class-component';
import Vue from 'vue';
// const Sidebar = require('../components/sidebar.vue').default; // Error require not found
import Sidebar from '../components/sidebar'; // Error module not found (need the .vue extension to workaround)
import settings from 'settings'; // Error module not found (need to import with relative paths to workaround)
@Component({ // Error experimentalDecorators are disabled and needs to be set
components: {
Sidebar
}
})
export default class Home extends Vue {
}
</script>
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"outDir": "dist",
"baseUrl": ".",
"rootDirs": [
"../common",
"./src/main",
"./src/renderer"
],
"paths": {
"pm_common": ["../common"],
"settings": ["./src/main/settings"]
}
},
"exclude": [
"node_modules",
"dist"
]
}
I have no idea why error occurs but why are you not use import to get vue file?
import Sidebar from './../components/sidebar.vue';
// const Sidebar = require('../components/sidebar.vue').default
all you need to do is to add definition file to that will say to TypeScript that file with *.vue extension is a Vue component
// vue-module.d.ts
declare module "*.vue" {
import Vue from 'vue'
export default typeof Vue
}
@ppasieka Thanks for the tip! I wasn't aware of declaring the module.
However with webpack the extension must be omitted in the import to compile correctly. This results in another false error report of 'Cannot find module' in VSCode (which goes away when the editor is restarted).
Everything compiles fine with the Typescript compiler with the extension emitted and omitted.
hmm...
Please check if your webpack config for ts-loader have appendTsSuffixTo: [/\.vue$/] option set
Highly recommend to compare your setup with https://github.com/Microsoft/TypeScript-Vue-Starter
{
loader: 'ts-loader',
test: /\.ts$/,
options: {
appendTsSuffixTo: [/\.vue$/]
}
}
It's now working with the .vue extension. ๐ The only downside is imports will be slightly inconsistent since I never include the extension when importing, with the exception being .vue.
There is another issue I have noticed, it appears aliases (paths) from tsconfig.json are not supported. import settings from 'settings' says Cannot find module. Unfortunately, the only work around for this one is to import with relative paths (which defeats the purpose of paths). I'll add this to the list of issues.
There is another issue I have noticed, it appears aliases (paths) from tsconfig.json are not supported. import settings from 'settings' says Cannot find module.
As for your settings, is it a vue file or js/ts file?
I've never used paths before, but through my limited testing VSCode seems to be throwing the same error module not found.
It'd be helpful if you can try to fork & modify this project to make a repro case: https://github.com/Microsoft/TypeScript-Vue-Starter
As for
import Sidebar from './../components/sidebar'; // Without .vue at the end
@sandersn is it possible to config TS so it doesn't report this as error? We do have this in javascriptMode which should handle vue extension import correctly...right?
https://github.com/octref/vetur/blob/master/server/src/modes/javascriptMode.ts#L49-L55
const parsedConfig = ts.parseJsonConfigFileContent(configJson,
ts.sys,
workspacePath,
compilerOptions,
configFilename,
undefined,
[{ extension: 'vue', isMixedContent: true }]);
@samrg472 Also, your way of using paths seems to differ from the official doc: https://www.typescriptlang.org/docs/handbook/module-resolution.html
I figured out the issue with paths. When you open a directory the tsconfig.json must be in the root of the editor.
--- No `paths` issue
โโ src/
โโ tsconfig.json
--- `paths` issue happens
Root folder
โโ client/
โ โโโ src/
โ โโโ tsconfig.json
โโ server/
โ โโโ src/
โ โโโ tsconfig.json
Hopefully I was able to explain this clearly enough. Looks like I'll have to open each project individually to work around this.
This also fixes the require issue, and the experimentalDecorators issue. I noticed that the *.vue import extension requirement is on the typescript compiler and webpack automatically resolves this for the compiler (hence the typescript error but no webpack issue).
It appears the real issue is improper dealing with sub-project directories.
Edit: The title may want to be changed to reflect the root of this issue.
@octref regarding importing vue files without the extension, it is probably possible to make this work by making resolveModuleNames in javascriptMode.ts smarter. The code you linked just makes the compiler accept .vue files if they are referenced.
Right now, resolveModuleNames delegates to ts.resolveModuleName for the non-extension case, which is the case that @samrg472 wants to work for .vue files.
```ts
resolveModuleNames (moduleNames: string[], containingFile: string): ts.ResolvedModule[] {
// in the normal case, delegate to ts.resolveModuleName
// in the relative-imported.vue case, manually build a resolved filename
return moduleNames.map(name => {
if (path.isAbsolute(name) || !isVue(name)) {
return ts.resolveModuleName(name, containingFile, compilerOptions, ts.sys).resolvedModule;
}
else {
const uri = Uri.file(path.join(path.dirname(containingFile), name));
const resolvedFileName = uri.fsPath;
if (ts.sys.fileExists(resolvedFileName)) {
const doc = docs.get(resolvedFileName) ||
jsDocuments.get(TextDocument.create(uri.toString(), 'vue', 0, ts.sys.readFile(resolvedFileName)));
return {
resolvedFileName,
extension: doc.languageId === 'typescript' ? ts.Extension.Ts : ts.Extension.Js,
};
}
}
});
},
````
For the simple case — relative paths with an explicit .vue extension — name is safe to treat as if it were a path to an actual file. For the complex case, the compiler is doing work to (1) resolve name to actual paths (2) decide which paths best match name. To get non-extension or absolute imports to work, resolveModuleNames needs to copy some of that work. Specifically:
To support import Sidebar from '../components/Sidebar', isVue would have to check ../components for ../components/Sidebar.ts, ../components/Sidebar.js, ../components/Sidebar.vue. If you find more than one, you to have to decide which one takes precedence (or whether it's an error). Then isVue should probably return the chosen path to resolveModuleNames so that it can create a TextDocument for it, etc.
To support import Sidebar from 'sidebar', isVue would additionally have to check all the paths that the compiler would check, check for all the extensions, and return the path of the best match. This is considerably more work. But it looks like @samrg472 doesn't necessarily need this to work, if I'm reading the code correctly.
Basic support for no-extension imports would probably be pretty easy, but it might be harder to do it exactly the way the compiler does it. I'd recommend looking through the source code to find out what it does.
To support import Sidebar from '../components/Sidebar', isVue would have to check ../components for ../components/Sidebar.ts, ../components/Sidebar.js, ../components/Sidebar.vue. If you find more than one, you to have to decide which one takes precedence (or whether it's an error). Then isVue should probably return the chosen path to resolveModuleNames so that it can create a TextDocument for it, etc.
Thanks. That makes sense & I'll do it soon.
@samrg472 Putting the tsconfig.json as the root of my project fixes the issue on mine too. Kind of annoying as my project is in a sub-directory of a non-typescript project.
It looks like vetur looks for the tsconfig file here and the workspacePath variable defaults to either the rootPath passed in by VSCode (Which works out the root of the project), or the result of process.cwd().
As for the extension omission, I wonder how it works with ts-loader/ATL.
Close due to inactivity.
If any one still meets the problem of extension omission, please reopen this issue and report a valid configuration for webpack as I cannot reproduce a working config.
Hello. It's about the .vue extension omission issue.
$ vue init akiralaine/vuets vuets-test
In src/App.vue no warning if I add a .vue extension to ./components/Home import
In src/main.ts it warns even when adding the extension to ./App
I then I wanted to try on veturpack but there it doesn't even check any imports (no warning even with a dummy path).
It's maybe an issue on my side idk.
VSCode and Vetur versions as of today.
Thanks for your time.
We don't support .vue extension omission.
We only report errors in script with lang="ts".
You need to add typing.d.ts to import SFC in plain ts file. declare module "*.vue";
Thanks for your answer, it makes total sense now.
Is thiis still unsupported? If still not supported, would it be possible to add the suggested code for resolving to .vue automatiicall and then explicetily enable it from a settinig. Took me a while to realize what's wrong with the import until I had a look at the ms/typescript-vue-starter.
You need to install awesome-typescript-loader package, then you can import without .vue extension
Most helpful comment
Is thiis still unsupported? If still not supported, would it be possible to add the suggested code for resolving to .vue automatiicall and then explicetily enable it from a settinig. Took me a while to realize what's wrong with the import until I had a look at the ms/typescript-vue-starter.