Skip to content
This repository has been archived by the owner on Dec 1, 2019. It is now read-only.

Support baseUrl and paths resolution as implemented in TS 1.9 #156

Closed
guncha opened this issue Jun 9, 2016 · 25 comments
Closed

Support baseUrl and paths resolution as implemented in TS 1.9 #156

guncha opened this issue Jun 9, 2016 · 25 comments

Comments

@guncha
Copy link
Contributor

guncha commented Jun 9, 2016

I was trying to use awesome-typescript-loader with typescript@next to see if I could set it all up to avoid this whole import {..} from "../../../../../dep business and it seems like baseUrl option solves it, but only when not running through the loader.

When running with the loader, I'm getting an error:

Error: Cannot resolve module 'dep' in app
  at ResolutionError.Error (native)
  at new ResolutionError (node_modules/awesome-typescript-loader/dist.babel/deps.js:577:88)
  at node_modules/awesome-typescript-loader/dist.babel/deps.js:402:37

Does the loader have its own module resolution strategy? If so, can we extend it to support what's being discussed in microsoft/TypeScript#5039 or perhaps use the compiler's?

@s-panferov
Copy link
Owner

@guncha this error is about webpack and how it resolves modules. Webpack knows nothing about typescript, it uses basic node-style module resolution strategy. I need to think about how to connect webpack's resolution config with typescript's one, but right now there is a workaround:

@guncha
Copy link
Contributor Author

guncha commented Jun 10, 2016

I see, that's very interesting. I had assumed that the loader tells webpack "hey, add these files as dependencies", but I guess it's the other way around.

@TheLarkInn
Copy link
Contributor

