How to Have HTML-Webpack-Plugin Generate <Style> Elements from CSS

Is it possible to have html-webpack-plugin generate style elements from css?

Sounds like the exact use case for these html-webpack plugins:

  • html-webpack-inline-source-plugin:

    It allows you to embed javascript and css source inline.

  • style-ext-html-webpack-plugin: an alternative to the previous one.

    If you use HtmlWebpackPlugin and ExtractTextPlugin in your Webpack builds to create HTML <link>s to external stylesheet files, add this plugin to convert the links to `~ elements containing internal (sometimes incorrectly called 'in-line') CSS.

  • html-inline-css-webpack-plugin: an alternative to style-ext-html-webpack-plugin.

    Convert external style sheet(<link rel="stylesheet"/>) to internal style sheet(<style>...<style/>). Require mini-css-extract-plugin and html-webpack-plugin

The last 2 HTML webpack plugins depend on one of the following webpack plugins:

  • Extract Text Plugin:

    Extract text from a bundle, or bundles, into a separate file. [...] It moves all the required *.css modules in entry chunks into a separate CSS file. So your styles are no longer inlined into the JS bundle, but in a separate CSS file (styles.css).

  • mini-css-extract-plugin: same as Extract Text Plugin, but for webpack v4.

    This plugin extracts CSS into separate files.

How to force webpack to put the plain CSS code into HTML head's style tag?

I've done this before only using style-loader that by default will add your css as style inline at <head> tag. This won't generate any output css file, this just will create one/multiple style tags with all you styles.

webpack.config.js

module.exports = {
//... your config

module: {
rules: [
{
test: /\.scss$/, // or /\.css$/i if you aren't using sass
use: [
{
loader: 'style-loader',
options: {
insert: 'head', // insert style tag inside of <head>
injectType: 'singletonStyleTag' // this is for wrap all your style in just one style tag
},
},
"css-loader",
"sass-loader"
],
},
]
},

//... rest of your config
};

index.js (entry point script)

import './css/styles.css';

Load CSS with link tag and HTMLWebpackPlugin

In your case chaining css-loader & style-loader are not relevant.

css-loader loads css and passes down an object with a selectors map + the css string.
style-loader injects the css and returns the same object.

Therefore, you get [Object object].

Try to use only file-loader, which returns a string with the path to a static file, and emits the file to outputPath.

<link href="!!file?esModule=false!~@internal-scope/package-name/dist/some.css" rel="stylesheet" id="important-id">
// ---------^ these !! are important to prevent from running rest of the loaders which are suitable from your config.

BTW, why you are trying to inject it directly in the template and not import it in js and let HTMLWebpack do it's thing? (it is by default injects link tag to emitted css files)

Can webpack package CSS into HTML as style/style?

Yes it can. Please take a look at style-ext-html-webpack-plugin webpack plugin.

The description on their readme is pretty good.

This is an extension plugin for the Webpack plugin HtmlWebpackPlugin -
a plugin that simplifies the creation of HTML files to serve your
webpack bundles.

The raw HtmlWebpackPlugin can bundle CSS assets as elements if
used in conjunction with ExtractTextPlugin. This extension plugin
builds on this by moving the CSS content generated by
ExtractTextPlugin from an external CSS file to an internal
element.

This plugin is used in combination with HtmlWebpackPlugin and ExtractTextPlugin plugins.

CSS not included in index.html

I would probably consider using [MiniCssExtractPlugin][1] for this purpose which together with the HtmlWebpackPlugin, would allow you to get the link tag in your HTML files, pointing to your CSS files.

I am quoting from the HtmlWebpackPlugin [documentation][2]:

If you have any CSS assets in webpack's output (for example, CSS extracted with the MiniCssExtractPlugin) then these will be included with tags in the element of generated HTML.

You can also check out this SO [answer][3] that suggests some additional ways to inline CSS in HTML.

If you want, you can share a link to your project, and I can try to assist you more specifically.
[1]: https://webpack.js.org/plugins/mini-css-extract-plugin/
[2]: https://webpack.js.org/plugins/html-webpack-plugin/
[3]: https://stackoverflow.com/a/50770543/6098812

Inline Styling and html-webpack-plugin

I think there's a way that you can achieve you goal by just simply using interpolation syntax of html-webpack-plugin without having to using html-loader (likely getting conflicted).

Here's the few steps:

  • Change your template to use interpolation syntax to require the image:
<div style="background-image: url(<%= require('assets/imgs/Portfolio/AFTO.png') %>" />
  • Disable esModule options of file-loader to make require function work without having to .default:

webpack.config.js

{
loader: 'file-loader',
options: {
// ...
esModule: false,
}
}
  • Finally, we might need to remove html-loader to avoid interpolation syntax not getting compiled

Injecting css file into head of html file generated using HtmlWebpackPlugin

I have injected the external stylesheet into the generated html page using react-helmet. First, I removed the css-loader from the webpack.config.js and the import ./bundle.css from my module. I edited my .babelrc to change the bundlePath of the css to the build directory.

Then I added:

import Helmet from 'react-helmet';

const cssLink = {
rel: 'stylesheet',
type: 'text/css',
href: './bundle.css',
};

I added the following to my root component:

 <Helmet link={[cssLink]} />

The component now looks like:

function HelloWorld() {
return (<h2 className={redClass}>
<Helmet link={[cssLink]} />
<LoremIpsum />
</h2>);
}

Take a look at the .babelrc and index.js



Related Topics



Leave a reply



Submit