webpack-contrib / mini-css-extract-plugin

Lightweight CSS extraction plugin
MIT License
4.66k stars 388 forks source link

Support insertInto option similar to style-loader? #370

Closed brophdawg11 closed 4 years ago

brophdawg11 commented 5 years ago

Would this package be open to adding support for an insertInto option similar to what style-loader supports, which allows clients to specify a selector for the DOM node into which they want link tags inserted inside of? By default, it would be the head.

We have a scenario where some orchestrated content being injected into an existing app inside of <body> and that content contains it's main app.css file. However, any async-loaded CSS files break the expected cascade because they go into <head>. So basically, we end up with a DOM such as:

<html> 
  <head>
    ...
    <!-- Injected asyncronously -->
    <link rel="stylesheet" href="async.css" />
  </head>
  <body>  
    ...
    <!-- Orchestrated content rendered server side on page load -->
    <div class="orchestrated-content">
        <link rel="stylesheet" href="app.css" />
        ...
    </div>
    ...
  </body>
</head>

When the normal order should be app.css -> async.css.

I'm planning to get a PR together, but the solution is fairly straightforward it seems. I've modified mainTemplate.hooks.requireEnsure.tap locally to essentially generate JS code that does the following, and it seems to work without issue:

// Assuming no config option passed
var parent = document.querySelector("head");
if (parent) { parent.appendChild(linkTag); }
else { reject("Invalid parent element"); }

// If the user passes config option: { insertInto: ".style-container" }
var parent = document.querySelector(".style-container");
if (parent) { parent.appendChild(linkTag); }
else { reject("Invalid parent element"); }
alexander-akait commented 5 years ago

Yep, we can implement this :+1: so it is feature

ScriptedAlchemy commented 5 years ago

@brophdawg11 would the style need to be injected in the right order as well? so async.css go under app.css

jens-duttke commented 5 years ago

A functionality like the insertAt of style-loader would make more sense, since you can specify the position even more exact.

I have the use-case that I have a large header (different device- and SEO-specific meta tags which are less important than the CSS references). So I want to inject the CSS-Links directly after the title-tag.

Using

    insertAt: {
        after: 'title'
    }

that would be easily possible.

To achive the usecase of @brophdawg11, what about:

    insertAt: {
        appendTo: '.style-container'
    }

?

I think appendTo, before and after, would cover all use-cases.

JuliaUsanova commented 5 years ago

Hey, thank you for the awesome plugin! really waiting for this feature, when are you planning to release it?

brophdawg11 commented 5 years ago

Sorry for the delay - I just updated the PR (https://github.com/webpack-contrib/mini-css-extract-plugin/pull/371) with the new approach suggested by @evilebottnawi

jens-duttke commented 4 years ago

Is there a chance to get an option, to insert the <link> tags right after the <title> tag? Or should I create a separate issue for that?

alexander-akait commented 4 years ago

https://github.com/webpack-contrib/mini-css-extract-plugin/pull/609