Skip to content

Commit d6f0b34

Browse files
authored
Merge pull request TypeStrong#94 from wonderful-panda/improve-vue-module-resolution
Improve module resolution of *.vue
2 parents 9bc9146 + 9de3ce3 commit d6f0b34

File tree

9 files changed

+121
-5
lines changed

9 files changed

+121
-5
lines changed

src/VueProgram.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,29 @@ class VueProgram {
149149

150150
for (const moduleName of moduleNames) {
151151
// Try to use standard resolution.
152-
const result = ts.resolveModuleName(moduleName, containingFile, programConfig.options, {
153-
fileExists: host.fileExists,
154-
readFile: host.readFile
152+
const { resolvedModule } = ts.resolveModuleName(moduleName, containingFile, programConfig.options, {
153+
fileExists(fileName) {
154+
if (fileName.endsWith('.vue.ts')) {
155+
return host.fileExists(fileName.slice(0, -3)) || host.fileExists(fileName);
156+
} else {
157+
return host.fileExists(fileName);
158+
}
159+
},
160+
readFile(fileName) {
161+
// This implementation is not necessary. Just for consistent behavior.
162+
if (fileName.endsWith('.vue.ts') && !host.fileExists(fileName)) {
163+
return host.readFile(fileName.slice(0, -3));
164+
} else {
165+
return host.readFile(fileName);
166+
}
167+
}
155168
});
156169

157-
if (result.resolvedModule) {
158-
resolvedModules.push(result.resolvedModule);
170+
if (resolvedModule) {
171+
if (resolvedModule.resolvedFileName.endsWith('vue.ts') && !host.fileExists(resolvedModule.resolvedFileName)) {
172+
resolvedModule.resolvedFileName = resolvedModule.resolvedFileName.slice(0, -3);
173+
}
174+
resolvedModules.push(resolvedModule);
159175
} else {
160176
// For non-ts extensions.
161177
const absolutePath = VueProgram.resolveNonTsModuleName(moduleName, containingFile, basedir, programConfig.options);

test/integration/vue.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,42 @@ describe('[INTEGRATION] vue', function () {
234234
expect(errors['example-nolang.vue'].length).to.be.equal(0);
235235
});
236236
});
237+
238+
describe('should resolve *.vue in the same way as TypeScript', function() {
239+
var errors;
240+
before(function(callback) {
241+
createCompiler({ vue: true, tsconfig: 'tsconfig-imports.json' });
242+
compiler.run(function(error, stats) {
243+
errors = stats.compilation.errors;
244+
callback();
245+
});
246+
});
247+
248+
it('should be able to import by relative path', function() {
249+
expect(
250+
errors.filter(e => e.rawMessage.indexOf('./Component1.vue') >= 0).length
251+
).to.be.equal(0);
252+
});
253+
it('should be able to import by path from baseUrl', function() {
254+
expect(
255+
errors.filter(e => e.rawMessage.indexOf('imports/Component2.vue') >= 0).length
256+
).to.be.equal(0);
257+
});
258+
it('should be able to import by compilerOptions.paths setting', function() {
259+
expect(
260+
errors.filter(e => e.rawMessage.indexOf('@/Component3.vue') >= 0).length
261+
).to.be.equal(0);
262+
});
263+
it('should be able to import by compilerOptions.paths setting (by array)', function() {
264+
expect(
265+
errors.filter(e => e.rawMessage.indexOf('foo/Foo1.vue') >= 0).length
266+
).to.be.equal(0);
267+
expect(
268+
errors.filter(e => e.rawMessage.indexOf('foo/Foo2.vue') >= 0).length
269+
).to.be.equal(0);
270+
});
271+
it('should not report any compilation errors', function() {
272+
expect(errors.length).to.be.equal(0);
273+
});
274+
});
237275
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<div>This is Component1</div>
3+
</template>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<div>This is Component2</div>
3+
</template>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<div>This is Component3</div>
3+
</template>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<script lang="ts">
2+
// resolve by relative path
3+
import Component1 from "./Component1.vue"; // imports/Component1.vue
4+
5+
// resolve by path from baseUrl(./src)
6+
import Component2 from "imports/Component2.vue"; // imports/Component2.vue
7+
8+
// resolve by compilerOptions.paths
9+
// { "@/*": ["imports/*"] }
10+
import Component3 from "@/Component3.vue"; // imports/Component3.vue
11+
12+
// resolve by compilerOptions.paths
13+
// { "foo/*": ["imports/foo1/*", "imports/foo2/*"] }
14+
import Foo1 from "foo/Foo1.vue"; // imports/foo1/Foo1.vue
15+
import Foo2 from "foo/Foo2.vue"; // imports/foo2/Foo2.vue
16+
17+
export default {
18+
name: "ImportTest",
19+
components: {
20+
Component1,
21+
Component2,
22+
Component3,
23+
Foo1,
24+
Foo2
25+
}
26+
};
27+
</script>
28+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<div>This is Foo1</div>
3+
</template>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<div>This is Foo2</div>
3+
</template>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": "./src",
4+
"moduleResolution": "node",
5+
"paths": {
6+
"@/*": ["imports/*"],
7+
"foo/*": [
8+
"imports/foo1/*",
9+
"imports/foo2/*"
10+
]
11+
}
12+
},
13+
"include": [
14+
"imports/Test.vue"
15+
],
16+
"exclude": [
17+
"node_modules"
18+
]
19+
}

0 commit comments

Comments
 (0)