Skip to content

Commit a5191f5

Browse files
committed
bug #484 Allow to import .vue files when using TypeScript (Lyrkan)
This PR was merged into the master branch. Discussion ---------- Allow to import .vue files when using TypeScript With the current default config importing a `.vue` file from a `.ts` file results in an error because the `ts-loader` don't know how to handle Vue files. This PR resolves that issue by setting the `appendTsSuffixTo` option of the `ts-loader` to `[/\.vue$/]` (as described [here](https://vue-loader.vuejs.org/guide/pre-processors.html#typescript)) when the `vue-loader` is enabled (fixes #467). Commits ------- 8bbc3f6 Allow to import .vue files when using TypeScript
2 parents 8f41783 + 8bbc3f6 commit a5191f5

File tree

7 files changed

+190
-0
lines changed

7 files changed

+190
-0
lines changed

fixtures/vuejs-typescript/App.vue

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<template>
2+
<div id="app">
3+
<img src="./assets/logo.png">
4+
<hello></hello>
5+
</div>
6+
</template>
7+
8+
<script lang="ts">
9+
import Vue from 'vue';
10+
import Hello from './components/Hello.vue'
11+
12+
class TestClassSyntax {
13+
14+
}
15+
16+
export default Vue.extend({
17+
name: 'app',
18+
components: {
19+
Hello
20+
}
21+
})
22+
</script>
23+
24+
<style>
25+
#app {
26+
font-family: 'Avenir', Helvetica, Arial, sans-serif;
27+
-webkit-font-smoothing: antialiased;
28+
-moz-osx-font-smoothing: grayscale;
29+
text-align: center;
30+
color: #2c3e50;
31+
margin-top: 60px;
32+
}
33+
</style>
34+
35+
<style lang="scss">
36+
#app {
37+
display: flex;
38+
color: #2c3e90;
39+
}
40+
</style>
41+
42+
<style lang="less">
43+
#app {
44+
margin-top: 40px;
45+
}
46+
</style>
6.69 KB
Loading
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<template>
2+
<div class="hello">
3+
<h1>{{ msg }}</h1>
4+
<h2>Essential Links</h2>
5+
<ul>
6+
<li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
7+
<li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
8+
<li><a href="https://gitter.im/vuejs/vue" target="_blank">Gitter Chat</a></li>
9+
<li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
10+
<br>
11+
<li><a href="http://vuejs-templates.github.io/webpack/" target="_blank">Docs for This Template</a></li>
12+
</ul>
13+
<h2>Ecosystem</h2>
14+
<ul>
15+
<li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
16+
<li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
17+
<li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
18+
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
19+
</ul>
20+
</div>
21+
</template>
22+
23+
<script lang="ts">
24+
import Vue from 'vue';
25+
26+
export default Vue.extend({
27+
name: 'hello',
28+
data () {
29+
return {
30+
msg: 'Welcome to Your Vue.js App'
31+
}
32+
}
33+
})
34+
</script>
35+
36+
<!-- Add "scoped" attribute to limit CSS to this component only -->
37+
<style scoped>
38+
h1, h2 {
39+
font-weight: normal;
40+
}
41+
42+
ul {
43+
list-style-type: none;
44+
padding: 0;
45+
}
46+
47+
li {
48+
display: inline-block;
49+
margin: 0 10px;
50+
}
51+
52+
a {
53+
color: #42b983;
54+
}
55+
</style>

fixtures/vuejs-typescript/main.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Vue from 'vue'
2+
import App from './App.vue'
3+
4+
new Vue({
5+
el: '#app',
6+
template: '<App/>',
7+
components: { App }
8+
})
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es6",
4+
"strict": true,
5+
"module": "es2015",
6+
"moduleResolution": "node"
7+
},
8+
"include": [
9+
"./**/*.ts",
10+
]
11+
}

lib/loaders/typescript.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ module.exports = {
4040
forkedTypesPluginUtil(webpackConfig);
4141
}
4242

43+
// allow to import .vue files
44+
if (webpackConfig.useVueLoader) {
45+
config.appendTsSuffixTo = [/\.vue$/];
46+
}
47+
4348
// use ts alongside with babel
4449
// @see https://github.com/TypeStrong/ts-loader/blob/master/README.md#babel
4550
let loaders = babelLoader.getLoaders(webpackConfig);

test/functional.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,71 @@ module.exports = {
12851285
});
12861286
});
12871287

1288+
it('Vue.js is compiled correctly using TypeScript', (done) => {
1289+
const appDir = testSetup.createTestAppDir();
1290+
1291+
fs.writeFileSync(
1292+
path.join(appDir, 'postcss.config.js'),
1293+
`
1294+
module.exports = {
1295+
plugins: [
1296+
require('autoprefixer')()
1297+
]
1298+
} `
1299+
);
1300+
1301+
const config = testSetup.createWebpackConfig(appDir, 'www/build', 'dev');
1302+
config.enableSingleRuntimeChunk();
1303+
config.setPublicPath('/build');
1304+
config.addEntry('main', './vuejs-typescript/main');
1305+
config.enableVueLoader();
1306+
config.enableSassLoader();
1307+
config.enableLessLoader();
1308+
config.enableTypeScriptLoader();
1309+
config.configureBabel(function(config) {
1310+
config.presets = [
1311+
['@babel/preset-env', {
1312+
'targets': {
1313+
'chrome': 52
1314+
}
1315+
}]
1316+
];
1317+
});
1318+
1319+
testSetup.runWebpack(config, (webpackAssert) => {
1320+
expect(config.outputPath).to.be.a.directory().with.deep.files([
1321+
'main.js',
1322+
'main.css',
1323+
'images/logo.82b9c7a5.png',
1324+
'manifest.json',
1325+
'entrypoints.json',
1326+
'runtime.js',
1327+
]);
1328+
1329+
// test that our custom babel config is used
1330+
webpackAssert.assertOutputFileContains(
1331+
'main.js',
1332+
'class TestClassSyntax'
1333+
);
1334+
1335+
testSetup.requestTestPage(
1336+
path.join(config.getContext(), 'www'),
1337+
[
1338+
'build/runtime.js',
1339+
'build/main.js'
1340+
],
1341+
(browser) => {
1342+
// assert that the vue.js app rendered
1343+
browser.assert.text('#app h1', 'Welcome to Your Vue.js App');
1344+
// make sure the styles are not inlined
1345+
browser.assert.elements('style', 0);
1346+
1347+
done();
1348+
}
1349+
);
1350+
});
1351+
});
1352+
12881353
it('Vue.js error when using non-activated loaders', (done) => {
12891354
const config = createWebpackConfig('www/build', 'dev');
12901355
config.setPublicPath('/build');

0 commit comments

Comments
 (0)