vite icon indicating copy to clipboard operation
vite copied to clipboard

Unable to use "tsconfig.json"'s "extends" key with yarn3

Open Alex-Yakubovsky opened this issue 2 years ago • 8 comments

Describe the bug

I'd like to extend a re-usable tsconfig.json (e.g, https://www.npmjs.com/package/@tsconfig/recommended). When adding the option "extends": "@tsconfig/recommended" to my tsconfig.json inside a Vite project (using vite's react + ts starter) and running yarn build I get:

▲ [WARNING] Cannot find base config file "@tsconfig/recommended"

    tsconfig.json:2:13:
      2 │   "extends": "@tsconfig/recommended",
        ╵              ~~~~~~~~~~~~~~~~~~~~~~~

Reproduction

https://github.com/Alex-Yakubovsky/vite-error-repo

System Info

System:
    OS: macOS 12.2.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 163.77 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
    Yarn: 3.2.1 - ~/.nvm/versions/node/v16.14.2/bin/yarn
    npm: 8.9.0 - ~/.nvm/versions/node/v16.14.2/bin/npm
  Browsers:
    Chrome: 101.0.4951.64
    Safari: 15.3

Used Package Manager

yarn

Logs

▲ [WARNING] Cannot find base config file "@tsconfig/recommended"

    tsconfig.json:2:13:
      2 │   "extends": "@tsconfig/recommended",
        ╵              ~~~~~~~~~~~~~~~~~~~~~~~

  vite:config bundled config file loaded in 97.90ms +0ms
  vite:config using resolved config: {
  vite:config   plugins: [
  vite:config     'vite:build-metadata',
  vite:config     'alias',
  vite:config     'vite:react-babel',
  vite:config     'vite:react-refresh',
  vite:config     'vite:react-jsx',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html-inline-proxy',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:build-html',
  vite:config     'vite:worker-import-meta-url',
  vite:config     'vite:watch-package-data',
  vite:config     'commonjs',
  vite:config     'vite:data-uri',
  vite:config     'rollup-plugin-dynamic-import-variables',
  vite:config     'vite:asset-import-meta-url',
  vite:config     'vite:build-import-analysis',
  vite:config     'vite:esbuild-transpile',
  vite:config     'vite:terser',
  vite:config     'vite:reporter',
  vite:config     'vite:load-fallback'
  vite:config   ],
  vite:config   build: {
  vite:config     target: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     polyfillModulePreload: true,
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: true,
  vite:config     cssTarget: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     sourcemap: false,
  vite:config     rollupOptions: {},
  vite:config     minify: 'esbuild',
  vite:config     terserOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     reportCompressedSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null,
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] }
  vite:config   },
  vite:config   resolve: { dedupe: [ 'react', 'react-dom' ], alias: [ [Object], [Object] ] },
  vite:config   optimizeDeps: {
  vite:config     include: [ 'react/jsx-dev-runtime' ],
  vite:config     esbuildOptions: { keepNames: undefined, preserveSymlinks: undefined }
  vite:config   },
  vite:config   configFile: '/Users/alexanderyakubovsky/test-vite/test/vite.config.ts',
  vite:config   configFileDependencies: [ '/Users/alexanderyakubovsky/test-vite/test/vite.config.ts' ],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     build: {}
  vite:config   },
  vite:config   root: '/Users/alexanderyakubovsky/test-vite/test',
  vite:config   base: '/',
  vite:config   publicDir: '/Users/alexanderyakubovsky/test-vite/test/public',
  vite:config   cacheDir: '/Users/alexanderyakubovsky/test-vite/test/node_modules/.vite',
  vite:config   command: 'build',
  vite:config   mode: 'production',
  vite:config   isWorker: false,
  vite:config   isProduction: true,
  vite:config   server: {
  vite:config     preTransformRequests: true,
  vite:config     fs: { strict: true, allow: [Array], deny: [Array] }
  vite:config   },
  vite:config   preview: {
  vite:config     port: undefined,
  vite:config     strictPort: undefined,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: undefined,
  vite:config     proxy: undefined,
  vite:config     cors: undefined,
  vite:config     headers: undefined
  vite:config   },
  vite:config   env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   packageCache: Map(0) { set: [Function (anonymous)] },
  vite:config   createResolver: [Function: createResolver],
  vite:config   worker: {
  vite:config     format: 'iife',
  vite:config     plugins: [
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object]
  vite:config     ],
  vite:config     rollupOptions: {}
  vite:config   }
  vite:config } +5ms
