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

Module resolver / path rewrites / aliases #702

Closed
lostpebble opened this issue Mar 6, 2020 · 18 comments · Fixed by #1834
Closed

Module resolver / path rewrites / aliases #702

lostpebble opened this issue Mar 6, 2020 · 18 comments · Fixed by #1834
Labels
Milestone

Comments

@lostpebble
Copy link

lostpebble commented Mar 6, 2020

Describe the feature

Making use of babel-plugin-module-resolver, babel currently allows me to do something like this:

plugins: [[
  "module-resolver",
  {
    "alias": {
      "^@gt/([^/]+)/build/(.+)": "@gt/\\1/src/\\2",
      "^@vs/([^/]+)/build/(.+)": "@vs/\\1/src/\\2",
      "^@sc/([^/]+)/build/(.+)": "@scr/\\1/src/\\2",
    },
    "extensions": [".js", ".jsx", ".ts", ".tsx"],
  },
]]

Babel plugin or link to the feature description

https://github.com/tleunen/babel-plugin-module-resolver

Additional context

This is exceptionally useful to me because I use a monorepo for my projects, and split up parts of my projects into different modules so that they can be re-used in multiple apps. Things like @gt/node-utils and @gt/services etc.

The way I've set it up is that when each of those individual modules are built - their code is imported with something like:

import { createFile } from "@gt/node-utils/build/filesystem/FileUtils"

I expect these imports to work, even if the code in those modules hasn't actually been built yet- because I'm always jumping between these separate monorepo modules to improve them and add new features.

I hardly ever actually "build" the modules in my day to day, as I can just use babel to rewrite the paths using babel-plugin-module-resolver so when my code is being compiled for dev or even production builds, it always hits the current source code in each module.

This could be related to #379, as I am using tsconfig.json to set up path aliasing so that TypeScript intellisense functions correctly in my IDE:

"paths": {
      "@gt/common-utils/build/*": ["gt-common-utils/src/*"],
      "@gt/node-utils/build/*": ["gt-node-utils/src/*"],
      "@vs/vs-server/build/*": ["vs-server/src/*"],
      "@gt/gt-server/build/*": ["gt-server/src/*"],
      "@gt/gt-frontend/build/*": ["gt-frontend/src/*"],
      "@gt/services/build/*": ["gt-services/src/*"],
      "@gt/task-function-utils/build/*": ["gt-task-function-utils/src/*"]
    }
@kdy1 kdy1 added the E-medium label Mar 30, 2020
@ws456999
Copy link

ws456999 commented Jun 9, 2020

Is there any progress?

@kdy1
Copy link
Member

kdy1 commented Jun 9, 2020

@ws456999 Sadly, not yet.

I recently got an idea about such api, but it's blocked by neon-bindings/neon#73 / infinyon/node-bindgen#37 (I'll switch to node-bindgen if required)


Edit: I got an idea about the api. I'll see if it works.

@monoclex
Copy link

Any progress on this? I also use this feature.

@aelbore
Copy link

aelbore commented May 17, 2021

Im currently using typescript resolveModuleName it would be great to have this.

@JulienKode
Copy link
Contributor

Is there any update about this issue ?
or any workaround

@pbadenski
Copy link

+1 we're migrating to a monorepo layout and it's a bit challenging without this feature

@kdy1
Copy link
Member

kdy1 commented Jun 18, 2021

I started working on this, and I'm not sure if it's correct to support both of babel rewriter and tsconfig rewriter.
What do you guys think?

@lostpebble
Copy link
Author

Well I just need to be able to tell the compiler to rewrite certain import paths when it encounters them and follow that new path for the module instead- whatever allows the most customization in this regard is the better one for me.

So I'd say the babel one is better? Since it uses a regex syntax and seems like you can use it for quite complex rewrites, as you can see I could do the same thing with a lot fewer lines than I could do with Typescript.

@pbadenski
Copy link

We only need tsconfig - so from our perspective simple matching is enough. As @lostpebble pointed out babel rewriting seems to be a superset, so sounds like a solution that makes more people happy :D Automated parsing of tsconfig would be nice, but if I need to duplicate this config in .swrc - I don't really mind.

@kdy1
Copy link
Member

kdy1 commented Jun 21, 2021

