TypeStrong / ts-loader

TypeScript loader for webpack
https://johnnyreilly.com/ts-loader-goes-webpack-5
MIT License
3.46k stars 429 forks source link

Project References won't work if extends config file #1035

Open t83714 opened 4 years ago

t83714 commented 4 years ago

Background

ts-load version: 6.2.1 webpack version: 4.28.3 webpack-cli version: 3.3.10 tyepscript version: 3.7.2

Given the following config files:

  1. tsconfig.json:
    {
    "extends": "../tsconfig-global.json",
    "compilerOptions": {
        "outDir": "./dist",
        "strictNullChecks": false,
        "rootDir": "./src",
        "tsBuildInfoFile": "./tsconfig.tsbuildinfo"
    },
    "references": [{ "path": "../typescript-common" }],
    "include": ["./src"]
    }
  2. tsconfig-web.json (extends the TS config file above):
    {
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "lib": [
            "dom",
            "es5",
            "scripthost",
            "es2015.core",
            "es2015.promise",
            "es2017"
        ]
    }
    }
  3. Webpack config (use tsconfig-web.json to build TS code):
    
    const path = require("path");
    const webpack = require("webpack");
    const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");

const configFile = path.resolve(__dirname, "../tsconfig-web.json");

module.exports = { entry: "./src/createTransformer.ts", mode: "production", output: { filename: "createTransformerForBrowser.js", path: path.join(__dirname, "..", "dist"), library: "createTransformer" }, devtool: "source-map", module: { rules: [ { test: /.tsx?$/, exclude: /node_modules/, loader: "ts-loader", options: { configFile, projectReferences: true } } ] }, resolve: { plugins: [ new TsconfigPathsPlugin({ configFile }) ], extensions: [".tsx", ".ts", ".js"] }, node: { fs: "empty" } };

### Actual Behaviour

Project reference doesn't work. And you will find the following errors:

ERROR in xx/xx.ts [tsl] ERROR in /xx/typescript-common/src/xxxxxx.ts(9,30) TS6059: File '/xx/typescript-common/src/xx/xx.ts' is not under 'rootDir' '/xx'. 'rootDir' is expected to contain all source files.



### Expected Behaviour

Should build without error.

However, if you either:
- add `"references": [{ "path": "../typescript-common" }],` to `tsconfig-web.json`
- Or modify `webpack.config.js` to use `tsconfig.json` to build (instead of `tsconfig-web.json`)

the build will complete with no error. 

### Steps to Reproduce the Problem

See: https://github.com/t83714/sample-repo-ts-loader

### Location of a Minimal Repository that Demonstrates the Issue.

https://github.com/t83714/sample-repo-ts-loader
jleider commented 4 years ago

@t83714 I believe this is actually an issue with tsconfigs not ts-loader as I have struggled with this a bunch recently. It would seem that there is no way to make files, includes, references, etc. relative to the current config. They are always relative to the config in which they were originally defined no matter what combination of rootDir or baseUrl compiler settings as they seem to have no effect on anything that is set outside of the compilerOptions object.

t83714 commented 4 years ago

@jleider For my sample repo, once you change "../tsconfig-web.json" in the webpack config to "../tsconfig.json", everything will just work fine.

And tsconfig.json is located in the same directory as tsconfig-web.json --- the only difference is tsconfig.json comes with references property (rather than set via extends).

From this, we probably can say ts-loader has NO relative path resolving issues. It just didn't process extends very well.

FrozenKiwi commented 4 years ago

https://github.com/TypeStrong/ts-loader/issues/911

Dup of this (closed, but not resolved) issue. Linking so we have more reference info.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

Closing as stale. Please reopen if you'd like to work on this further.

FlorianWendelborn commented 4 years ago

@t83714 can you please re-open this issue?

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

Closing as stale. Please reopen if you'd like to work on this further.

mh-alahdadian commented 4 years ago

any update on this? what's the badpractice to fix this problem? I need to use project reference

johnnyreilly commented 4 years ago

No update - if someone would like to work on this that would be amazing 🥰

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

Closing as stale. Please reopen if you'd like to work on this further.

elsasslegend commented 4 years ago

Please reopen !

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

lukescott commented 3 years ago

I'm experiencing an issue where it seems that configFile is not working at all. Related?

Also I have seen a lot of stale bot lately. Given the nature of the pandemic and the lack of resources, can it be switched off?

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

FlorianWendelborn commented 2 years ago

@stale don’t.

devenliu commented 2 months ago