vite v2.9.9 building for production...
✓ 34 modules transformed.
dist/assets/favicon.17e50649.svg   1.49 KiB
dist/assets/logo.ecc203fb.svg      2.61 KiB
dist/index.html                    0.46 KiB
dist/assets/index.62f502b0.css     0.75 KiB / gzip: 0.48 KiB
dist/assets/index.2b0e2339.js      140.35 KiB / gzip: 45.10 KiB

Validations

Alex-Yakubovsky avatar May 27 '22 19:05 Alex-Yakubovsky

The error comes from esbuild and it was reproducible only with esbuild. Closing as it is not a bug in Vite.

You could create an issue at esbuild repository but it seems it won't be supported (https://github.com/evanw/esbuild/issues/237). It might be an option to create an issue at yarn because they maintain esbuild-plugin-pnp.

sapphi-red avatar May 28 '22 14:05 sapphi-red

Thank you for pointing me to esbuild-plugin-pnp. There may still be an issue on Vite's side as I'm able to build with just esbuild. I've updated the https://github.com/Alex-Yakubovsky/vite-error-repo to include an example that successfully builds with esbuild but not with vite.

Inside of vite.config.ts I added

import { pnpPlugin } from '@yarnpkg/esbuild-plugin-pnp';
export default defineConfig({
    ...
    optimizeDeps: {
       esbuildOptions: {
           plugins: [pnpPlugin()]
       }
    }
})

however, I'm still seeing the warning described in the issue.

If instead I have

// build.js
const { pnpPlugin } = require('@yarnpkg/esbuild-plugin-pnp')

require('esbuild').build({

    entryPoints: ['./src/App.tsx'],
    bundle: true,
    outfile: 'out.js',
    plugins: [pnpPlugin()]
}).catch(() => process.exit(1))

and run yarn node build.js. I get no such warning.

I also only run into this issue when vite.config.ts is present. I am able to use tsconfig.json's "extends" key without any issue when using the vanilla ts starter + yarn3 pnp. Happy to create a minimal working example if that helps.

Alex-Yakubovsky avatar May 28 '22 16:05 Alex-Yakubovsky

I suppose esbuild-plugin-pnp conflicts with Vite's internal esbuild plugin.

sapphi-red avatar May 28 '22 17:05 sapphi-red

I think there is a conflict with #1688

Shouldn't we use esbuild-plugin-pnp directly like the rollup plugins instead of the above commit? It may also be related to #6493

black7375 avatar Jun 16 '22 01:06 black7375

The warning is about the tsconfig for local files, not optimized dependencies. So neither optimizeDeps config option nor optimizer changes are related.

Local files are processed by vite:esbuild plugin here.

Vite loads tsconfigs itself and passes compilerOptions to esbuild.transform.

However, for vite.config.ts Vite uses esbuild.build directly, which means that ESBuild has to locate tsconfigs on its own — and fails in case of Yarn PnP.

So the warning actually is purely about vite.config.ts bundling, and does not affect application code.

Note that adding esbuild-plugin-pnp here won't help. ESBuild Plugin API does not allow customization of tsconfig loading. The only possible fix on Vite side for now is to use the same approach that the main bundling process uses — that is, use ESBuild transform API and load tsconfigs beforehand.

Here's a suggestion for adding config loading customization via plugin API I've submitted in ESBuild repo some time ago https://github.com/evanw/esbuild/issues/2095

swandir avatar Jun 27 '22 01:06 swandir

Oh, I see. Thank you for your kind explanation.

black7375 avatar Jun 27 '22 02:06 black7375

I'm not sure if an issue in yarn3 justifies changing how Vite loads vite.config.ts. We can't easily use the transform API since we have to bundle all relative imports as well, but still worth exploring is one is up for it. I'll mark this as an upstream bug at the meantime.

bluwy avatar Jul 03 '22 02:07 bluwy

By the way, to avoid the error (even if it doesn't affect anything), you can run yarn unplug @tsconfig/<whatever>, and then change extends to ./.yarn/unplugged/<folder>/node_modules/@tsconfig/<package>/tsconfig.json.

ravenclaw900 avatar Jul 26 '22 20:07 ravenclaw900

esbuild just added support for PnP with version 0.15.0: https://github.com/evanw/esbuild/releases/tag/v0.15.0! However, when I force vite to use [email protected] via package.json#resolutions, I still see the warning. 🤔

jonaskuske avatar Aug 10 '22 17:08 jonaskuske