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

ERR_UNKNOWN_FILE_EXTENSION with css inside dependency #3862

Closed
6 tasks done
silverwind opened this issue Aug 2, 2023 · 10 comments · Fixed by #3880
Closed
6 tasks done

ERR_UNKNOWN_FILE_EXTENSION with css inside dependency #3862

silverwind opened this issue Aug 2, 2023 · 10 comments · Fixed by #3880
Labels
enhancement New feature or request

Comments

@silverwind
Copy link
Contributor

silverwind commented Aug 2, 2023

Describe the bug

When a npm dependency imports CSS, vitest's resolution fails with node error ERR_UNKNOWN_FILE_EXTENSION, even with the css option is enabled. The same works fine when the imported CSS file is first-party, so I think it's an error in vitest's module resolution. vite is able to build this fine, but vitest fails.

Previous suggestions to this problem were to use deps.inline, but as this has now been deprecated, I'm looking for better solutions which ideally do not involve whitelisting the dependencies that have CSS imports.

Reproduction

Repo: https://github.com/silverwind/vitest-css.
Dependency vitest-css-test-module is published to npm from the subdirectory.

git clone https://github.com/silverwind/vitest-css
cd vitest-css
npm install
npx vitest

Will fail with

 DEV  v0.34.1 vitest-css

 ❯ index.test.js (0)

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  index.test.js [ index.test.js ]
TypeError: Unknown file extension ".css" for node_modules/vitest-css-test-module/index.css
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'ERR_UNKNOWN_FILE_EXTENSION' }
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

 Test Files  1 failed (1)
      Tests  no tests
   Start at  14:30:10
   Duration  343ms (transform 36ms, setup 0ms, collect 0ms, tests 0ms, environment 0ms, prepare 99ms)

System Info

System:
    OS: macOS 13.4
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 84.09 MB / 16.00 GB
    Shell: 5.9 - /usr/local/bin/zsh
  Binaries:
    Node: 20.3.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.7.1 - ~/.npm-global/bin/npm
    pnpm: 8.6.2 - ~/.npm-global/bin/pnpm
  Browsers:
    Chrome: 113.0.5672.126
    Chrome Canary: 114.0.5686.0
    Firefox Nightly: 113.0a1
    Safari: 16.5
  npmPackages:
    vitest: 0.34.1 => 0.34.1

Used Package Manager

npm

Validations

@sheremet-va
Copy link
Member

Previous suggestions to this problem were to use deps.inline, but as this has now been deprecated, I'm looking for better solutions which ideally do not involve whitelisting the dependencies that have CSS imports.

Use deps.optimizer.

@silverwind
Copy link
Contributor Author

silverwind commented Aug 2, 2023

Use deps.optimizer.

Such an option does not exist. You mean optimizeDeps.disabled? I just tried it, same error. I also tried optimizeDeps.exclude, also changes nothing.

I think this is defintely a bug in vitest because the resolution works with vite.

@sheremet-va
Copy link
Member

sheremet-va commented Aug 2, 2023

Such an option does not exist

https://vitest.dev/config/#deps-optimizer

I think this is defintely a bug in vitest because the resolution works with vite.

This is not a bug, but a performance optimization. We cannot run all dependencies inside vite-node because your tests will be running x10 slower. If you want identical handling, use browser tests. Vitest does a lot of hacks to be performant, but we cannot handle all cases.


