I’m attempting to add support for JSX or TSX files to an Ember 3.28 app. Based on ember-react-components, I tried configuring my ember-cli-build.js as follows:
babel: {
spec: true,
plugins: [
require.resolve("@babel/plugin-syntax-jsx"),
require.resolve("@babel/plugin-transform-react-jsx"),
],
},
"ember-cli-babel": {
enableTypeScriptTransform: true,
extensions: ["js", "ts", "jsx"],
},
However, once I add a .jsx file, I get a build error from TypeScript:
test.jsx: Type parameter list cannot be empty. (2:9)
1 | export function TestJsx() {
> 2 | return <>Hello world!</>
| ^
3 | }
4 |SyntaxError: /Users/matthew/repos/cc/v4/frontend/cc-frontend/utils/test.jsx: Type parameter list cannot be empty. (2:9)
1 | export function TestJsx() {
> 2 | return <>Hello world!</>
| ^
3 | }
4 |
at constructor (/Users/matthew/repos/cc/v4/frontend/node_modules/@babel/parser/lib/index.js:359:19)
at TypeScriptParserMixin.raise ...
I believe that ember-cli-typescript is parsing the JSX before @babel/plugin-transform-react-jsx
can, causing it to complain at the (valid) JSX that is invalid TypeScript.
I get the same error if I use a .tsx file and configure TypeScript to process it ("jsx": "react-jsx"
in tsconfig.json and “tsx” in ember-cli-babel.extensions
). I tried adding .jsx files to my tsconfig.json’s exclude
list but it does not help.
Any ideas for how to get this working? I guess I could opt out of ember-cli-babel’s auto-generated config, but I’ve had trouble getting that to work with TypeScript.
If I do opt out of ember-cli-babel’s auto-generated config, I run into this build error (before adding anything jsx related):
Build Error (StripBadReexports)
[BABEL] unknown file: Preset /* your preset */ requires a filename to be set when babel is called directly,
babel.transformSync(code, { filename: 'file.ts', presets: [/* your preset */] });
See https://babeljs.io/docs/en/options#filename for more information.
The stack trace points to this line in ember-composable-helpers (v4.4.1). I can understand what the error is saying, but I’m confused why it only fails after I opt out.
Here is my babel.config.js (based on GitHub - emberjs/ember-cli-babel: Ember CLI plugin for Babel):
//babel.config.js
const { buildEmberPlugins } = require("ember-cli-babel")
module.exports = function (api) {
api.cache(true)
return {
presets: [
[
require.resolve("@babel/preset-env"),
{
targets: require("./config/targets"),
spec: true,
},
],
[require.resolve("@babel/preset-typescript"), { allowDeclareFields: true }],
],
plugins: [
// this is where all the ember required plugins would reside
...buildEmberPlugins(__dirname, {
/*customOptions if you want to pass in */
}),
],
}
}
Okay, I got this working with a fairly standard ember-cli-babel/TypeScript setup. The key change is to explicitly list @babel/plugin-transform-typescript
in babel.plugins
so that you can add the isTsx: true
option, overriding the options set by enableTypeScriptTransform: true
.
Otherwise, you just need to install and specify plugins equivalent to babel-preset-react.
Here is the relevant part of my ember-cli-build.js
:
babel: {
plugins: [
[require.resolve("@babel/plugin-syntax-jsx")],
[require.resolve("@babel/plugin-transform-react-jsx"), { runtime: "automatic" }],
[require.resolve("@babel/plugin-transform-react-display-name")],
[
require.resolve("@babel/plugin-transform-typescript"),
{ allowDeclareFields: true, isTSX: true },
],
],
},
"ember-cli-babel": {
enableTypeScriptTransform: true,
extensions: ["js", "ts", "jsx", "tsx"],
},