Description:
Consider the following file, which with various extensions doesn't parse.
/** @jsx mdx */
import {mdx} from '@mdx-js/preact';
export default function MDXContent() {
return <h1>hi</h1>>;
}
When using .js:
> ./scripts/dev-rome parse test-file.js
test-file.js:2 parse/js โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ import and export can only appear in a module
1 โ /** @jsx mdx */
> 2 โ import {mdx} from '@mdx-js/preact';
โ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 โ
4 โ export default function MDXContent() {
โน Change the extension to .mjs to turn this file into a module
โน Add "type": "module" to your package.json
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
When using .mjs
> ./scripts/dev-rome parse test-file.mjs
test-file.mjs:5:9 parse/js โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ JSX syntax isn't enabled
4 โ export default function MDXContent() {
> 5 โ return <h1>hi</h1>>;
โ ^
6 โ }
โน Are you using TypeScript? Change the file extension to .tsx
โน Are you using Flow? Add a @flow comment annotation to the top of the file
โน Not using either? Change the file extension to .jsx
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Found 1 problem
when using .jsx
./scripts/dev-rome parse test-file.jsx
test-file.jsx:2 parse/js โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ import and export can only appear in a module
1 โ /** @jsx mdx */
> 2 โ import {mdx} from '@mdx-js/preact';
โ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 โ
4 โ export default function MDXContent() {
โน Change the extension to .mjs to turn this file into a module
โน Add "type": "module" to your package.json
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Found 1 problem
test-file with the appropriate extension from above (.js, .mjs, or .jsx)../scripts/dev-rome parse test-file.jsxI expected it to be able to parse ES Modules without .mjs since this is supported by browsers. I didn't expect the .jsx extension to be relevant, although I can understand that. I expected that a file with ES Modules and JSX syntax would be parsed regardless of file extension.
I agree that it would be better not to rely on the extension. The issue with that is that it is very difficult to cover all edge cases to determine what type of source it is without other kind of metadata to let the parser know how to parse it.
One way to do it is to include type: "module" in your package.json. If you have a code base with multiple types of files, you could split ES Modules and CommonJS modules into their own folders and add a relative package.json with the type set to the expected module system.
I can't think of any other way to do this. This is just the way Node does it, since in the browser you can just do <script type="module">, so the only equivalence in Node is to use the package.json or the file extension.
Edit: Crazy idea: A new .mjsx file extension for ES Modules with JSX.
you could split ES Modules and CommonJS modules into their own folders and add a relative package.json with the type set to the expected module system.
You can also use .cjs for the CommonJS files. Using multiple package.json files should be a very last resort since it makes it really hard to follow what's going on in the project. Both humans and tools have to constantly look through the directory tree just in case there's a package.json file hiding somewhere.
I think I would prefer if JSX syntax would be treated as a layered feature. Using a file extension even though it's not really a different file type seems awkward and inconsistent:
mjs vs js: Completely different execution semantics and incompatible grammar. Not ever valid mjs is a valid js and vice versa.jsx vs js: Enables an additional syntax feature that down-levels cleanly to other expressions. Every valid .js is also a valid .jsx (clean subset).So to me it feels like JSX could just be enabled syntax in mjs and treated like other "future syntax". Unless the expectation is that any .js and .mjs file should work as-is and it skips compilation for them..? In which case: How about "just" saying that .jsx is a module by default? It does have the downside that it could complicate migration to rome of course. :)
I implemented the current Node ES modules interop which requires either a .mjs extension to enable ES modules for that file, or a "type": "module" added to package.json. Regardless of if you're a fan of this approach, the ecosystem is likely going to need to converge on it.
This bug is actually caused by the way syntax is enabled. The parsing here is happening inside of the Rome server which has special logic to initially determine the syntax of a file. You can find what syntax is enabled for what files here in fileHandlers.ts. jsx and flow are enabled for all .js files but that was due to internal FB weirdness. I do want to remove that.
We do enable flow all the time in a file if there's a comment that contains @flow. This is done in js-parser/tokenizer/index.ts. This is only since it's the unfortunate convention for Flow users to use the .js syntax.
Does someone want to PR some additional logic to add jsx syntax for a @jsx comment?
yeah I'll take a crack at adding it
This is still an issue in 10.0.4-beta. Even with a pragma of /** @jsx jsx */, no file extension seems to satisfy Rome.
It may be tricky under the hood, but I would like to be able to use .js, or at least .jsx files with imports/exports, without a pragma, without type: module in package.json (not workable when using NextJS), and without multiple package.json files.
At a stopgap, please add the ability to suppress this error?
Most helpful comment
This is still an issue in 10.0.4-beta. Even with a pragma of
/** @jsx jsx */, no file extension seems to satisfy Rome.It may be tricky under the hood, but I would like to be able to use
.js, or at least.jsxfiles with imports/exports, without a pragma, withouttype: modulein package.json (not workable when using NextJS), and without multiple package.json files.At a stopgap, please add the ability to suppress this error?