other ways to use style-loader without bundling style-loader lib into every bundled style?

717 Views Asked by At

I was using webpack 5 to bundle my css styles, I wanted to include each module as is. without building it into a single file but I noticed that styles that were less than 1kb or even 5kb to 10kb are all above 30kb when I use style-loader.

I am assuming that is because of the style-loader code to inject the css into the body. I tried to use mini css extract but adding the css as link tags were not working for SPFX. so I ended up bundling it with file loader so it is a string and using a custom script to inject the styles.

export const attrReducer = (acc, cv) => cv[1] !== null || typeof cv[1] !== 'undefined'
  ? acc.concat(`${cv[0]}="${cv[1]}" `)
  : acc

export const mapToAttr = (o) => Object.entries(o).reduce(attrReducer, ``)

export const makeStyleTagLinkString = (props) => `<link ${mapToAttr(props)}></link>`
export const makeStyleTagString = ({ content, ...props }) => `<style ${mapToAttr(props)}>${content}</style>`

export const injectStyleTag = (props) => (url) => (
  !document.querySelector(`style[data-href="${url}"]`)
    ? document.head.insertAdjacentHTML('beforeend', makeStyleTagString({ props, href: url }))
    : null
);
export const injectStyleLinkTag = (props) => (url) => (content) => (
  !document.querySelector(`style[data-href="${url}"]`)
    ? document.head.insertAdjacentHTML('beforeend', makeStyleTagLinkString({ ...props, content: content }))
    : null
);

The above works well for my setup but this is really not what I wanted to ended up using, since webpack supposed to handle that for me.

Another issue is that style-loader was doing well for me, besides the problem of increasing the size of every css module, was to manipulate the style tag at build time depending on the content of the styles, this was useful for me cause I can apply the container query polyfill (or any other) based on the content of the css. ex:

{
  loader: "style-loader",
  options: {
    styleTagTransform: function (css, style) {
      css.indexOf('@container') > -1
        ? style.setAttribute('cqfill', '')
        : null;
      style.innerHTML = css;
      document.head.appendChild(style);
    },
  },
},

SPFX does have its own implementation for loading styles which I tried but it did not work well with the container-query-polyfill. Also no options to add anything to style tag or manipulate it in anyways.

export default class JQueryAccordionWebPart extends BaseClientSideWebPart<IJQueryAccordionWebPartProps> {
  protected onInit(): Promise<void> {
    SPComponentLoader.loadCss('https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.min.css');
    return super.onInit();
  }

  // ...
}

So the question is if there are other ways to export the css file as an assets and use either style loader as a separated lib to build the style or link tag? Or any other library that I can include that does this without having to use custom code.

1

There are 1 best solutions below

3
matthiasgiger On

Not sure if I understand all parts of the question. With the style-loader and mini-css-extract-plugin it's important to know that in development mode the styles will always be injected from a JS file as that's faster. Only in a production build will the styles end up in a separate CSS file (process.env.NODE_ENV === 'production').