Aral Roca
Aral Roca

Reputation: 5919

React 16.14.0: Error was not caught ReferenceError: exports is not defined

I'm the author of next-translate library, and I'm working on an experimental version to which I get an error with React 16.14.0 and I don't understand why it happens. Upgrading React to version 17 then it works fine, but I don't want to force everyone who uses the new version of my library to migrate their React version.

I've created a reproducible error example: https://github.com/aralroca/next-translate-error-reproduction

In order to reproduce this issue:

Error was not caught ReferenceError: exports is not defined

And the prerelease code of my lib is here:

tsconfig.json

{
  "compilerOptions": {
    "strict": false,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "removeComments": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "declaration": true,
    "lib": ["esnext", "dom"],
    "allowJs": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./lib/esm"
  },
  "include": ["./src"]
}

tsconfig-cjs.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "CommonJS",
    "outDir": "./lib/cjs",
    "declaration": false
  }
}

And this is the package code:

If anyone knows where this error came from and can help me I would be very grateful! I've been trying to solve it for several days but I'm a little lost because I don't know why it's happening... Thanks!

Note: Looks that it only happens in development, doing yarn build && yarn start works fine.

Upvotes: 9

Views: 821

Answers (2)

hackape
hackape

Reputation: 19987

Glad you've found the bug, here's the explanation of your case.

Let's compare the compiled result of both version:

Look around ln:54 in both files 1.0.0-experimental.14 1.0.0-experimental.15.

var react_1 = __importDefault(require("react"));

// The key different is the exclusion of this line:
var app_1 = __importDefault(require("next/app"));

var I18nProvider_1 = __importDefault(require("./I18nProvider"));
var loadNamespaces_1 = __importDefault(require("./loadNamespaces"));

Because you don't use App.getInitialProps() no more, the import App from 'next/app' is also dropped by TypeScript. The real problem lies in next/app module.

Following the breadcrumbs, we see next/app simple re-exports next/dist/pages/_app:

module.exports = require('./dist/pages/_app')

As of the content of ./dist/pages/_app, go check this link. It refs exports as a global variable everywhere, and that's causing the problem: Error was not caught ReferenceError: exports is not defined

The problem is clear, that code of next/dist/pages/_app.js is included in the bundled JS code shipped to the webpage without being transpiled properly by webpack.

But after this point I cannot provide further help since I'm not familiar with the next.js stack. Guess you need to tune the webpack config to do something about that exports global variable.

Upvotes: 1

Aral Roca
Aral Roca

Reputation: 5919

I've already fixed it, but if I'm honest, I haven't understood why... Let's see if someone can explain it to me!

I was debugging and saw that it was something in my library code that caused TypeScript to compile badly. So, I was uncommenting line by line, until I saw what was wrong with the line:

import App from 'next/app'

// Inside getInitialProps wrapper...
App.getInitialProps() // THIS LINE

It seems that when commenting App.getInitialProps() then TypeScript it compiles well. Fortunately, I have been able to dispense with this line of code in my library and now with prerelease 1.0.0-experimental.15 it seems to work well with React 16.

I don't really understand why this could be happening, could it be because I have Next.js as peerDependency? I hope someone can clarify for me why this was happening 🙏

Upvotes: 4

Related Questions