linaria icon indicating copy to clipboard operation
linaria copied to clipboard

Weird problem with or without `babel.config.json` about `@linaria/babel-preset`

Open malash opened this issue 2 years ago • 2 comments

Environment

  • Linaria version: 7.23.3
  • Bundler (+ version): Babel 7.23.3
  • Node.js version: 18.16.1
  • OS: macOS Sonama 14.1.1

Description

I met a weird problem when attempting to upgrade from Linaria v2 to v5. It seems that the use of @linaria/babel-preset causes @babel/preset-typescript invalid when utilizing Babel CLI with the --presets parameter instead of using a babel.config.json file.

yarn run v1.22.19
$ babel --presets=@babel/typescript,@linaria src/index.ts
SyntaxError: /Users/malash/Projects/test-goji/src/index.ts: /Users/malash/Projects/test-goji/src/index.ts: Missing initializer in const declaration. (1:7)

> 1 | const a: number = 1;
    |        ^
  2 |
    at constructor (/Users/malash/Projects/test-goji/node_modules/@babel/parser/lib/index.js:356:19)
    at Parser.raise (/Users/malash/Projects/test-goji/node_modules/@babel/parser/lib/index.js:3223:19)
    at Parser.parseVar (/Users/malash/Projects/test-goji/node_modules/@babel/parser/lib/index.js:13267:16)
    at Parser.parseVarStatement (/Users/malash/Projects/test-goji/node_modules/@babel/parser/lib/index.js:13100:10)
    at Parser.parseStatementContent (/Users/malash/Projects/test-goji/node_modules/@babel/parser/lib/index.js:12683:23)
    at Parser.parseStatementLike (/Users/malash/Projects/test-goji/node_modules/@babel/parser/lib/index.js:12588:17)

For more details you can checkout this repo: https://github.com/malash/linaria-issue-1382

You can reproduce the issue on the master branch, and as a contrast the good-case contains a babel.config.json and it works well.

I believe both usages should function in the same way.

Also, I'm confident this is a bug of Linaria v5 because it doesn't reproduce on Linaria v2, see the good-case-linaria-2 branch.

Reproducible Demo

https://github.com/malash/linaria-issue-1382

malash avatar Nov 16 '23 11:11 malash

I found a similar issue https://github.com/callstack/linaria/issues/1218

malash avatar Nov 16 '23 12:11 malash

I spent few hours to deep dive the root cause of this issue. I found a way to reproduce this issue even with a babel.config.json file. I created a new branch bad-case-with-babel-config to approve it. On this branch I added a second parameter to the @linaria preset to disable the useBabelConfigs feature.

{
  "presets": [
    "@babel/typescript",
    [
      "@linaria",
      {
        "features": { "useBabelConfigs": false }
      }
    ]
  ]
}

By disabling this feature, the @babel/preset-typescript could not be able to run during the parse phase. This may cause the TypeScript parsing syntax error.

Therefore, I can fix this issue by adding the @babel/preset-typescript again to the babelOptions parameter of the @linaria preset. It may sound tricky, but does work.

{
  "presets": [
    "@babel/typescript",
    [
      "@linaria",
      {
        "features": { "useBabelConfigs": false },
        "babelOptions": {
          "presets": ["@babel/typescript"]
        }
      }
    ]
  ]
}

I believe the root cause is that @linaria/babel-preset uses a pre hook of Babel to parse the source code:

https://github.com/callstack/linaria/blob/1467f4a7017fe2420d65ec0572bc2fdcc24d7e68/packages/babel/src/plugins/babel-transform.ts#L23

I have no idea whether it's a recommended way to implement the Babel plugin. But in Linaria v2, it uses a visitor hook and everything works fine.

@Anber Could you please take a look at this issue? I saw you say useBabelConfigs will be changed to false in the next major release in https://github.com/callstack/linaria/pull/1355 . If it happened, I think it would break most TypeScript projects.

malash avatar Nov 17 '23 08:11 malash