How can I return the value of a default export within a webpack loader?

26 views Asked by At

I would like to author my styles as regular objects and pass them to postcss (with postcss-js as a parser) to generate css.

Here is the relevant portion from my webpack config. This is an excerpt from the module.rules array

{
  "test": /\.css.ts$/,
  "use": [
    "style-loader",
    {
      "loader": "css-loader",
      "options": {
        "importLoaders": 1
      }
    },
    {
      "loader": "postcss-loader",
      "options": {
        "implementation": "postcss",
        "postcssOptions": {
          "parser": "postcss-js"
        }
      }
    },
    "ts-loader"
  ]
}

And here is the file that is being processed by the webpack rule in question

Button.css.ts

import { Button } from '../styles/Button.styles';

const styles = {
    '.Button': Button
}
export default styles;

Button.styles.ts

export const Button: CSSObject = {
    display: 'inline-flex'
}

Looking at postcss-js' documentation, it appears that it is expecting just a plain object. Here is an example lifted directly from their documentation

const postcss = require('postcss')
const postcssJs = require('postcss-js')

const style = {
  top: 10,
  '&:hover': {
    top: 5
  }
};

postcss().process(style, { parser: postcssJs }).then( (result) => {
  result.css //=> top: 10px;
             //   &:hover { top: 5px; }
})

But ts-loader outputs what the typescript compiler emits for that single file, import declarations and all.

I believe I need an intermediate loader between ts-loader and postcss-loader that evaluates what ts-loader returns, extracts the value of the default export, and returns that.

I can sort of get it working by changing the postcss loader in my rule to this

{
  "loader": "postcss-loader",
  "options": {
    "implementation": "postcss",
    "postcssOptions": {
      "parser": function(_, file) {
        const code = require(file.from);
        const postcssjs = require('postcss-js');
        const parsed = postcssjs.parse(code.default);
        return parsed;
      }
    }
  }
}

With this, the hot module reloading doesn't work since the require is happening outside of webpack's context.

I have also tried val-loader, but I would rather not have to format my exports in a particular way (exporting a function that returns an object with a 'code' key).

0

There are 0 answers