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

[@web/dev-server-esbuild] does not read tsconfig.json #1921

Open
pmcelhaney opened this issue Apr 2, 2022 · 16 comments
Open

[@web/dev-server-esbuild] does not read tsconfig.json #1921

pmcelhaney opened this issue Apr 2, 2022 · 16 comments

Comments

@pmcelhaney
Copy link
Contributor

As far as I can tell, the ESBuild plugin does not look at tsconfig.json.

It uses the ESBuild's Transform API, which would require the plugin to explicitly pass the contents of the tsconfig.json file via the tsconfigRaw option.

So far not reading the tsconfig.json hasn't presented any significant problems for me, but the fact that my changes to that file had no effect on web-dev-server was confusing. I would suggest either documenting the fact that the tsconfig.json file is ignored or adding an option to specify the path to the tsconfig.json file.

If either of those sounds good, or you have some other idea, I'm happy to create a PR.

@LarsDenBakker
Copy link
Member

Adding an option to specify the path would be a good idea.

@kobleistvan
Copy link

I agree. We would need this to work, because we're using this within a monorepo, and specifying path aliases would be very useful. Thanks

@pmcelhaney
Copy link
Contributor Author

@kobleistvan Would it be helpful if there was an option to automatically find the tsconfig file for each .ts file (using the same algorithm as TypeScript itself)?

That's my ultimate goal. I started with specifying the path to a single tsconfig.json because I didn't want to do too much in one PR (and there are cases when I want to point to a specific config).

@kobleistvan
Copy link

kobleistvan commented Apr 18, 2022

@pmcelhaney In our application, we have a 'base' tsconfig in the monorepo root, and some packages have their own tsconfig file which extends the one from the root. So it would be great if perhaps the wtr command itself could take as an additional argument the path to a specific tsconfig file (and take into consideration the internal 'extends' key's value).

@kobleistvan
Copy link

@pmcelhaney FYI, I worked around my issue via:
`import { fromRollup } from '@web/dev-server-rollup';
import tsConfigPaths from 'rollup-plugin-tsconfig-paths';

const tsPaths = fromRollup(tsConfigPaths.default);

// ...

plugins: [
tsPaths({}),
esbuildPlugin({ ts: true }),
],
`

So basically there's a rollup plugin to overcome the path issues, and the fromRollup makes it so that I can use it here. Would be nice if there would be native support though (i.e. for other tsConfig configs)

Cheers

@lucaelin
Copy link
Contributor

So far not reading the tsconfig.json hasn't presented any significant problems for me

One example for this being useful is the importsNotUsedAsValues compilerOption. This option is supposed to fix the need for duplicate import statements when importing a module with both a type export and side-effects, like defining a custom-element.
Without this option, typescript strips all import statements, that only import types. This also gets rid off any side-effects that would happen during the import, see https://www.typescriptlang.org/tsconfig#importsNotUsedAsValues .

Starting in v14, esbuild now aligns with behavior of tsc, see https://github.com/evanw/esbuild/releases/tag/v0.14.0 , so by default import-statements in typescript file often have to be listed twice, once for the type and once as a bare import to cause side-effects.

Passing the tsconfig with this option set to preserve would fix the duplication.

@lucaelin
Copy link
Contributor

lucaelin commented May 6, 2022

I saw the MR for this being merged, but no new release for this plugin. Is there an estimate on when the next release is gonna happen?

@muratcorlu
Copy link
Contributor

This problem causes inconsistencies for some Typescript features (like decorators) in tests. I had a problem (explained in #1963) and returning back to v0.2.16 fixed the issue. I hope v0.3.1 will arrive soon with a fix for this.

Does anyone know what is the procedure for releases?

@jrencz
Copy link

jrencz commented Jan 26, 2023

I just found this issue after a of of investigation of some problem I experienced in my project.

I'm happy that tsconfig can be specified since #1922 and specifying it resolved the problem I had, but I think that when ts is set to true, then @web/dev-server-esbuild should try to find a tsconfig.json. I'm not creating a new issue, because name of this one exactly describes what I wanted to write. Maybe but for "does not automatically read" part :)

Problem I had was that @web/dev-server-esbuild compiles to esnext if

In my case it caused property decorated with a Lit decorator @query,

@query('.something')
foo;

which in compiled code becomes:

__decorateClass([
  query(".something")
], MyClass.prototype, "foo", 2);

being shadowed with an empty initializer:

foo;

(I'm aware it's a thin ice to use esbuild when Lit recommends using decorators in TS ina certain way)

Once pointed path to my tsconfig, problem went away: the field initializer is not longer emitted.

@pmcelhaney
Copy link
Contributor Author

@jrencz I agree. I figured adding a config option would be easier to "sell" to the maintainers and is probably necessary in some cases anyway. All that remains now is default that option to the location of the automatically found tsconfig.json file (if one exists).

Per the TypeScript docs:

... the compiler searches for the tsconfig.json file starting in the current directory and continuing up the parent directory chain.

I don't have the bandwidth right now so I'll leave it open for anyone else who wants to create a pull request.

@Stradivario
Copy link

Hello there guys!

Any solution to namespace problem with esbuild and testing library ?

I have a component called flights.component.ts

I have a test which just imports the lit html web component import './flights.component

My test looks as follows

import './flights.component';

it('Should create admin-flights element', () => {
  document.createElement('admin-flights');
});

I have the following configuration inside web-test-runner.config.mjs

import { esbuildPlugin } from '@web/dev-server-esbuild';
import { legacyPlugin } from '@web/dev-server-legacy';
import { fileURLToPath } from 'url';

export default {
  files: ['src/**/*.spec.ts'],
  nodeResolve: true,
  watch: true,
  concurrency: 10,
  plugins: [
    esbuildPlugin({ ts: true, tsconfig: fileURLToPath(new URL('./tsconfig.json', import.meta.url)), target: 'auto' }),
    // make sure this plugin is always last
    legacyPlugin({
      polyfills: {
        webcomponents: true,
        // Inject lit's polyfill-support module into test files, which is required
        // for interfacing with the webcomponents polyfills
        custom: [
          {
            name: 'lit-polyfill-support',
            path: 'node_modules/lit/polyfill-support.js',
            test: "!('attachShadow' in Element.prototype)",
            module: false,
          },
        ],
      },
    }),
  ],
};

When i run the tests i got an error that it cannot resolve import @core/services

 Could not import your test module. Check the browser logs or open the browser in debug mode for more information. 

Error while transforming src/app/portals/admin/flights/flights.component.ts: Could not resolve import "@core/services".
  10 |   return result;
  11 | };
