s-panferov / awesome-typescript-loader

Awesome TypeScript loader for webpack
Other
2.35k stars 181 forks source link

Can we have a better example for TsConfigPathsPlugin #402

Open simonbear89 opened 7 years ago

simonbear89 commented 7 years ago

Hello, I can't seem to get this to compile correctly in webpack even though my editor (VSCode) resolves the file correctly.

// ./src/server/api/users/create.ts
import {User} from 'models/User';
...

My config files

// ./tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "models/*": ["src/server/models/*"]
    },

    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "outDir": "dist",
    "sourceRoot": "src",
    "target": "es5"
  }
}
// ./webpack.config.js
const TsConfigPathsPlugin = require('awesome-typescript-loader').TsConfigPathsPlugin;
...
module.exports = {
  resolve: {
    extensions: ['.ts', '.js', '.json'],
    modules: [
      `${__dirname}/node_modules`
    ],
    plugins: [
      new TsConfigPathsPlugin({
        tsconfig: __dirname + '/tsconfig.json',
        compiler: 'typescript'
      })
    ]
  },
  ...
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: [
          'awesome-typescript-loader',
          'angular2-template-loader'
        ]
      },
      ...
    ],
  }
};

Error

module.js:471
    throw err;
    ^

Error: Cannot find module 'models/User'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/simonxca/source/simonxca/simonxca.com-universal/dist/server/index.js:57593:18)
    at __webpack_require__ (/User
    ...

I couldn't tell from https://github.com/s-panferov/awesome-typescript-loader#advanced-path-resolution-in-typescript-20 whether or not I configured this correctly. Could we have a more specific example of how to configure TsConfigPathsPlugin so that it works with Typescript's baseUrl and paths options?

shorn commented 7 years ago

I have a similar issue. Typescript compiler by itself compiles correctly, but the webpack will give an error "Module not found: Error: Can't resolve ".

So I tried to fix this by just including the new TsConfigPathsPlugin() in the resolve section as above. I didn't know what to put in the parameters, and I don't configure configFilePath or anything in my modules rules, so I put nothing. I'm not sure what's happening, but the node process uses up 1.5GB of memory and then barfs with an "out of heap memory" error.

Don't know if this is a bug, or if I'm just using it wrong.

ollwenjones commented 7 years ago

having the same issue here, unless we enumerate a bunch of folders we want to hit, instead of relying on the cascading example in the TS docs.

dustincleveland commented 7 years ago

I was also struggling to get this working properly, but I think I've figured out the correct configuration for my application at least.

The issue I ran into was that even though I specified baseUrl: '.' in tsconfig.json, not all of my modules were being resolved correctly. It was actually very strange that in the example below, the first three imports worked fine. However, the last import did not work at all. I kept receiving an error that 'app/shared/index' couldn't be resolved.

import { ConfirmDiscardedChanges } from 'app/route-guards/index';
import { UnitConversionService } from 'app/shared/units/unit-conversion.service'
import { measurementUnits } from 'app/shared/units/measurement-units'

import {
    ModalDialogComponent,
    ModelValidationError,
    ResponseError,
    ConfigurationService,
    Cache
} from 'app/shared/index';

To fix the issue, I had to change up the configuration of the TsConfigPathsPlugin. I noticed that I could specify baseUrl in the plugin's constructor, so I removed the reference to tsconfig.json and replaced it with baseUrl. Now, everything seems to be working... so far.

new TsConfigPathsPlugin({
    baseUrl: helpers.root('src'),
    // tsconfig: helpers.root('src', 'tsconfig.json'),
    compiler: 'typescript'
})
mgenware commented 7 years ago

I hit this issue too, fixed it this way, hope it helps. webpack 2 only.

Set up the loader in module - rules:

// webpack.conf.js
{
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'awesome-typescript-loader'
      }
    ]
  }
}

No need to use any plugin, use webpack's resolve.modules(doc), also make sure .ts and .tsx are included in resolve - extensions.

// webpack.conf.js
{
    resolve: {
      extensions: ['.js', '.vue', '.json', '.ts', '.tsx'],
      modules: [path.resolve(__dirname, 'src'), 'node_modules']
  },
}

Note that this only solve the issue raised by webpack loader, for resolving relative path of Typescript in tsc or other tools, you may need to use tsconfig.json(doc) like this.

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "*": ["src/*"]
        }
    }
}
sthomp commented 6 years ago

Im having a similar issue getting at-loader to resolve a module. I'm importing a library using <head><script src='...' in my .html (to keep my bundle size smaller). To get types I've installed type @types in my node_modules. I can compile fine using tsc but using at-loader I get the error Module not found.

Looking at the webpack verbose output I can see it looking in node_modules/vendor_library but it's not looking in node_modules/@types/vendor_library so its not finding the index.d.ts file. I think I need to use TsConfigPathsPlugin to nudge it towards finding the types but this plugin doesn't seem to be documented anywhere?

ashok-sc commented 6 years ago

@simonxca have you solved this? I'm just starting to look into this and I agree the documentation is pretty terrible.

simonbear89 commented 6 years ago

Unfortunately I have not and just had to resort to using relative paths :(

jonaskello commented 6 years ago

I think a root cause can be that the plugin does not find the tsconfig.json. From what I remember that will result in a silent error. In tsconfig-paths-webpack-plugin we do a check of the options for the plugin and we also log out the path of the tsconfig.json being used. Note that the path to the tsconfig.json may be different than what you set for the loader. This is because resolver plugins don't get all the info that loader plugins get so it does not have a good way to find your default path.

ravenblackx commented 5 years ago

I've just debugged what this is - for me, TsconfigPaths.loadConfig (which is called by TsconfigPathsPlugin) transforms a baseUrl of "/a/b/c" on a project in "/x/y/z" into a value loadResult.absoluteBaseUrl = "/x/y/z/a/b/c". (On Windows - it looks like path.isAbsolute would produce a different outcome in a different environment.) TsconfigPathsPlugin, however, does not perform that same transformation on a baseUrl value passed to it directly, as in new TsConfigPathsPlugin({configFile: "someTsconfig.json", baseUrl: "/a/b/c"}), so if you set it there it will work, but now you'll have written the same path in two places like you were trying to avoid by using this module.

The difference is options.baseUrl gets passed through path.resolve(baseUrl) to generate an absolute path, whereas config-loader in the tsconfig-paths module does path.isAbsolute(baseUrl) ? baseUrl : path.join(cwd, baseUrl)

(Bearing in mind, this was the TsConfigPathsPlugin with regular ts-loader, not -awesome-.)