Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EvalError: $RefreshReg$ is not a function - broken usage with react refresh #1308

Closed
ntucker opened this issue Jul 27, 2023 · 6 comments · Fixed by #1307
Closed

EvalError: $RefreshReg$ is not a function - broken usage with react refresh #1308

ntucker opened this issue Jul 27, 2023 · 6 comments · Fixed by #1307
Labels
bug report 🦗 Issue is probably a bug, but it needs to be checked bundler: webpack 📦 Issue is related to webpack bundler needs: complete repro 🖥️ Issue need to have complete repro provided

Comments

@ntucker
Copy link

ntucker commented Jul 27, 2023

Environment

  • "react-refresh": "0.14.0",
  • Linaria version:
    "@linaria/babel-preset": "4.5.4",
    "@linaria/core": "4.5.4",
    "@linaria/react": "4.5.4",
    "@linaria/shaker": "4.5.3",
  • Bundler (+ version): "webpack": "5.88.2",
  • Node.js version: 20.5
  • OS: Ubuntu

Description

Module build failed (from ./node_modules/@linaria/webpack5-loader/lib/index.js):
EvalError: $RefreshReg$ is not a function in
| /home/projects/rlmiozmrm.github/src/pages/Home/index.tsx

    at Module.evaluate (file:///home/projects/rlmiozmrm.github/node_modules/@linaria/babel-preset/lib/module.js:350:13)
    at evaluate (file:///home/projects/rlmiozmrm.github/node_modules/@linaria/babel-preset/lib/evaluators/index.js:16:5)
    at evalStage (file:///home/projects/rlmiozmrm.github/node_modules/@linaria/babel-preset/lib/transform-stages/2-eval.js:26:45)
    at syncStages (file:///home/projects/rlmiozmrm.github/node_modules/@linaria/babel-preset/lib/transform.js:50:45)
    at transform (file:///home/projects/rlmiozmrm.github/node_modules/@linaria/babel-preset/lib/transform.js:140:10)

Reproducible Demo

https://stackblitz.com/github/data-client/rest-hooks/tree/master/examples/todo-app?file=src%2Fpages%2FHome%2FTodoList.tsx

@ntucker ntucker added bug report 🦗 Issue is probably a bug, but it needs to be checked needs: complete repro 🖥️ Issue need to have complete repro provided needs: triage 🏷 Issue needs to be checked and prioritized labels Jul 27, 2023
@github-actions github-actions bot added bundler: webpack 📦 Issue is related to webpack bundler and removed needs: triage 🏷 Issue needs to be checked and prioritized labels Jul 27, 2023
@ntucker
Copy link
Author

ntucker commented Jul 27, 2023

It seems like linaria is too eagerly trying to apply babel presets in contexts it does not correctly know how to consume. $RefreshReg$ is injected by react-refresh/babel and has meaning when webpack's refresh plugin is used.

does linaria provide caller information? (like https://github.com/ntucker/anansi/blob/master/packages/babel-preset-anansi/index.js#L21)

@Anber
Copy link
Collaborator

Anber commented Jul 28, 2023

It looks related #1299

@ntucker
Copy link
Author

ntucker commented Sep 23, 2023

Still broken in v5:

ERROR in ./src/App.tsx
Module build failed (from ../../node_modules/@linaria/webpack5-loader/lib/index.js):
EvalError: $RefreshReg$ is not defined in/home/ntucker/src/anansi/examples/linaria/src/App.tsx

    at Module.evaluate (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/module.js:224:13)
    at evaluate (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/evaluators/index.js:15:5)
    at BaseAction.evalFile (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/generators/evalFile.js:35:43)
    at evalFile.next (<anonymous>)
    at /home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/actions/BaseAction.js:66:78
    at EventEmitter.action (/home/ntucker/src/anansi/node_modules/@linaria/utils/lib/EventEmitter.js:25:22)
    at BaseAction.emitAction (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/actions/BaseAction.js:131:39)
    at nextFn (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/actions/BaseAction.js:66:32)
    at processNext (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/actions/BaseAction.js:111:28)
    at Object.next (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/actions/BaseAction.js:120:9)
    at asyncActionRunner (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/actions/actionRunner.js:39:102)
    at async asyncActionRunner (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform/actions/actionRunner.js:46:22)
    at async transform (/home/ntucker/src/anansi/node_modules/@linaria/babel-preset/lib/transform.js:95:20)

Test

Anber added a commit that referenced this issue Sep 23, 2023
…orts (fixes #1308) (#1343)

* feat(babel): overrideContext option

* fix(shaker): process functions and classes definitions in default exports
@Anber
Copy link
Collaborator

Anber commented Sep 23, 2023

Hi @ntucker!

I've added $RefreshReg$ to the list of global identifiers that should be deleted, but with your project, the problem is that $RefreshReg$ is inserted when the code remover finishes.

There are two solutions:

  1. You can use caller in your babel preset and exclude plugins that generate unprocessable code.
  2. You can use new overrideContext options to define fake $RefreshReg$:
overrideContext: (context) => ({ ...context, $RefreshReg$: () => {} })

One more related problem with undefined variables was fixed in 5.0.1

@ntucker
Copy link
Author

ntucker commented Sep 23, 2023

react-refresh is pretty common in react projects. Is there projects that use it another way?

Another way to fix this would be if linaria injected caller information - then my babel config would know not to use react-refresh based on the context in which it is called.

For instance, I have ESM detection

  const supportsModules = api.caller(
    caller => caller && caller.supportsStaticESM,
  );

I tried to inspect what members caller had when this originally came up, but it didn't have any distinguishable characteristics.

Currently logic is based on a bunch of concepts

  const shouldHotReload =
    !babelNode &&
    !options.nodeTarget &&
    callerCouldTargetWeb(callerTarget) &&
    process.env.NO_HOT_RELOAD !== 'true' &&
    process.env.NO_HOT_RELOAD !== true &&
    api.caller(caller => !caller || !caller.noHotReload) &&
    !['commonjs', 'cjs'].includes(options.modules);

https://github.com/ntucker/anansi/blob/master/packages/babel-preset-anansi/index.js#L68

In fact, I wouldn't even need to make changes if you just added 'noHotReload' to the caller. I believe I stole this from some other configs, so doing this would give you free compatibility with some other common configurations as well.

@ntucker
Copy link
Author

ntucker commented Sep 23, 2023

Oh I see you changed the caller name. I will use that for now; tho I still think feature parameters are better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report 🦗 Issue is probably a bug, but it needs to be checked bundler: webpack 📦 Issue is related to webpack bundler needs: complete repro 🖥️ Issue need to have complete repro provided
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants