strothj / react-app-rewire-typescript-babel-preset

Add TypeScript support to Create React App using @babel/preset-typescript
https://react-app-rewire-typescript-babel-preset.netlify.com
MIT License
52 stars 6 forks source link

2.0.0-next.3e165448 "Failed to compile." #15

Closed strothj closed 6 years ago

strothj commented 6 years ago

Upgrading from react-scripts 2.0.0-next.66cc7a90 to 2.0.0-next.3e165448 (released 2018-06-17) causes an error when running npm run start:

Failed to compile.

./src/theme/index.ts
3:0-33 './themes' does not contain an export named 'Theme'.

/src/theme/index.ts:

export { ThemeBaseline } from "./ThemeBaseline";
export * from "./themeProviders";
export { Theme } from "./themes";

/src/theme/themes.ts:

// ...
export type Theme = typeof lightTheme;
// ...
strothj commented 6 years ago

Seems to have been resolve by rebuilding the yarn.lock.

deftomat commented 6 years ago

We have the same problem. However, rebuilding the lock file didn't help. Any idea what could cause this issue?

strothj commented 6 years ago

These issues can be tricky sometimes. Are you using a monorepo or regular?

If you haven’t already, try deleting your node modules directory after deleting the lock file.

Often the issue relates to type definition packages depending on other type definition packages. Something weird happens with the directory structure of node modules that creates a situation where different type packages don’t line up with each other.

Are you using Yarn or NPM?

deftomat commented 6 years ago

Well, we are using Yarn and monorepo.

Deleting the node_modules and yarn.lock didn't help.

I even tried to use is as a regular repo (I removed the "workspaces" property from a parent package.json) and still the same issue: '@src/modules/auth/authService' does not contain an export named 'Session'.

I cannot provide the repo as it is private, however I can list a minimal dependencies, which are required by an app:

"dependencies": {
    "antd": "^3.6.5",
    "apollo-cache-inmemory": "^1.2.2",
    "apollo-cache-persist": "^0.1.1",
    "apollo-client": "^2.3.2",
    "apollo-link-context": "^1.0.8",
    "apollo-link-error": "^1.1.0",
    "apollo-link-http": "^1.5.4",
    "apollo-link-logger": "^1.2.2",
    "aws-amplify": "^0.4.6",
    "aws-appsync": "^1.1.2",
    "formik": "^0.11.11",
    "formik-effect": "^1.2.0",
    "graphql-tag": "^2.9.2",
    "ip": "^1.1.5",
    "moment-timezone": "^0.5.17",
    "query-string": "^6.1.0",
    "ramda": "^0.25.0",
    "react": "^16.4.0",
    "react-apollo": "^2.1.4",
    "react-dom": "^16.4.0",
    "react-router-dom": "^4.2.2",
    "rxjs": "^6.2.0",
    "styled-components": "^3.3.3",
    "yup": "^0.24.0"
  },
  "devDependencies": {
    "@babel/preset-typescript": "7.0.0-beta.52",
    "@types/react": "^16.3.14",
    "@types/react-dom": "^16.0.5",
    "@types/react-router-dom": "^4.2.6",
    "@types/yup": "^0.24.4",
    "react-app-rewire-typescript-babel-preset": "^2.3.0",
    "react-app-rewired": "^2.0.0",
    "react-scripts": "2.0.0-next.3e165448",
    "typescript": "^2.9.1"
  }
strothj commented 6 years ago

I’m not encountering the issue myself at the moment but I suspect it may have something to do with how Yarn may be selecting a version of a common package which is depended on my two or more other packages.

Specifically, I would start by checking your yarn.lock file and investigating which packages depend on utility packages from Facebook.

Unfortunately, I’m in the middle of a crunch time with work so I won’t have time available until Sunday to look deeper.

Yarn has some tools available if you can determine the cause: nohoist, resolutions

deftomat commented 6 years ago

@strothj Yeah, the same here. We are finishing the project this week, so I don't have much time to investigate it. 😞

strothj commented 6 years ago

I think the main difference between the latest beta and the second oldest version is the conversion to Webpack 4. Small build time improvement on the latest version due to the Webpack upgrade but nothing crucial.

strothj commented 6 years ago

Setting the following in config-overrides.js will bypass the problem for now:

config.module.strictExportPresence = false;

I think the problem relates to the conversion to Webpack 4 and the way exports are being detected as non-existent in some cases.

I need to pinpoint what exactly is causing this. Setting the above option will demote the error to a warning. The Webpack default is false, it is set to true by the CRA's Webpack config.

deftomat commented 6 years ago

@strothj Awesome, thanks for a workaround.

deftomat commented 6 years ago

@strothj I discovered that errors are cause only by a few exported interfaces. When I change them to abstract classes, all errors disappears.

So, it looks like the typescript-preset is omitting these exports as interfaces are not necessary in a final bundle and webpack 4 is not happy with it.

deftomat commented 6 years ago

UPDATE: It looks like the re-exported interfaces are causing these issues.

// auth.ts
export interface Session {
  id: string;
}

// index.ts
export { Session } from './auth.ts';

It throws an error even when all code is importing a Session from auth.ts. Removing the re-export from index.ts will fix this.

Another solution is to change the interface to abstract class and then I can keep the re-export.

So, now I'm not sure if this is a correct repo for this issue.

strothj commented 6 years ago

@deftomat This lines up with my experience.

themes.ts:

export type Theme = typeof lightTheme;

index.ts:

export { Theme } from "./themes";

Error:

WARNING in ./src/theme/index.ts 3:0-33
"export 'Theme' was not found in './themes'

Interestingly, I reuse Create React App's Babel Loader, and nothing else, in Storybook. It also emits the same error. I'm using the Storybook v4 alpha.

Storybook v4 brings in Webpack 4 like CRA. So both are Webpack 4 and Babel 7.

deftomat commented 6 years ago

Looks like this is not a bug. typescript-babel-preset is trying to mimic a TypeScript with --isolatedModules. See this announcement.

When you add this flag to your tsconfig.json, then even a TS compiler will complain that you cannot re-export the interface.

So, it is RECOMMENDED to set isolatedModules to true when you want to use Babel for compilation.

My latest workaround without abstract classes:

import { Session as BaseSession } from './auth.ts';

export type Session = BaseSession;
strothj commented 6 years ago

Fantastic! Thank you for the update!

I'll make sure to update the documentation.

strothj commented 6 years ago

A bit annoying how this works but making similar changes fixes my stuff.

GabeDuarteM commented 6 years ago

this happened to me, but it was just a silly mistake.

I just had not installed @babel/preset-typescript (and apparently, the docs don't say it's necessary), so a simple npm install -D @babel/preset-typescript solved the issue for me 😃

Is it really necessary? If so, shoulnd't we add it to the docs?

strothj commented 6 years ago

@GabrielDuarteM Sorry about that; that was an oversight when re-doing the docs. Splitting the README into separate pages caused that important bit of information to get lost.

It's actually mentioned here: https://react-app-rewire-typescript-babel-preset.netlify.com/#/docs/limitations

But it really needs to be here: https://react-app-rewire-typescript-babel-preset.netlify.com/#/docs/installation

I can't include it in the package because the version of the preset needs to be in sync with the version of the Babel parser inside of react-scripts.

I'll create an issue for it, feel free to make a pull request. I'll handle it in a couple of days if you don't have time. :-p

GabeDuarteM commented 6 years ago

Sure, I've just created the PR #22

strothj commented 6 years ago

Closing this. I've updated the documentation to mention the use of the isolatedModules option.