diff options
author | 2021-07-28 11:31:50 -0700 | |
---|---|---|
committer | 2021-07-28 14:31:50 -0400 | |
commit | 829d5baafe45273c150c32c9287fadaf9676d404 (patch) | |
tree | 03adc1f931037d4cd621758270df097e184d2eed | |
parent | 189098b6e569758d67d221162c76aa2c032e1a38 (diff) | |
download | astro-829d5baafe45273c150c32c9287fadaf9676d404.tar.gz astro-829d5baafe45273c150c32c9287fadaf9676d404.tar.zst astro-829d5baafe45273c150c32c9287fadaf9676d404.zip |
fix tsx+jsx error (#916)
* fix tsx+jsx error
* throw error if no build can be returned
14 files changed, 91 insertions, 19 deletions
diff --git a/.changeset/heavy-ears-hope.md b/.changeset/heavy-ears-hope.md new file mode 100644 index 000000000..a63bdaf30 --- /dev/null +++ b/.changeset/heavy-ears-hope.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix TSX issue with JSX multi-rendering diff --git a/packages/astro/snowpack-plugin-jsx.cjs b/packages/astro/snowpack-plugin-jsx.cjs index 419c55195..9c3e51079 100644 --- a/packages/astro/snowpack-plugin-jsx.cjs +++ b/packages/astro/snowpack-plugin-jsx.cjs @@ -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', diff --git a/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx b/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx index 3340e3f8e..498738113 100644 --- a/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx +++ b/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx @@ -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>; } diff --git a/packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx b/packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx new file mode 100644 index 000000000..7bfe65ada --- /dev/null +++ b/packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx @@ -0,0 +1,5 @@ +/** @jsxImportSource preact */ + +export default function({}: object) { + return <div class="pragma-comment">Hello world</div>; +} diff --git a/packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx b/packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx new file mode 100644 index 000000000..c341e13eb --- /dev/null +++ b/packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx @@ -0,0 +1,5 @@ +import {h} from 'preact'; + +export default function({}: object) { + return <div class="ts-component">Hello world</div>; +} diff --git a/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro b/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro index 91db69830..720a0e0a5 100644 --- a/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro +++ b/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro @@ -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> diff --git a/packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro b/packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro new file mode 100644 index 000000000..2e2597f10 --- /dev/null +++ b/packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro @@ -0,0 +1,12 @@ +--- +import TypeScriptComponent from '../components/TypeScriptComponent.tsx'; +--- + +<html> +<head> + <title>Preact TS component</title> +</head> +<body> + <TypeScriptComponent client:load /> +</body> +</html>
\ No newline at end of file diff --git a/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx b/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx new file mode 100644 index 000000000..d8ea77810 --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx @@ -0,0 +1,5 @@ +/** @jsxImportSource react */ + +export default function() { + return <div className="pragma-comment">Hello world</div>; +} diff --git a/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx b/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx new file mode 100644 index 000000000..9f2256fbf --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx @@ -0,0 +1,5 @@ +/** @jsxImportSource react */ + +export default function({}: object) { + return <div className="pragma-comment">Hello world</div>; +} diff --git a/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx b/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx new file mode 100644 index 000000000..bde96da84 --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function({}) { + return <div className="ts-component">Hello world</div>; +} diff --git a/packages/astro/test/fixtures/react-component/src/pages/index.astro b/packages/astro/test/fixtures/react-component/src/pages/index.astro index a64e076ce..3c0240296 100644 --- a/packages/astro/test/fixtures/react-component/src/pages/index.astro +++ b/packages/astro/test/fixtures/react-component/src/pages/index.astro @@ -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> diff --git a/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro b/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro new file mode 100644 index 000000000..b3ddba639 --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro @@ -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> diff --git a/packages/astro/test/preact-component.test.js b/packages/astro/test/preact-component.test.js index 67d071718..9ef02cad0 100644 --- a/packages/astro/test/preact-component.test.js +++ b/packages/astro/test/preact-component.test.js @@ -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 }) => { diff --git a/packages/astro/test/react-component.test.js b/packages/astro/test/react-component.test.js index 6f10b2914..6bfde0d25 100644 --- a/packages/astro/test/react-component.test.js +++ b/packages/astro/test/react-component.test.js @@ -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}`); |