These are chat archives for webpack/webpack/dev

10th
Dec 2017
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:33

Hey everyone!
I've been looking into how loaders work, with a very specific goal in mind.
I would like to be able to do something like this:
import {arbitrary, objects} from './styles.css';
I thought it should be easy to achieve with loaders, since css-loader already does something similar in module:true mode.
But as far as I can tell, that solution is not generic, and instead the style-loader looks for certain props to then expose css-module data.

Any advice on how I should approach this problem? :/

Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:34
@ZeeCoder My understanding was that you just need to convert your css file into javascript that exports an object.
So, for example you loader could return this string:
"module.exports = { arbitrary: 'foo', objects: [{}, {}] }"
And then you should be able to import it in the way you described.
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:35
I've done that, but it doesn't work with css and style loader. my output disappears
Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:35
What is the goal?
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:36
To be able to import JS objects generated by loaders that analysed the imported CSS
Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:36
Here is a loader my friend made that does the same: https://github.com/monvillalon/sass-values-loader
He generates ES6 directly though, looking at the source.
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:38
hmm maybe I should try es6, I'm using webpack 3 actually
Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:38
Either should work. Perhaps there is some other problem.
Did you try doing console.log(require("!!your-loader!./some-file.css"))?
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:40
I've just set up a new project and added my custom loader to css
Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:41
Is it being invoked?
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:41
I've just tried returning this: module.export = {hey: "ho"} from my loader, but it just got injected to the header by style-loader, and the returned value is an empty object
Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:41
So module.export = { hey: "ho" } ended up in a <styles> tag?
Without knowing what you're trying to do exactly it's hard to say, but I think that more complicated work is required if you want to both export styles and JS from the same file... Perhaps using a plugin. I'm not 100% sure.
When I use sass-values-loader the file is actually used multiple times.
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:44

yeah.
Which is expected, since that's what style-loader does if it gets a string.
It thinks it's css, which it needs to inject.
If I return an object from my loader then compilation fails alltogether.

It only seems to work for the css-loader, which I think returns a locals object which is handled as an exception in style-loader.

Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:44
So we can do:
import styles from "./some-stylesheet.scss"
import constants from "!!sass-values-loader!./some-stylesheet.scss"
I don't know how to help if you want to build such a thing, but I'd recommend looking into how style-loader handles its modules: true arg.
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:47

I did, so it's css-loader that has the modules flag, and style-loader recognises it and handles it specially.
Which is odd, because I thought these loaders would be generic, but instead they seem tightly coupled to me.

It would be nicer to have a more generic solution, where multiple loaders could operate on the same CSS file, and still expose their own thing.

Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:48
What exactly are you trying to do though?
Make an alternative to css-modules?
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:51

I have a container-query solution, which works this way:
a postcss plugin extracts information from the CSS file, and assembles a json.
Then a runtime JS object can be created which is given that JSON.

This is basically how I imagine it:

import queryData from './Component.pcss';

const element = document.getElementById('Component');
const containerInstance = new Container(component, queryData);

https://github.com/ZeeCoder/container-query

Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:54
Hm, yeah. Interesting. I don't know how css-loader works, but it might be sufficient to just explicitly load it in when you need it (like we do for sass-values-loader).
Obvs. would be better if you could just drop it in and replace the module: true behaviour. Sorry I can't help more.
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:54

Currently instead I'm just using the postcss-plugin with the postcss-loader, which creates the JSON aside the CSS file, then import it in webpack, like so:

require('./Component.pcss');
const queryData = require('./Component.pcss.json');

const element = document.getElementById('Component');
const containerInstance = new Container(component, queryData);

This is not only uglier, but triggers the build twice for every change in the CSS, because:
1) the css change generates a new JSON file through the postcss-loader
2) the json change triggers a new js build

Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:55
Wouldn't you need to run 1 & 2 even if it was going through the same loader?
Ah, but it would need to build the file and all its dependencies I guess.
I see the problem.
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:55
yeah.

Not sure what the right forum would be to talk about this though.
I think the way the style-loader works with the css-loader is highly dependent on the icss "standard": https://github.com/css-modules/icss
Which is in this case a bit limiting though.

Just in general seems like CSS-modules enjoys some priviliges others can't :/

Anyway, thanks for the help @rhys-vdw !
Rhys van der Waerden
@rhys-vdw
Dec 10 2017 02:59
Best of luck. :)
Viktor Hubert
@ZeeCoder
Dec 10 2017 02:59
I wasn't sure if I have a real problem or not, but I guess it's just not as simple as I thought :)