Skip to content

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

Open

Description

@vincentjames501

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.

Activity

  1. Timer commented on Dec 11, 2018

    @Timer
    Contributor

    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.

  2. alexkuz commented on Dec 24, 2018

    @alexkuz

    @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.

  3. Timer commented on Dec 24, 2018

    @Timer
    Contributor

    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.

  4. alexkuz commented on Dec 24, 2018

    @alexkuz

    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.

  5. tlehtimaki commented on Feb 19, 2019

    @tlehtimaki
    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?

  6. Obiwarn commented on Feb 22, 2019

    @Obiwarn

    @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"
      },
    ...
    
  7. ChristianUlbrich commented on May 9, 2019

    @ChristianUlbrich

    @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".

  8. byxor commented on Sep 19, 2019

    @byxor

    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.

  9. byxor commented on Sep 20, 2019

    @byxor

    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",
        // ...
      },
  10. ChristianUlbrich commented on Nov 13, 2019

    @ChristianUlbrich

    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.

  11. jonrimmer commented on Jun 3, 2020

    @jonrimmer

    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.

  12. JoshMcCullough commented on Aug 20, 2020

    @JoshMcCullough

    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.

  13. illume commented on Mar 22, 2021

    @illume

    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.

  14. jurajpiar commented on Mar 29, 2021

    @jurajpiar

    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)

  15. cakeinpanic commented on Feb 28, 2022

    @cakeinpanic

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

  16. JessicaSachs commented on May 9, 2022

    @JessicaSachs

    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.

  17. samboylett commented on Aug 10, 2022

    @samboylett

    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'),
        };
      },
    };
  18. Crismon96 commented on Apr 24, 2023

    @Crismon96

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions