FredKSchott / snowpack

ESM-powered frontend build tool. Instant, lightweight, unbundled development. ✌️
https://www.snowpack.dev
MIT License
19.48k stars 921 forks source link

[FEATURE] Support multiple extensions in plugin's resolve config #2832

Open BPScott opened 3 years ago

BPScott commented 3 years ago

The problem that you want to solve.

Somewhere between a bug and a feature.

Extracted from https://github.com/snowpackjs/snowpack/pull/2707#issuecomment-788429446 so it doesn't get lost.

I'm trying to define a loader plugin for sass files that contains the resolve config: resolve: { input: ['.scss', '.sass'], output: ['.module.css']} (and aside from that it's identical to the official sass plugin). I'm investigating snowpack in an existing project where the rule is "*.scss files get ran through css modules". Rather than rename all my .scss files to .module.scss, I'd like to configure snowpack to treat all scss files as needing to be ran through snowpack's built-in modules stuff to avoid too much churn.

Here's the reproduction.

When running with that plugin I get a 500 error when loading http://localhost:8080/dist/App.module.css.proxy.js (which is the compiled output for src/App.scss). The error is:

[16:21:46] [snowpack] Build Result Error: There was a problem with a file build result.
[16:21:46] [snowpack] TypeError: Cannot read property 'code' of undefined
    at FileBuilder.getProxy (/Users/ben/src/github.com/BPScott/snowpack-test/compile-to-module-css/node_modules/snowpack/lib/index.js:111801:48)
    at loadUrl (/Users/ben/src/github.com/BPScott/snowpack-test/compile-to-module-css/node_modules/snowpack/lib/index.js:130547:57)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
    at async handleRequest (/Users/ben/src/github.com/BPScott/snowpack-test/compile-to-module-css/node_modules/snowpack/lib/index.js:130627:28)
[16:21:46] [snowpack] TypeError: Cannot read property 'code' of undefined
[16:21:46] [snowpack] [500] /dist/App.module.css.proxy.js

Your take on the correct solution to problem.

I would expect resolve: { input: ['.scss', '.sass'], output: ['.module.css']} to work and that the contents of a scss file loaded by a plugin containing such code should be processed by css modules.

drwpow commented 3 years ago

You can name files .module.scss and they should be processed as CSS Modules (you can also have normal .sass in the same project that will output global styles).

Just so I understand your usecase a bit better, is it possible to use the .module.scss naming structure? Or is there some other criteria for determining which gets CSS Modules treatment, and which don’t?

As you’ve discovered our CSS Module detection currently happens before the plugins get run, and we don’t have a way to dynamically inject that behavior from a plugin. But perhaps we could add some kind of hook or interface for this based on your needs.

BPScott commented 3 years ago

Just so I understand your usecase a bit better, is it possible to use the .module.scss naming structure? Or is there some other criteria for determining which gets CSS Modules treatment, and which don’t?

I'm trying to integrate snowpack into a large existing application where the convention is that that all .scss files are ran through css modules (in the very very rare case where global styles are desired we use :global {}). Renaming all our .scss files to be .module.scss would work, though I was trying too maintain existing conventions while investigating snowpack as I don't fancy renaming and updating imports for ~1600 scss files at this point in the investigation :)

I think I can work around this by using output: ['.js', '.css'] and handling css modules within the plugin - which might be more performant for my use-case anyway as already need to do sass then postcss transforms.

BPScott commented 3 years ago

Multiple extensions should work in 3.1.1 thanks to #2593. The "hooking into css-modules" thing is a slightly different case.

I'll update my stuff and shall hopefully update this.

FredKSchott commented 3 years ago

Yea, it could make sense to add a global config to define your own regex/glob to match CSS modules (for your use-case that would just be *.scss). Definitely not on by default, but useful for the people who need it.