@t83714 I believe this is actually an issue with tsconfigs not ts-loader as I have struggled with this a bunch recently. It would seem that there is no way to make files, includes, references, etc. relative to the current config. They are always relative to the config in which they were originally defined no matter what combination of rootDir or baseUrl compiler settings as they seem to have no effect on anything that is set outside of the compilerOptions object.

Hey jleider, I asked about ChatGPT and I got the following answer, not sure if it is possible.

const ts = require('typescript');
const path = require('path');

function getFullTsConfig(filePath) {
    const configFile = ts.readConfigFile(filePath, ts.sys.readFile);
    if (configFile.error) {
        throw new Error(ts.flattenDiagnosticMessageText(configFile.error.messageText, '\n'));
    }

    const parsedConfig = ts.parseJsonConfigFileContent(
        configFile.config,
        ts.sys,
        path.dirname(filePath)
    );

    if (parsedConfig.errors.length > 0) {
        throw new Error(parsedConfig.errors.map(e => ts.flattenDiagnosticMessageText(e.messageText, '\n')).join('\n'));
    }

    return parsedConfig;
}

const tsConfigPath = path.resolve(__dirname, 'tsconfig.json');
const fullConfig = getFullTsConfig(tsConfigPath);

console.log(JSON.stringify(fullConfig, null, 2));

My tsconfig.lib.json:

{
    "compilerOptions": {
        /* Projects */
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        /* Modules */
        "target": "es2015",
        "module": "esnext",
        "rootDir": "./",
        "moduleResolution": "node",
        "baseUrl": "./",
        "resolveJsonModule": true,
        /* Emit */
        "allowJs": true,
        "declaration": true,
        "declarationMap": true,
        "emitDeclarationOnly": false,
        "sourceMap": true,
        "outDir": "dist",
        "noEmit": false,
        "downlevelIteration": true,
        "declarationDir": "dist",
        /* Interop Constraints */
        "isolatedModules": true,
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        /* Type Checking */
        "strict": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "strictBindCallApply": true,
        "strictPropertyInitialization": true,
        "noImplicitThis": true,
        "useUnknownInCatchVariables": true,
        "noUnusedLocals": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true,
        "skipLibCheck": true
    }
}

My tsconfig.json:

{
    "extends": "./tsconfig.lib.json",
    "compilerOptions": {
        "jsx": "react",
        "target": "es5",
        "module": "esnext",
        "rootDir": "./src",
        "baseUrl": "./",
        "paths": {}
    },
    "include": ["src", "src/**/*.d.ts"],
    "exclude": ["node_modules", "dist"],
    "ts-node": {
        "transpileOnly": true,
        "compilerOptions": {
            "module": "commonjs",
            "target": "es5",
            "allowSyntheticDefaultImports": true,
            "esModuleInterop": true
        }
    }
}

Output:

{
  "options": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": 1,
    "module": 99,
    "rootDir": "<my-package-root>/src",
    "moduleResolution": 2,
    "baseUrl": "<my-package-root>",
    "resolveJsonModule": true,
    "allowJs": true,
    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": false,
    "sourceMap": true,
    "outDir": "<my-package-root>/dist",
    "noEmit": false,
    "downlevelIteration": true,
    "declarationDir": "<my-package-root>/dist",
    "isolatedModules": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "useUnknownInCatchVariables": true,
    "noUnusedLocals": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "skipLibCheck": true,
    "jsx": 2,
    "paths": {},
    "pathsBasePath": "<my-package-root>"
  },
  "fileNames": [
    "<my-package-root>/src/index.ts",
    "<my-package-root>/src/logger.ts"
  ],
  "typeAcquisition": {
    "enable": false,
    "include": [],
    "exclude": []
  },
  "raw": {
    "extends": "./tsconfig.lib.json",
    "compilerOptions": {
      "jsx": "react",
      "target": "es5",
      "module": "esnext",
      "rootDir": "./src",
      "baseUrl": "./",
      "paths": {}
    },
    "include": [
      "src",
      "src/**/*.d.ts"
    ],
    "exclude": [
      "node_modules",
      "dist"
    ],
    "ts-node": {
      "transpileOnly": true,
      "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "declaration": false,
        "declarationMap": false,
        "sourceMap": false
      }
    },
    "compileOnSave": false
  },
  "errors": [],
  "wildcardDirectories": {
    "<my-package-root>/src": 1
  },
  "compileOnSave": false
}

I Used "typescript": "^5.5.4"