-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Implement TypeScript resolver plugin #4936
Comments
In response to the open questions:
|
Importing images, CSS, etc. from TS-based UI components seems like it‘s fairly common, and should be supported by Parcel. Also other languages that TS doesn’t natively understand like .vue and .svelte. I believe it’s possible to build TS language service extensions to handle these eg https://github.com/mrmckeb/typescript-plugin-css-modules |
@101arrowz the syntax issue is fairly simple to solve just configure a declaration file with something like this (like Devon already mentioned this is fairly common, I used to do it all the time for svg to react transformers):
and it will no longer throw syntax errors, as this is a standard Parcel feature it's probably a good idea to write a config/plugin for people in the docs that really supports everything as this declaration file trick I just mentioned does break the path autocomplete. |
I was not aware of the existence of TS language service plugins, which would likely be the best solution for custom Parcel imports. I'd be willing to help with the implementation. |
Originally posted by @zachbryant in #202 (comment) |
it looks like Changing async resolve({ filePath, dependency, options, logger }) { to async resolve({ specifier: filePath, dependency, options, logger }) { fixes that. I can't find a public repo for |
Public repo of Change of |
thanks @bycaldr ! I'll have a look when I get back to this. |
I think it's worth also noting that typescript allows me to import with a Form what I can tell this is becoming a popular setup as it brings the code you write in typescript closer to what would work natively in an a JS engine - where file extensions in imports is encouraged AFAICT. Is that within scope of this issue? edit: FileA.ts
FileB.ts
|
@bycaldr and @ thread Updated the plugin after a bit of a hiatus. Should be all good now. |
I just tried with "baseUrl": "./",
"paths": {
"@shared/*": ["pages/shared/*"]
} are still not taken into account for typescript import like this: import Icon from '@shared/components/Icon'; The error I get from parcel build is
Was this actually supposed to be fixed by the recent updates @zachbryant ? |
@jacekkopecky could you make an issue in the repo, and also include your project folder structure? The latest update was to address some api changes in the 2.0 release |
I just noticed that the docs on module resolution mention using tilde or alias mappings, which I hadn't noticed the latter before. However, the latest parcel still cannot use tsconfig.json aliases. Is parcel specifically only allowing tilde resolution? Is it important to use baseUrl '.' for some reason, like the example? Would really appreciate clarity on this in the docs, that other aliases are not supported, because current phrasing pretty much says the opposite. |
With TypeScript 4.7’s new To be clear {
"alias": {
"./this-stuff-is-just-for-local-parcel-tests": "https://github.com/parcel-bundler/parcel/issues/4936",
"./source/sender.js": "./source/sender.ts",
"./source/receiver.js": "./source/receiver.ts",
"./source/types.js": "./source/types.ts",
"./source/shared.js": "./source/shared.ts",
"./source/api.js": "./source/api.ts",
"./source/index.js": "./source/index.ts",
"./source/thisTarget.js": "./source/thisTarget.ts",
ETC
}
} Edit: This is equivalent and works for all: {
"alias": {
"./this-stuff-is-just-for-local-parcel-tests": "https://github.com/parcel-bundler/parcel/issues/4936",
"./source/**/*.js": "./source/$1/$2.ts"
}
} |
Wait so you write .js even though you actually want .ts? That's horrible! |
That's right. Tell the TypeScript team. The reasoning is that they don't want to rewrite the paths, so you have to write the final path and it'll ignore the extension. |
See latest attempts to convince them here: microsoft/TypeScript#49083 |
An alternative to creating a Parcel resolver for TypeScript syntax is to create a TypeScript resolver for Parcel syntax, that way you can use any Parcel import with |
I replied on that issue. The official response seems to be that the |
Nothing is "only for node." The moduleResolution setting does add support for "node-only" imports from node_modules but bundlers exist specifically to bring node modules to the browser. The As for my case specifically:
The last point specifically is why many of us are here. Extensions are only enforced by this new setting, but they've been there for years in TypeScript. As for this issue, if TypeScript can resolve it, then a "typescript resolver" presumably should too. |
I wanted to migrate my projects using webpack to parcel, but the lack of path resolution with Then I created a resolver (didn't knew that some already existed) and its working in some of my projects. It needs more tests, but have some documentation, maybe someone could benefit from it. |
I'm currently trying to implement support for baseUrl, paths, moduleSuffixes, and extension replacement (e.g. One question I've come across is how to load |
@devongovett not sure how to do it in Parcel as I'm not enough familiar with it. But as you said in a monorepo you'd usually run At least that is what I've seen and done myself. I'd guess there would be some design flaw in project structure if you'd have additional nested configurations in addition to base+project 🤔 |
Yeah I decided to search upward for the nearest tsconfig.json file from the source file containing the import, and resolve using that. That will be the closest without requiring manual configuration of all of the project roots. This will not apply within node_modules and will only apply for dependencies in JS and TS files (e.g. paths will not apply to CSS files). |
I'm curious if this should also apply to project references - the project reference seems very similar to the |
#8807 adds support for the following tsconfig features:
It also matches TSC's behavior in regards to extensions: Importing a file with a This is now released in nightly if anyone wants to try it and report back. Thanks! |
Hi @devongovett, I’m testing how various bundlers handle imports from let bundler = new Parcel({
entries: path.resolve(__dirname, `../../src/${filename}`),
defaultConfig: require.resolve("@parcel/config-default"),
mode: "production",
targets: {
main: {
engines: {
node: "14",
},
distDir: path.resolve(__dirname, `../../dist/${idx}`),
},
},
}); and the |
I guess we'd need to add mts and cts here:
|
Is there a way to easily override that default config value in the options I pass in? |
Yes. You can create a {
"extends": "@parcel/config-default",
"transformers": {
"*.{mts,cts}": [
"@parcel/transformer-babel",
"@parcel/transformer-js",
"@parcel/transformer-react-refresh-wrap"
]
}
} |
Is there a way to do that from the API without adding another file? (I’m programmatically running many bundlers for https://andrewbranch.github.io/interop-test, so adding file-based config is a bit of a pain.) |
I went ahead and added a config file, and FYI the bundled output crashes in Node with stuff like
So I guess there may be a bit more to do to support Edit: the resolution errors seem to occur only in test cases that use dynamic import. The results are now published at https://andrewbranch.github.io/interop-test/#parcel-mts, and you can see the methodology at https://github.com/andrewbranch/interop-test/blob/main/lib/runners/runParcelTest.js if you’re interested in obtaining a repro. |
Looks like you've run into what's described in #8468: with your config, the current semantics of parcelrc mean that --- lib/runners/runParcelTest.js
+++ lib/runners/runParcelTest.js
@@ -26,7 +26,7 @@ module.exports = async (runtime, variant, ext, packageJsonType) => {
const parcelrcContent = {
extends: "@parcel/config-default",
transformers: {
- "*.mts": [
+ "*.{js,mjs,jsm,jsx,es6,cjs,ts,tsx,mts,cts}": [
"@parcel/transformer-babel",
"@parcel/transformer-js",
] |
Excellent, that does fix it. Thanks! |
So what is the resolution to this? Is there any update to the Parcel Documentation site about using this? |
TypeScript supports some additional features in its resolver on top of the Node resolution algorithm. These are configured in
tsconfig.json
.baseUrl
- a root directory from which to resolve non-relative paths, in addition tonode_modules
. See also: [TypeScript]baseUrl
inside tsconfig.json not supporting. #202.paths
- additional directories, relative tobaseUrl
, that should also be searched.rootDirs
- virtual directories that relative paths can be resolved fromThere's also the legacy module resolution mode that TS supports. Not sure if that's something we should also support, but I guess someone might still use it. 🤷
Implementation
These resolution features should be supported in Parcel for imports declared in
.ts
or.tsx
files. This can be done via a new resolver plugin, included in the default config:@parcel/resolver-typescript
. This resolver should look at thesourcePath
property of the dependency, and if it has a.ts
or.tsx
extension, it should resolve using the TS compiler API'sresolveModuleName
method. It should use a customModuleResolutionHost
that ensures the Parcel file system is used instead of the Node one. This can be created using the@parcel/ts-utils
package, which already includes anFSHost
package implementing much of the required interface.If a module is not resolved, or the source file is not a
.ts
or.tsx
file, then the resolver should returnnull
. This will then fall back to the default Parcel resolver, which will handle Parcel specific features like aliases.Open questions
url:./foo.jpg
to import an image as a url). Theoretically we could fall back to the default resolver if TS doesn't find anything, but what if you aliasreact
topreact
butreact
is found by the TS resolver?The text was updated successfully, but these errors were encountered: