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

Add a way to specify an alternate tsconfig for production builds #6023

Open
vincentjames501 opened this issue Dec 11, 2018 · 18 comments
Open

Comments

@vincentjames501
Copy link
Contributor

Is this a bug report?

No. This is a feature request. Our team is now using CRA with TS and it is great! One thing we can't seem to find is any information on is having different TS compiler settings when doing a production build. Simply adding a tsconfig.prod.json appears to have no effect. I can't seem to find a documented way to add this and it would be super useful!

Did you try recovering your dependencies?

N/A

Which terms did you search for in User Guide?

TypeScript https://reactjs.org/docs/static-type-checking.html#typescript

Environment

Environment Info:

  System:
    OS: macOS 10.14.1
    CPU: x64 Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
  Binaries:
    Node: 10.14.0 - /usr/local/bin/node
    Yarn: 1.12.3 - /usr/local/bin/yarn
    npm: 6.4.1 - ~/Projects/cirrus-admin-webapp/node_modules/.bin/npm
  Browsers:
    Chrome: 70.0.3538.110
    Firefox: 63.0.3
    Safari: 12.0.1
  npmPackages:
    @types/react: 16.7.7 => 16.7.7
    @types/react-dom: 16.0.11 => 16.0.11
    react: 16.6.3 => 16.6.3
    react-dom: 16.6.3 => 16.6.3
    react-scripts: 2.1.1 => 2.1.1
  npmGlobalPackages:
    create-react-app: Not Found

Steps to Reproduce

  1. Add TS to your project as outlined in the docs.
  2. Attempt to add a tsconfig.prod.json with different settings than tsconfig.json:
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "noUnusedLocals": true
  }
}
  1. Run yarn build or whatever you have configured to do a production build with react-scripts
  2. Notice the settings aren't applied.

Expected Behavior

It would honor the tsconfig.prod.json

Actual Behavior

It honors the original tsconfig.json.

Reproducible Demo

N/A. I can add one later if people have any issues reproducing.

@Timer
Copy link
Contributor

Timer commented Dec 11, 2018

Sorry, this isn't possible and we have no plans to add support for this.
It would be better to accomplish this via linting, e.g. TSLint.

@alexkuz
Copy link

alexkuz commented Dec 24, 2018