Thanks for the response!
I decided to implement tsconfig.paths because I want to make a complete typescript compiler :)

@kdy1 kdy1 added this to the v1.2.62 milestone Jun 24, 2021
kdy1 added a commit that referenced this issue Jun 24, 2021
swc_ecma_loader:
 - Add `Resolve`. 
 - Add `TsConfigResolver`. 

swc_ecma_transforms_module:
 - Use `Resolve` for remapping import paths.
 - Add `ImportResolver`.
 - Add `NodeImprortResolver`.

swc:
 - Add `paths` to `.swcrc`.
 - Use `paths`. (#379, #702)
 - Canonicalize file names.
@vjpr
Copy link

vjpr commented Aug 25, 2021

NOTE: To get this to work you must specify a module option in your config or modules are left untouched:

{
   "jsc": { ... },
   "module": {
     type": "commonjs"
   }
}

Using module.type = es6 also doesn't do anything. This is maybe a bug?

@vjpr
Copy link

vjpr commented Aug 25, 2021

I think there are some bugs here.

// .swcrc

    "paths": {
      "@src/*": [
        "*"
      ]
    }
// src/foo/index.ts

import '@src/index'

Output:

// lib/foo/index.ts

- require('./index')
+ require('../index')

When resolving path aliases, it should resolve relative to the base url.

Can the base url be read without reading a tsconfig?

And what happens is a tsconfig uses extends? Does it resolve this correctly?

@kdy1
Copy link
Member

kdy1 commented Aug 25, 2021

Can the base url be read without reading a tsconfig?

I'm not sure about this memory, but I thunk you should specify baseUrl in .swcrc

Does it resolve this correctly?

No

@vjpr
Copy link

vjpr commented Aug 25, 2021

but I thunk you should specify baseUrl in .swcrc

I specified baseUrl: 'src' just like I have in tsconfig.json, and it doesn't have any effect.

@athrunsun
Copy link

@kdy1 There's nothing in the documentation about baseUrl, could you provide more details on this?

@kdy1
Copy link
Member

kdy1 commented Sep 7, 2021

@athrunsun You can refer to documentation for baseUrl of typescript.

@vjpr
Copy link

vjpr commented Sep 7, 2021

The problem with the current code is that base_url is not used in the TsConfigResolver.

With:

rootDir: ".",
baseUrl: "src",
paths: {"@src/*": ["*"]},

If we have:

src/foo/index.js

import from '@src/index'

It should resolve @src/index to absolute path <base_url>/index, and then determine the relative path from src/foo/index to <base_url>/index, which should be ../index. But currently it is ./index.

for (from, to) in &self.paths {
match from {
Pattern::Regex(from) => {
let captures = from.captures(src);
let captures = match captures {
Some(v) => v,
None => continue,
};
let mut iter = captures.iter();
let _ = iter.next();
let capture = iter.next().flatten().expect(
"capture group should be created by initializer of TsConfigResolver",
);
let mut errors = vec![];
for target in to {
let replaced = target.replace('*', capture.as_str());
let rel = format!("./{}", replaced);
let res = self.inner.resolve(base, &rel).with_context(|| {
format!(
"failed to resolve `{}`, which is expanded from `{}`",
replaced, src
)
});
errors.push(match res {
Ok(v) => return Ok(v),
Err(err) => err,
});
if to.len() == 1 {
return Ok(FileName::Custom(replaced));
}
}
bail!(
"`{}` matched `{}` (from tsconfig.paths) but failed to resolve:\n{:?}",
src,
from.as_str(),
errors
)
}
Pattern::Exact(from) => {
// Should be exactly matched
if src == from {
return self
.inner
.resolve(base, &format!("./{}", &to[0]))
.with_context(|| {
format!(
"tried to resolve `{}` because `{}` was exactly matched",
to[0], from
)
});
}
}
}
}
self.inner.resolve(base, src)
}
}

Changing self.inner.resolve(base, &rel) to self.inner.resolve(base_url, &rel) might work I think. base_url needs to be added as a param though.

@swc-bot
Copy link
Collaborator

swc-bot commented Oct 22, 2022

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@swc-project swc-project locked as resolved and limited conversation to collaborators Oct 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

Successfully merging a pull request may close this issue.

10 participants