> 12 | import { Api } from "@core/services";
     |                     ^
  13 | import { Component } from "@rhtml/component";
  14 | import { FlexLayout } from "@rhtml/modifiers";
  15 | import { Container } from "@rxdi/core";

Chrome: |██████████████████████████████| 1/1 test files | 0 passed, 0 failed

Finished running tests, watching for file changes...

In my tsconfig i have the following paths specified

    "paths": {
      "@shared/*": [
        "app/shared/*"
      ],
      "@introspection/*": [
        "app/@introspection/*"
      ],
      "@core/*": [
        "app/core/*"
      ],
      "@assets/*": [
        "assets/*"
      ],
      "~/*": [
        "app/*"
      ]
    }

I was assuming that since i have defined tsconfig property and import the configuration inside esbuild plugin it will automatically resolve my paths but unfortunate this does not happen.

Any idea how i can manage to add my paths from tsconfig to esbuild ?

For my regular starting the application i am using babel to convert these paths to appropriate imports but inside web testing runner i cannot make it to work...

@jrencz
Copy link

jrencz commented Mar 2, 2023

@Stradivario take a look at rollup-plugin-typescript-paths

I use it and it does the job

@venikx
Copy link

venikx commented Mar 16, 2023

@kobleistvan and possibly @pmcelhaney is the test case I added here what you were referring to?

@electrovir
Copy link

electrovir commented Apr 4, 2023

@jrencz how does one use rollup-plugin-typescript-paths in wtr? I added typescriptPaths to plugins but it just throws tons of Could not resolve import errors.

Edit:

Figured it out. I needed the following configuration:

import {fromRollup} from '@web/dev-server-rollup';
import {typescriptPaths} from 'rollup-plugin-typescript-paths';
import {esbuildPlugin} from '@web/dev-server-esbuild';

export default {
    plugins: [
        fromRollup(typescriptPaths)({
            preserveExtensions: true,
            absolute: false,
            transform(path) {
                return '/' + path;
            },
        }),
        esbuildPlugin({ts: true}),
    ],
}

All of the typescriptPaths options provided above were necessary (for me at least).

@jrencz
Copy link

jrencz commented Apr 4, 2023

@electrovir you need to pass the tsconfig part next to ts:true in esbuild

@difosfor
Copy link

Ah, thanks! I was able to get this working by specifying the tsconfig option to esbuildPlugin as now documented:

import { fileURLToPath } from 'url';

esbuildPlugin({
  ts: true,
  tsconfig: fileURLToPath(new URL('./tsconfig.json', import.meta.url)),
});

-- https://modern-web.dev/docs/dev-server/plugins/esbuild/

I also had to add "useDefineForClassFields": false below "experimentalDecorators": true in my tsconfig.json file as now documented by lit: https://lit.dev/docs/components/decorators/#decorators-typescript

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

No branches or pull requests

10 participants