I just want to elaborate on the idea with the optimizer (currently in the reproduction it doesn't change anything). When .css is used in a dependency, it is usually some kind of a components library. For performance reasons, it's always better to bundle it (the reason is described in the documentation).

These files are then imported using the native Node.js mechanism (not the vite-node wrapper that is used for source code, it is very slow on large amounts of files). Unfortunately with assets (.png, .svg, ...) and .css files it doesn't really work that well. You can still use deps.server.inline to inline only needed dependencies.

Vitest will provide an alternative option to allow the processing of specific files without inlining them (so, they will still run in Node.js, and not in slow vite-node):

deps: {
  optimizer: {
    web: {
      transformAssets?: boolean
      transformCss?: boolean
      transformGlobPattern?: string[]
    }
  }
}

@sheremet-va sheremet-va added enhancement New feature or request and removed pending triage labels Aug 2, 2023
@silverwind
Copy link
Contributor Author

silverwind commented Aug 2, 2023

So what would you put into deps.optimizer to fix the reproduction? I find the docs on this option hard to understand, I tried this:

    deps: {
      optimizer: {
        web: {
          disabled: true,
        },
      },
    },

Is it possible to fix without specifying the name of the dependency?

This is not a bug, but a performance optimization. We cannot run all dependencies inside vite-node because your tests will be running x10 slower.

I don't really mind slower performance if the outcome is correct and works resolves like vite.

Ideally a CSS import would alter document.styleSheets in the fake DOM, but I'm not even asking for that, I just want it to silently ignore these CSS imports.

@sheremet-va
Copy link
Member

sheremet-va commented Aug 2, 2023

I tried this

There is no "disable" option in the optimizer. It's called enabled and it overrides optimizeDeps.disable. Also, I said in my previous message:

I just want to elaborate on the idea with the optimizer (currently in the reproduction it doesn't change anything).

I don't really mind slower performance if the outcome is correct and works resolves like vite.

I do mind it :)

As I said before, you can still use server.deps.inline for your usecase if you don't care about performance.

@silverwind
Copy link
Contributor Author

silverwind commented Aug 2, 2023

There is no "disable" option in the optimizer. It's called enabled and it overrides optimizeDeps.disable

Would you mind posting a full config for the repro that works? The vitest docs link to vite's optimizeDeps which shows a disabled. This is the latest thing I tried:

import {defineConfig} from "vitest/config";

export default defineConfig({
  test: {
    environment: "jsdom",
    deps: {
      optimizer: {
        web: {
          disabled: true,
        },
      },
    },
  },
});

@silverwind
Copy link
Contributor Author

silverwind commented Aug 2, 2023

Generally, I do think removing this implicit CSS import and moving it to an explicit @import in the consumer's CSS is the way to go as I see value in having such frontend JS importable in Node. Still I would be interested in how it can be solved with deps.optimizer, I tried many variations of the supposed config like with empty include array but nothing works. The docs on this option are really lacking, they don't specify what options web or ssr can hold, some examples would be great.

@sheremet-va
Copy link
Member

Generally, I do think removing this implicit CSS import and moving it to an explicit @import in the consumer's CSS is the way to go as I see value in having such frontend JS importable in Node. Still I would be interested in how it can be solved with deps.optimizer, I tried many variations of the supposed config like with empty include array but nothing works. The docs on this option are really lacking, they don't specify what options web or ssr can hold, some examples would be great.

There is an open issue: #3524

Would you mind posting a full config for the repro that works? The vitest docs link to vite's optimizeDeps which shows a disabled. This is the latest thing I tried:

You are correct that currently it will not work because we always inline optimized dependencies which is a bug, but the working config would be:

{
  test: {
    css: {
      include: /.+/,
    },
    server: {
      deps: {
        inline: [
          /vitest-css-test-module/,
        ]
      }
    }
  },
}

@silverwind
Copy link
Contributor Author

Okay, feel free to close unless you want to keep it open for the mentioned bug. I will definitely remove these CSS imports as I don't feel like relying on such advanced/unstable config options is a good idea.

I do wonder one thing thought: What if the module would export a .jsx file? Node can't load these either. Would vitest fail similarily? I think the problem is not directly related to JS, but all things node can't load (but vite can).

@sheremet-va
Copy link
Member

Would vitest fail similarily? I think the problem is not directly related to JS, but all things node can't load (but vite can).

Yes, you need to add those files to deps.optimize so they are transformed to JS before Vitest can consume them. Vite does this automatically by crawling imports, but we cannot do that because not all dependencies should be bundled and we also cannot reload the process if optimized dependency is out of date like Vite does by reloading the page.

Usually, Vite plugins add those dependencies manually to optimizeDeps.

I will definitely remove these CSS imports as I don't feel like relying on such advanced/unstable config options is a good idea.

Vitest will start processing assets and CSS in web transform mode in the --experimentalVmThreads runner in the near future. --threads and --child_process are harder to implement because Node.js loader is very experimental.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
2 participants