@Timer I agree that unused variables is linter's job. But currently TSLint considers this rule deprecated, since it's quite hard for them to maintain it and tsc already has this feature (palantir/tslint#4100).

I don't think it's "impossible" to support this (create-react-app-typescript did that somehow), but I understand if it goes against zero-config policy. Still it would be nice to find some appropriate solution.

@Timer
Copy link
Contributor

Timer commented Dec 24, 2018

Ultimately, it comes down to being a foot-gun IMO. Users may accidentally configure their tsconfig.json differently between development and production (besides "linting" rules) and be really confused when their bundle is broken in production.

If this is necessary, I'd suggest modifying tsconfig.json on-the-fly before your CI tests run.

@alexkuz
Copy link

alexkuz commented Dec 24, 2018

Since I only need that unused variable checking, I ended up just running tsc -p tsconfig.prod.json before an actual build with "skipLibCheck": true for better performance.

@tlehtimaki
Copy link
Contributor

Since I only need that unused variable checking, I ended up just running tsc -p tsconfig.prod.json before an actual build with "skipLibCheck": true for better performance.

Would you @alexkuz mind elaborating a bit more how you did this?

@Obiwarn
Copy link

Obiwarn commented Feb 22, 2019

@alexkuz
Add a tsconfig.production.json:

{
    "extends": "./tsconfig.json",  
    "compilerOptions": {
      "noUnusedLocals": true,
      "skipLibCheck": true
    },
  "exclude": ["**/*.test.ts", "*.test.tsx"]
}

and change your build script in package.json:

...
  "scripts": {
    "start": "react-scripts start",
    "build": "tsc -p tsconfig.production.json && react-scripts build",
    "deploy": "npm run build && firebase deploy",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
...

@ChristianUlbrich
Copy link

@Timer Why would this not be possible? To me it looks like it would simply involve changing:

appTsConfig: resolveApp('tsconfig.json'),

in packages/react-scripts/config/paths.js to something "env-based" using the Advanced Configuration "way".

@byxor
Copy link

byxor commented Sep 19, 2019

We need to use "jsx": "react" in our production builds, but react-scripts start is overwriting the line to "jsx": "preserve". 😦

This behaviour is breaking our production builds and could be avoided by allowing me to specify a different tsconfig.json when doing quick local development.

@byxor
Copy link

byxor commented Sep 20, 2019

Update: I've worked around this by creating three files:

tsconfig.base.json
tsconfig.development.json        // inherits from base config
tsconfig.production.json         // inherits from base config

I added some extra steps to the build to copy the correct config to tsconfig.json before building. Now I can use multiple typescript configurations for different builds.

For example, here is what I added to package.json to copy the files:

  "scripts": {
    // ...
    "start": "cp -f ./typescript/tsconfig.development.json ./tsconfig.json && npm install && react-scripts start",
    "build": "cp -f ./typescript/tsconfig.production.json ./tsconfig.json && npm install && webpack --config webpack/webpack.config.js --mode development",
    // ...
  },

@ChristianUlbrich
Copy link

I can "work around" nearly everything, because JS got' eval() but this is not the point. :) @byxor We used nearly the same approach; however such a standard feature should not be worked around, but supported natively.

@jonrimmer
Copy link

Support for multiple tsconfigs is a fundamental requirement for any build tool that claims to support TypeScript. Not having it is the real footgun.

The reason is that, in order for intellisense in editors like VSCode to work, your root tsconfig.json must include every source file and dependency in your app. I.e. all your app's source files, all the .test.ts files, the .stories.tsx files, etc. And the types/libs must reference things like Storybook, node, Jest, etc. as well.

However, when building your app, you obviously don't want to include everything. In fact, it is very dangerous to do so. If one of your app's components accidentally imported something from Storybook or node, you wouldn't get an error and build/type-check time. Therefore, you need to create a separate tsconfig.app.json that extends from the root tsconfig.json but which narrows the list of included files and allowed dependencies. You create a similar tsconfig file for your tests, Storybook, Cypress, etc.

This is how other tools like Angular CLI work, and it is how it is supposed to work. It's the whole reason TypeScript supports multiple tsconfig files and extending from each other.

@JoshMcCullough
Copy link

FWIW adding tsc -p tsconfig.production.json before react-scripts build does work, but also adds time to the build process. Best we can do for now, IMO.

@illume
Copy link

illume commented Mar 22, 2021

Having "*.stories.tsx" excluded/skipped in the production build would be useful. Otherwise storybook and its required dependencies need to be installed with npm install --only=prod. The other way it reduces build time is because there's a lot less to compile.

FWIW adding tsc -p tsconfig.production.json before react-scripts build does work, but also adds time to the build process. Best we can do for now, IMO.

This work-around doesn't work for the use case of excluding files from the production build.

@jurajpiar
Copy link

Having "*.stories.tsx" excluded/skipped in the production build would be useful. Otherwise storybook and its required dependencies need to be installed with npm install --only=prod. The other way it reduces build time is because there's a lot less to compile.

FWIW adding tsc -p tsconfig.production.json before react-scripts build does work, but also adds time to the build process. Best we can do for now, IMO.

This work-around doesn't work for the use case of excluding files from the production build.

Agree.
This one does though btw. #6023 (comment)

@cakeinpanic
Copy link

Hi, I believe a feature to use different tsconfigs is crucial, why aren't you planning to add it?

@JessicaSachs
Copy link

JessicaSachs commented May 9, 2022

Support for multiple tsconfigs is a fundamental requirement for any build tool that claims to support TypeScript. Not having it is the real footgun.

The reason is that, in order for intellisense in editors like VSCode to work, your root tsconfig.json must include every source file and dependency in your app. I.e. all your app's source files, all the .test.ts files, the .stories.tsx files, etc. And the types/libs must reference things like Storybook, node, Jest, etc. as well.

However, when building your app, you obviously don't want to include everything. In fact, it is very dangerous to do so. If one of your app's components accidentally imported something from Storybook or node, you wouldn't get an error and build/type-check time. Therefore, you need to create a separate tsconfig.app.json that extends from the root tsconfig.json but which narrows the list of included files and allowed dependencies. You create a similar tsconfig file for your tests, Storybook, Cypress, etc.

Hello from Cypress! 👋🏻

Support for multiple tsconfigs would be a huge benefit for users.

Cypress 10 supports Component Testing and recommends adding *.cy.tsx files sibling to your Jest *.spec.tsx (also sibling to your source code). To avoid resolving global it, describe, and expect as Jest types from VSCode Intellisense... the only workaround we've found is using reference types at the top of each file. 😢

/// <reference types="cypress" />

Depending on the version of VSCode, you need to reload (Cmd + R) for the new reference types to take effect. This is a poor DX.

Lastly, files executed in the node context, like cypress.config.ts or plugins would benefit from a different set of types, where the DOM isn't actually available.

In projects that have: mixed toolchains, mixed environments (node vs browser), mixed module systems (esm, cjs), it's critical to support diversity in compilation options.

@samboylett
Copy link

You can achieve this with react-app-rewired:

// config-overrides.js

const path = require('path');

module.exports = {
  paths: function(paths) {
    return {
      ...paths,
      appTsConfig: path.join(__dirname, 'tsconfig.production.json'),
    };
  },
};

@Crismon96
Copy link

Guys! There is a PR for it. It would make me so happy to see such a crucial change merged CarlRibbegaardh but it seems to have gotten stale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests