fix tsx+jsx error (#916)

* fix tsx+jsx error

* throw error if no build can be returned
This commit is contained in:
Fred K. Schott 2021-07-28 11:31:50 -07:00 committed by GitHub
parent 189098b6e5
commit 829d5baafe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 91 additions and 19 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fix TSX issue with JSX multi-rendering

View file

@ -23,6 +23,10 @@ function getLoader(fileExt) {
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>}
*/
@ -74,18 +78,8 @@ module.exports = function jsxPlugin(config, options = {}) {
};
if (importSources.size === 0) {
error(
logging,
'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: '',
},
};
throw new Error(`${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.`);
}
// 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
// so let's just use `h` and `Fragment` as placeholders
const { code: codeToScan } = await esbuild.transform(code, {
loader: 'jsx',
// we need valid JS here, so we can 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(contents + PREVENT_UNUSED_IMPORTS, {
loader,
jsx: 'transform',
jsxFactory: 'h',
jsxFragment: 'Fragment',

View file

@ -1,5 +1,5 @@
/** @jsxImportSource preact */
export default function() {
return <div id="pragma-comment">Hello world</div>;
return <div class="pragma-comment">Hello world</div>;
}

View file

@ -0,0 +1,5 @@
/** @jsxImportSource preact */
export default function({}: object) {
return <div class="pragma-comment">Hello world</div>;
}

View file

@ -0,0 +1,5 @@
import {h} from 'preact';
export default function({}: object) {
return <div class="ts-component">Hello world</div>;
}

View file

@ -1,10 +1,14 @@
---
import PragmaComponent from '../components/PragmaComment.jsx';
import PragmaComponentTypeScript from '../components/PragmaCommentTypeScript.tsx';
---
<html>
<head>
<title>Preact component works with Pragma comment</title>
</head>
<body><PragmaComponent client:load/></body>
<body>
<PragmaComponent client:load/>
<PragmaComponentTypeScript client:load/>
</body>
</html>

View 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>

View file

@ -0,0 +1,5 @@
/** @jsxImportSource react */
export default function() {
return <div className="pragma-comment">Hello world</div>;
}

View file

@ -0,0 +1,5 @@
/** @jsxImportSource react */
export default function({}: object) {
return <div className="pragma-comment">Hello world</div>;
}

View file

@ -0,0 +1,5 @@
import React from 'react';
export default function({}) {
return <div className="ts-component">Hello world</div>;
}

View file

@ -4,6 +4,7 @@ import Later from '../components/Goodbye.vue'; // use different specifier
import ArrowFunction from '../components/ArrowFunction.jsx';
import PropsSpread from '../components/PropsSpread.jsx';
import {Research2} from '../components/Research.jsx';
import TypeScriptComponent from '../components/TypeScriptComponent';
const someProps = {
text: 'Hello world!',
@ -20,5 +21,6 @@ const someProps = {
<ArrowFunction />
<PropsSpread {...someProps}/>
<Research2 client:idle />
<TypeScriptComponent client:load />
</body>
</html>

View 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>

View file

@ -25,6 +25,14 @@ PreactComponent('Can load function component', async ({ runtime }) => {
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 }) => {
const result = await runtime.load('/hooks');
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}`);
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 }) => {

View file

@ -43,6 +43,7 @@ React('Can load React', async () => {
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').text(), 'Hello world!');
assert.equal($('.ts-component').length, 1, 'Can use TS components');
});
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');
});
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 () => {
const result = await runtime.load('/');
assert.ok(!result.error, `build error: ${result.error}`);