fix tsx+jsx error (#916)
* fix tsx+jsx error * throw error if no build can be returned
This commit is contained in:
parent
189098b6e5
commit
829d5baafe
14 changed files with 91 additions and 19 deletions
5
.changeset/heavy-ears-hope.md
Normal file
5
.changeset/heavy-ears-hope.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix TSX issue with JSX multi-rendering
|
|
@ -23,6 +23,10 @@ function getLoader(fileExt) {
|
||||||
return fileExt.substr(1);
|
return fileExt.substr(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The `tsx` loader in esbuild will remove unused imports, so we need to
|
||||||
|
// be careful about esbuild not treating h, React, Fragment, etc. as unused.
|
||||||
|
const PREVENT_UNUSED_IMPORTS = ';;(React,Fragment,h);';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {import('snowpack').SnowpackPluginFactory<PluginOptions>}
|
* @type {import('snowpack').SnowpackPluginFactory<PluginOptions>}
|
||||||
*/
|
*/
|
||||||
|
@ -74,18 +78,8 @@ module.exports = function jsxPlugin(config, options = {}) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (importSources.size === 0) {
|
if (importSources.size === 0) {
|
||||||
error(
|
throw new Error(`${colors.yellow(filePath)}
|
||||||
logging,
|
Unable to resolve a renderer that handles JSX transforms! Please include a \`renderer\` plugin which supports JSX in your \`astro.config.mjs\` file.`);
|
||||||
'renderer',
|
|
||||||
`${colors.yellow(filePath)}
|
|
||||||
Unable to resolve a renderer that handles JSX transforms! Please include a \`renderer\` plugin which supports JSX in your \`astro.config.mjs\` file.`
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
'.js': {
|
|
||||||
code: '',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we only have a single renderer, we can skip a bunch of work!
|
// If we only have a single renderer, we can skip a bunch of work!
|
||||||
|
@ -99,10 +93,10 @@ Unable to resolve a renderer that handles JSX transforms! Please include a \`ren
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need valid JS to scan for imports
|
// we need valid JS here, so we can use `h` and `Fragment` as placeholders
|
||||||
// so let's just use `h` and `Fragment` as placeholders
|
// NOTE(fks, matthewp): Make sure that you're transforming the original contents here.
|
||||||
const { code: codeToScan } = await esbuild.transform(code, {
|
const { code: codeToScan } = await esbuild.transform(contents + PREVENT_UNUSED_IMPORTS, {
|
||||||
loader: 'jsx',
|
loader,
|
||||||
jsx: 'transform',
|
jsx: 'transform',
|
||||||
jsxFactory: 'h',
|
jsxFactory: 'h',
|
||||||
jsxFragment: 'Fragment',
|
jsxFragment: 'Fragment',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/** @jsxImportSource preact */
|
/** @jsxImportSource preact */
|
||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
return <div id="pragma-comment">Hello world</div>;
|
return <div class="pragma-comment">Hello world</div>;
|
||||||
}
|
}
|
||||||
|
|
5
packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx
vendored
Normal file
5
packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/** @jsxImportSource preact */
|
||||||
|
|
||||||
|
export default function({}: object) {
|
||||||
|
return <div class="pragma-comment">Hello world</div>;
|
||||||
|
}
|
5
packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx
vendored
Normal file
5
packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import {h} from 'preact';
|
||||||
|
|
||||||
|
export default function({}: object) {
|
||||||
|
return <div class="ts-component">Hello world</div>;
|
||||||
|
}
|
|
@ -1,10 +1,14 @@
|
||||||
---
|
---
|
||||||
import PragmaComponent from '../components/PragmaComment.jsx';
|
import PragmaComponent from '../components/PragmaComment.jsx';
|
||||||
|
import PragmaComponentTypeScript from '../components/PragmaCommentTypeScript.tsx';
|
||||||
---
|
---
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Preact component works with Pragma comment</title>
|
<title>Preact component works with Pragma comment</title>
|
||||||
</head>
|
</head>
|
||||||
<body><PragmaComponent client:load/></body>
|
<body>
|
||||||
|
<PragmaComponent client:load/>
|
||||||
|
<PragmaComponentTypeScript client:load/>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
12
packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro
vendored
Normal file
12
packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
import TypeScriptComponent from '../components/TypeScriptComponent.tsx';
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Preact TS component</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<TypeScriptComponent client:load />
|
||||||
|
</body>
|
||||||
|
</html>
|
5
packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx
vendored
Normal file
5
packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/** @jsxImportSource react */
|
||||||
|
|
||||||
|
export default function() {
|
||||||
|
return <div className="pragma-comment">Hello world</div>;
|
||||||
|
}
|
5
packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx
vendored
Normal file
5
packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/** @jsxImportSource react */
|
||||||
|
|
||||||
|
export default function({}: object) {
|
||||||
|
return <div className="pragma-comment">Hello world</div>;
|
||||||
|
}
|
5
packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx
vendored
Normal file
5
packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function({}) {
|
||||||
|
return <div className="ts-component">Hello world</div>;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import Later from '../components/Goodbye.vue'; // use different specifier
|
||||||
import ArrowFunction from '../components/ArrowFunction.jsx';
|
import ArrowFunction from '../components/ArrowFunction.jsx';
|
||||||
import PropsSpread from '../components/PropsSpread.jsx';
|
import PropsSpread from '../components/PropsSpread.jsx';
|
||||||
import {Research2} from '../components/Research.jsx';
|
import {Research2} from '../components/Research.jsx';
|
||||||
|
import TypeScriptComponent from '../components/TypeScriptComponent';
|
||||||
|
|
||||||
const someProps = {
|
const someProps = {
|
||||||
text: 'Hello world!',
|
text: 'Hello world!',
|
||||||
|
@ -20,5 +21,6 @@ const someProps = {
|
||||||
<ArrowFunction />
|
<ArrowFunction />
|
||||||
<PropsSpread {...someProps}/>
|
<PropsSpread {...someProps}/>
|
||||||
<Research2 client:idle />
|
<Research2 client:idle />
|
||||||
|
<TypeScriptComponent client:load />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
14
packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro
vendored
Normal file
14
packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
import PragmaComponent from '../components/PragmaComment.jsx';
|
||||||
|
import PragmaComponentTypeScript from '../components/PragmaCommentTypeScript.tsx';
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>React component works with Pragma comment</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<PragmaComponent client:load/>
|
||||||
|
<PragmaComponentTypeScript client:load/>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -25,6 +25,14 @@ PreactComponent('Can load function component', async ({ runtime }) => {
|
||||||
assert.equal($('#arrow-fn-component').length, 1, 'Can use function components');
|
assert.equal($('#arrow-fn-component').length, 1, 'Can use function components');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PreactComponent('Can load TS component', async ({ runtime }) => {
|
||||||
|
const result = await runtime.load('/ts-components');
|
||||||
|
assert.ok(!result.error, `build error: ${result.error}`);
|
||||||
|
const $ = doc(result.contents);
|
||||||
|
assert.equal($('.ts-component').length, 1, 'Can use TS components');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
PreactComponent('Can use hooks', async ({ runtime }) => {
|
PreactComponent('Can use hooks', async ({ runtime }) => {
|
||||||
const result = await runtime.load('/hooks');
|
const result = await runtime.load('/hooks');
|
||||||
assert.ok(!result.error, `build error: ${result.error}`);
|
assert.ok(!result.error, `build error: ${result.error}`);
|
||||||
|
@ -46,7 +54,7 @@ PreactComponent('Can use a pragma comment', async ({ runtime }) => {
|
||||||
assert.ok(!result.error, `build error: ${result.error}`);
|
assert.ok(!result.error, `build error: ${result.error}`);
|
||||||
|
|
||||||
const $ = doc(result.contents);
|
const $ = doc(result.contents);
|
||||||
assert.equal($('#pragma-comment').length, 1, 'rendered the PragmaComment component.');
|
assert.equal($('.pragma-comment').length, 2, 'rendered the PragmaComment component.');
|
||||||
});
|
});
|
||||||
|
|
||||||
PreactComponent('Uses the new JSX transform', async ({ runtime }) => {
|
PreactComponent('Uses the new JSX transform', async ({ runtime }) => {
|
||||||
|
|
|
@ -43,6 +43,7 @@ React('Can load React', async () => {
|
||||||
assert.equal($('#arrow-fn-component').length, 1, 'Can use function components');
|
assert.equal($('#arrow-fn-component').length, 1, 'Can use function components');
|
||||||
assert.equal($('#component-spread-props').length, 1, 'Can use spread for components');
|
assert.equal($('#component-spread-props').length, 1, 'Can use spread for components');
|
||||||
assert.equal($('#component-spread-props').text(), 'Hello world!');
|
assert.equal($('#component-spread-props').text(), 'Hello world!');
|
||||||
|
assert.equal($('.ts-component').length, 1, 'Can use TS components');
|
||||||
});
|
});
|
||||||
|
|
||||||
React('Includes reactroot on hydrating components', async () => {
|
React('Includes reactroot on hydrating components', async () => {
|
||||||
|
@ -74,6 +75,13 @@ React('Can load Vue', async () => {
|
||||||
assert.equal($('#vue-h2').text(), 'Hasta la vista, baby');
|
assert.equal($('#vue-h2').text(), 'Hasta la vista, baby');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
React('Can use a pragma comment', async () => {
|
||||||
|
const result = await runtime.load('/pragma-comment');
|
||||||
|
assert.ok(!result.error, `build error: ${result.error}`);
|
||||||
|
const $ = doc(result.contents);
|
||||||
|
assert.equal($('.pragma-comment').length, 2, 'rendered the PragmaComment component.');
|
||||||
|
});
|
||||||
|
|
||||||
React('uses the new JSX transform', async () => {
|
React('uses the new JSX transform', async () => {
|
||||||
const result = await runtime.load('/');
|
const result = await runtime.load('/');
|
||||||
assert.ok(!result.error, `build error: ${result.error}`);
|
assert.ok(!result.error, `build error: ${result.error}`);
|
||||||
|
|
Loading…
Reference in a new issue