@s-panferov how would you go about setting this in alias in webpack. (I've pasted below what I've been able to get to work in ts-loader. If it helps.

ts.config

    "paths": {
      "@angular2-material/core/*": [
        "./core/*",
        "../core/*"
      ],
      "@angular2-material/*": [
        "./components/*",
        "../components/*"
      ]
    }

webpack.config.js

var components = [
    'button',
    'card',
    'checkbox',
    'grid-list',
    'icon',
    'input',
    'list',
    'progress-bar',
    'progress-circle',
    'radio',
    'sidenav',
    'slide-toggle',
    'button-toggle',
    'tabs',
    'toolbar'
];
/** Map relative paths to URLs. */
var aliasMap: any = {
    '@angular2-material/core': ngAppResolve('./src/core'),
};

components.forEach(function (name) {
  aliasMap[("@angular2-material/" + name)] = ngAppResolve("./src/components/" + name);
  return aliasMap[("@angular2-material/" + name)] = ngAppResolve("./src/components/" + name);
});

export const config = {
  resolve: {
    alias: aliasMap
  }
}

@s-panferov
Copy link
Owner

@TheLarkInn yes, aliases is the right way to go. I just need to think if it possible to set them automatically , using info from tsconfig.json.

I suppose we need something like

import { tsAliases } from `awesome-typescript-loader`

export const config = {
  resolve: {
     alias: tsAliases({ /* additional aliases */ })
  }
}

@TheLarkInn
Copy link
Contributor

@s-panferov could you set it in compiler.plugin('run') or ('watch-run') or both.

@s-panferov
Copy link
Owner

@TheLarkInn I don't think so, because as far as I remember webpack creates resolver one time during init process. I need to dig into this.

@TheLarkInn
Copy link
Contributor

@sokra do you have any suggestions for this? I'm not sure the best way to handle aliasing like this.

@sokra
Copy link

sokra commented Jun 22, 2016

You can write a resolver plugin for webpack, which takes care of resolving dependencies accoring to a tsconfig relative to the origin file.

@s-panferov
Copy link
Owner

@sokra ok, I'll try to implement this. Do you have any examples?

@TheLarkInn
Copy link
Contributor

TheLarkInn commented Jun 22, 2016

@s-panferov https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L273-L286

Looks like how webpack reads aliases and applies them.

compiler.applyPlugins("after-plugins", compiler);
        // I would assume right here is where we want to add to the resolvers. 
    compiler.resolvers.normal = ResolverFactory.createResolver(assign({
        resolver: compiler.resolvers.normal
    }, options.resolve));

    compiler.resolvers.context = ResolverFactory.createResolver(assign({
        resolver: compiler.resolvers.context,
        resolveToContext: true
    }, options.resolve));
    compiler.resolvers.loader = ResolverFactory.createResolver(assign({
        resolver: compiler.resolvers.loader
    }, options.resolveLoader));

@sokra
Copy link

sokra commented Jun 23, 2016

Here is the webpack alias plugin: https://github.com/webpack/enhanced-resolve/blob/master/lib/AliasPlugin.js

It's used here: https://github.com/webpack/enhanced-resolve/blob/master/lib/ResolverFactory.js#L155


So you can write your own alias plugin: TsConfigAliasPlugin and use it in the configuration:

resolve: {
  plugins: [
    new TsConfigAliasPlugin("described-resolve", "resolve")
  ]
}

@s-panferov
Copy link
Owner

Basic implementation landed in v2.0.0-rc.15.

var TsConfigPathsPlugin = require('awesome-typescript-loader').TsConfigPathsPlugin;

resolve: {
    plugins: [
        new TsConfigPathsPlugin()
    ]
}

Please try and say what you think.

@TheLarkInn
Copy link
Contributor

Good timing I'll try right now. Great work.

@TheLarkInn
Copy link
Contributor

ReferenceError: ts is not defined at Object.readConfigFile (/Users/larkinfamily/Code/angular-cli/node_modules/awesome-typescript-loader/src/instance.ts:319:30)

I didn't see ts defined anywhere in instance.ts

@TheLarkInn
Copy link
Contributor

@s-panferov I am still seeing that error. Just to confirm, I don't have to pass any arguments to the plugin, it likes in the code it already picked up and obtained from instance

@TheLarkInn
Copy link
Contributor

Here is a gist of the configuration if this helps.

@s-panferov
Copy link
Owner

@TheLarkInn just to confirm, you don't have a tsconfig.json file in your project?

s-panferov added a commit that referenced this issue Jun 25, 2016
@s-panferov
Copy link
Owner

I've fixed the error in 2.0.0-rc.16, but it appeared only when you don't have tsconfig.json.

This is right config for your app:

new TsConfigPathsPlugin({
   tsconfig: ngAppResolve('./src/demo-app/tsconfig.json'),
})

Unfortunately, the plugin can't communicate with the loader, so you have to specify tsconfig option twice for now.

@TheLarkInn
Copy link
Contributor

This is for a situation where angular CLI I which generates projects. so the tsconfig is not at the root execution path it's the projects patg

@TheLarkInn
Copy link
Contributor

Thank you that's no problem at all. I'll let you know here in a bit, sorry for this edge-casey kind of stuff.

@s-panferov s-panferov mentioned this issue Jun 27, 2016
12 tasks
@s-panferov
Copy link
Owner

@TheLarkInn could you please confirm that everything works?

@TheLarkInn
Copy link
Contributor

@s-panferov Yup. I'll take a look at it again today. And let you know what I find.

@guncha
Copy link
Contributor Author

guncha commented Jun 27, 2016

Nice, I can confirm that it works with baseUrl and paths options in tsconfig.json. A few things that weren't immediately obvious to me:

  1. This is a webpack 2.0 plugin and the configuration has no effect when used with 1.x.
  2. I had to add *.ts and *.tsx to resolve.extensions. That seems a little odd, but I think I understand the underlying reason for it. Perhaps the plugin could ensure that those are added?

Either way, awesome work. Can't wait to use this. Now if the editors could catch up to 1.9.x, that'd be great.

@TheLarkInn
Copy link
Contributor

My edge case project is really hard to test this feature and tell you reliably if it's working so I'm going to create a test project and test this feature more in depth.

@TheLarkInn
Copy link
Contributor

@s-panferov I had to back port an isolated hack of this to v1.1.1 but when I did I could confirm it was working (did have some a-t-loader diagnostic errors because a-t-loader 's Resolver was failing to find 1 or two files). In regards to the back port there seems to be some strange path resolution issues outside of this use.

Second when baseUrl:'' it needs to default to './' or path.dirname(configFilePath). Sorry for the delay with this I've been cross coding like 5 libraries webpack and angular-cli being two of them.

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

No branches or pull requests

4 participants