Skip to content

Commit fd9d323

Browse files
bluwyDan Jutan
andauthored
Support Vue JSX (#4897)
Co-authored-by: Dan Jutan <danjutan@gmail.com>
1 parent 24bad5a commit fd9d323

12 files changed

Lines changed: 329 additions & 5 deletions

File tree

.changeset/honest-melons-walk.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@astrojs/vue': minor
3+
'astro': patch
4+
---
5+
6+
Support Vue JSX

packages/astro/src/runtime/server/render/component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function guessRenderers(componentUrl?: string): string[] {
2727
return ['@astrojs/vue'];
2828
case 'jsx':
2929
case 'tsx':
30-
return ['@astrojs/react', '@astrojs/preact'];
30+
return ['@astrojs/react', '@astrojs/preact', '@astrojs/vue (jsx)'];
3131
default:
3232
return ['@astrojs/react', '@astrojs/preact', '@astrojs/vue', '@astrojs/svelte'];
3333
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'astro/config';
2+
import vue from '@astrojs/vue';
3+
4+
// https://astro.build/config
5+
export default defineConfig({
6+
integrations: [vue({ jsx: true })],
7+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@test/vue-jsx",
3+
"version": "0.0.0",
4+
"private": true,
5+
"dependencies": {
6+
"@astrojs/vue": "workspace:*",
7+
"astro": "workspace:*",
8+
"vue": "^3.2.39"
9+
}
10+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { defineComponent, ref } from 'vue';
2+
3+
export default defineComponent({
4+
props: {
5+
start: {
6+
type: String,
7+
required: true
8+
},
9+
stepSize: {
10+
type: String,
11+
default: "1"
12+
}
13+
},
14+
setup(props) {
15+
const count = ref(parseInt(props.start))
16+
const stepSize = ref(parseInt(props.stepSize))
17+
const add = () => (count.value = count.value + stepSize.value);
18+
const subtract = () => (count.value = count.value - stepSize.value);
19+
return () => (
20+
<div class="counter">
21+
<h1><slot /></h1>
22+
<button onClick={subtract}>-</button>
23+
<pre>{count.value}</pre>
24+
<button onClick={add}>+</button>
25+
</div>
26+
)
27+
},
28+
})
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<pre>{{ value }}</pre>
3+
</template>
4+
5+
<script>
6+
7+
export default {
8+
props: {
9+
value: {
10+
type: Number,
11+
required: true
12+
}
13+
}
14+
}
15+
</script>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
import Counter from '../components/Counter.jsx'
3+
import Result from '../components/Result.vue'
4+
---
5+
<html lang="en">
6+
<head>
7+
<meta charset="utf-8" />
8+
<meta
9+
name="viewport"
10+
content="width=device-width"
11+
/>
12+
<title>Vue component</title>
13+
<style>
14+
:global(:root) {
15+
font-family: system-ui;
16+
padding: 1em;
17+
}
18+
</style>
19+
</head>
20+
<body>
21+
<main>
22+
<Result value={2345}></Result>
23+
<Counter start="0">SSR Rendered, No Client</Counter>
24+
<Counter start="1" client:load>SSR Rendered, client:load</Counter>
25+
<!-- Test island deduplication, i.e. same UID as the component above. -->
26+
<Counter start="1" client:load>SSR Rendered, client:load</Counter>
27+
<!-- Test island deduplication account for non-render affecting props. -->
28+
<Counter start="1" step-size="2" client:load>SSR Rendered, client:load</Counter>
29+
<Counter start="10" client:idle>SSR Rendered, client:idle</Counter>
30+
<!-- Test that two client:visibles have unique uids -->
31+
<Counter start="100" client:visible>SSR Rendered, client:visible</Counter>
32+
<Counter start="1000" client:visible>SSR Rendered, client:visible</Counter>
33+
</main>
34+
</body>
35+
</html>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { expect } from 'chai';
2+
import * as cheerio from 'cheerio';
3+
import { loadFixture } from './test-utils.js';
4+
5+
describe('Vue JSX', () => {
6+
let fixture;
7+
8+
before(async () => {
9+
fixture = await loadFixture({
10+
root: './fixtures/vue-jsx/',
11+
});
12+
});
13+
14+
describe('build', () => {
15+
before(async () => {
16+
await fixture.build();
17+
});
18+
19+
it('Can load Vue JSX', async () => {
20+
const html = await fixture.readFile('/index.html');
21+
const $ = cheerio.load(html);
22+
23+
const allPreValues = $('pre')
24+
.toArray()
25+
.map((el) => $(el).text());
26+
27+
expect(allPreValues).to.deep.equal(['2345', '0', '1', '1', '1', '10', '100', '1000']);
28+
});
29+
});
30+
});

packages/integrations/vue/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,40 @@ export default {
9494
})],
9595
}
9696
```
97+
98+
### jsx
99+
100+
You can use Vue JSX by setting `jsx: true`.
101+
102+
__`astro.config.mjs`__
103+
104+
```js
105+
import { defineConfig } from 'astro/config';
106+
import vue from '@astrojs/vue';
107+
108+
export default defineConfig({
109+
integrations: [
110+
vue({ jsx: true })
111+
],
112+
});
113+
```
114+
115+
This will enable rendering for both Vue and Vue JSX components. To customize the Vue JSX compiler, pass an options object instead of a boolean. See the `@vitejs/plugin-vue-jsx` [docs](https://github.com/vitejs/vite/tree/main/packages/plugin-vue-jsx) for more details.
116+
117+
__`astro.config.mjs`__
118+
119+
```js
120+
import { defineConfig } from 'astro/config';
121+
import vue from '@astrojs/vue';
122+
123+
export default defineConfig({
124+
integrations: [
125+
vue({
126+
jsx: {
127+
// treat any tag that starts with ion- as custom elements
128+
isCustomElement: tag => tag.startsWith('ion-')
129+
}
130+
})
131+
],
132+
});
133+
```

packages/integrations/vue/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
},
3535
"dependencies": {
3636
"@vitejs/plugin-vue": "^3.0.0",
37+
"@vitejs/plugin-vue-jsx": "^2.0.1",
38+
"@vue/babel-plugin-jsx": "^1.1.1",
3739
"@vue/compiler-sfc": "^3.2.39"
3840
},
3941
"devDependencies": {

0 commit comments

Comments
 (0)