GithubHelp home page GithubHelp logo

runjuu / html-inline-css-webpack-plugin Goto Github PK

View Code? Open in Web Editor NEW
79.0 3.0 21.0 730 KB

☄️ A webpack plugin to convert external stylesheets into embedded stylesheets

Home Page: https://www.npmjs.com/package/html-inline-css-webpack-plugin

License: MIT License

TypeScript 100.00%
webpack webpack4 webpack-plugin inline-css inline-styles html-webpack-plugin mini-css-extract-plugin embedded-stylesheet document-stylesheet webpack5

html-inline-css-webpack-plugin's Introduction

html-inline-css-webpack-plugin

MIT Licence PRs Welcome Total downloads npm version

Convert external stylesheet to embedded stylesheet, aka document stylesheet.

<link rel="stylesheet" /> => <style>...<style/>

Require mini-css-extract-plugin and html-webpack-plugin

Install

NPM

npm i html-inline-css-webpack-plugin -D

Yarn

yarn add html-inline-css-webpack-plugin -D

Minimal example

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HTMLInlineCSSWebpackPlugin = require("html-inline-css-webpack-plugin").default;

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    }),
    new HtmlWebpackPlugin(),
    new HTMLInlineCSSWebpackPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader"
        ]
      }
    ]
  }
}

Config

interface Config {
  filter?: (fileName: string) => boolean
  styleTagFactory?: (params: { style: string }) => string
  leaveCSSFile?: boolean
  replace?: {
    target: string
    position?: 'before' | 'after'
    removeTarget?: boolean
  }
}

filter(optional)

filter?: (fileName: string) => boolean

Return true to make current file internal, otherwise ignore current file. Include both css file and html file name.

example
...
new HTMLInlineCSSWebpackPlugin({
  filter(fileName) {
    return fileName.includes('main');
  },
}),
...

styleTagFactory(optional)

styleTagFactory?: (params: { style: string }) => string

Used to customize the style tag.

example
...
  new HTMLInlineCSSWebpackPlugin({
    styleTagFactory({ style }) {
      return `<style type="text/css">${style}</style>`;
    },
  }),
...

leaveCSSFile(optional)

if true, it will leave CSS files where they are when inlining

replace(optional)

replace?: {
  target: string
  position?: 'before' | 'after' // default is 'before'
  removeTarget?: boolean // default is false
}

A config for customizing the location of injection, default will add internal style sheet before the </head>

target

A target for adding the internal style sheet

position(optional)

Add internal style sheet before/after the target

removeTarget(optional)

if true, it will remove the target from the output HTML

Please note that HTML comment is removed by default by the html-webpack-plugin in production mode. #16

example
<head>
    <!-- inline_css_plugin -->
    <style>
        /* some hard code style */
    </style>
</head>
...
  new HTMLInlineCSSWebpackPlugin({
    replace: {
      removeTarget: true,
      target: '<!-- inline_css_plugin -->',
    },
  }),
...
output:
<head>
    <style>
        /* style from *.css files */
    </style>
    <style>
        /* some hard code style */
    </style>
</head>

html-inline-css-webpack-plugin's People

Contributors

dependabot[bot] avatar pjetrucha avatar runjuu avatar sluukkonen avatar stevenzwzhai avatar tristyb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

html-inline-css-webpack-plugin's Issues

Split CSS across multiple files

I have a couple of .scss files and I want to specify which files are inlined in which .html files. How do I do that? Right now all entry .scss files are inlined in every result .html file, which is not what I want. Here's the relevant plugin config:

new MiniCssExtractPlugin(),
...files.map(file => new HtmlWebpackPlugin({
    template: `src/pug/${file}.pug`,
    filename: `${file}.html`,
    templateParameters: {
        filename: file
    },
    inject: false
})),
new HTMLInlineCSSWebpackPlugin(),

Even though I did inject: false your plugin still injects every entry style file into the <head>.

Can not inline multiple css

When there are multiple css in the page that need to be inlined,a part of css will not be inlined。
I readed the source code in v4.ts, maybe the problem is here:

private prepareCSSStyle(data: BeforeAssetTagGenerationData) {
    data.assets.css.forEach((cssLink, index) => {
      if (this.isCurrentFileNeedsToBeInlined(cssLink)) {
        const style = this.getCSSStyle({
          cssLink,
          publicPath: data.assets.publicPath,
        })

        if (style) {
          if (this.cssStyleMap.has(data.plugin)) {
            this.cssStyleMap.get(data.plugin)!.push(style)
          } else {
            this.cssStyleMap.set(data.plugin, [style])
          }
          // prevent generate <link /> tag
          data.assets.css.splice(index, 1)
        }
      }
    })
  }

for example:
image

the element in the middle is deleted, it results in a part of css cannot be inlined.

Allow usage of nonce-attributes on generated style tag (CSP Level 2)

I want to use Content Security Policy Level 2 on my website. This requires me to add a 'nonce' attribute to all <style> tags.

I'm currently using this plugin to inline some css and of course it does not produce a nonce-attribute which causes the generated <style> tag to fail.

What I would love to see is one of the following options:

  1. A nonce configuration option in the plugin that I can set to any value and which is then rendered as a "nonce"-attribute on the generated style tag. I would probably use it to inject a dummy value which I would then replace server side, but in other setups this might be different. OR:
  2. An option to omit the <style> tag itself and replace the token only with the css content. This would allow me to move the <style> tag with the nonce attribute to the HTML template directly. OR:
  3. An option to specify a function as the 'target' which would receive the HTML and the CSS declarations as parameters and would return the rendered result, allowing for custom replacement logic.

Any of these would help a lot in this and similar scenarios. Please let me know what you think and if you have a preference for any option.

Multi-entry setup

Hello,

Is there a support for multi-entry html?
Right now I have multiple HtmlWebpackPlugin instances for each html file:

    plugins: [
      new MiniCssExtractPlugin({
        filename: '[name].css',
        chunkFilename: "[id].css"
      }),
      ...inputFiles.map(path => new HtmlWebpackPlugin({
        inject: true,
        chunks: [path],
        filename: `${path}.html`,
        template: `src/${path}.html`,
      })),
      new HTMLInlineCSSWebpackPlugin({
        leaveCSSFile: false,
      }),

But the injected CSS is not right because all html files contains all css tyles.

filter function must return 'true' for css file as well as the output html file

If I understand the code correctly, the filter function is not only called for the CSS files to decide if they should be inlined or not, but also for the target .html-file in which the styles should be injected.

I don't think this is very intuitive and at the very least it should be mentioned in the documentation. I had to debug through the plugin to find out, why my CSS does not get inlined.

TypeError: html.replace is not a function

Thanks for the plugin, but unfortunately I'm getting this error when using it.

emitting html-inline-css-webpack-plugin(node:946) UnhandledPromiseRejectionWarning: TypeError: html.replace is not a function
    at Function.Plugin.addStyle (/Users/dimitris/blueground/website/node_modules/html-inline-css-webpack-plugin/build/index.js:28:25)
    at /Users/dimitris/blueground/website/node_modules/html-inline-css-webpack-plugin/build/index.js:76:35
    at Array.forEach (<anonymous>)
    at /Users/dimitris/blueground/website/node_modules/html-inline-css-webpack-plugin/build/index.js:75:40
    at Array.forEach (<anonymous>)
    at Plugin.process (/Users/dimitris/blueground/website/node_modules/html-inline-css-webpack-plugin/build/index.js:73:36)
    at /Users/dimitris/blueground/website/node_modules/html-inline-css-webpack-plugin/build/index.js:94:23
    at _err6 (eval at create (/Users/dimitris/blueground/website/node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:61:1)
    at emitHtmlPromise.then (/Users/dimitris/blueground/website/node_modules/html-webpack-plugin/index.js:313:11)
(node:946) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:946) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

package.json

"webpack": "^4.28.4",
"html-webpack-plugin": "^4.0.0-beta.5",
"html-webpack-inline-source-plugin": "^1.0.0-beta.2",

CSS files are deleted when using together with CopyWebpackPlugin

In my webpack config I have my main entry with HTML+CSS, and I want this CSS to be injected. I use simple

new HtmlInlineCSSWebpackPlugin()

for doing this, and it works fine.

I also have a CopyWebpackPlugin, which copies some third party lib, which includes HTML+CSS files in its assets.

These CSS files are removed when being copied. They are not removed if I use leaveCSSFile: true, but then the CSS file from main entry is not removed either.

I wonder why does this plugin deal with files from other plugin? But even if it does - I would expect these CSS get injected correctly in all HTML+CSS pairs it deals with. Currently it only REMOVES all of CSS files, without injecting them.

Guard against order with `html-webpack-plugin` always triggers

Hi,

It seems that the error about ordering this plugin after HTMLWebpackPlugin always triggers no matter the order:

const HtmlWebpackPlugin = require('html-webpack-plugin')
const HTMLInlineCSSWebpackPlugin = require('html-inline-css-webpack-plugin')
  .default
const path = require('path')

module.exports = () => {
  /** @type {import('webpack').Configuration} */
  const config = {
    entry: path.resolve(__dirname, './index.js'),
    mode: 'production',

    plugins: [
      new HtmlWebpackPlugin(),
      new HTMLInlineCSSWebpackPlugin(),
    ],
  }

  return config
}

Customize location of injection

Can we add a config option called something like replaceToken in order to determine where the inline styles get injected?

By default, I like the appending it to the very end of the head tag, but it would be nice to configure something like

   <head>
    <!-- inline_css_plugin -->
    <style>
        /* my app styles that get injected with server side rendiering */
    </style>
   </head>
new HTMLInlineCSSWebpackPlugin({
  replaceToken: '<!-- inline_css_plugin -->'      
}),

Webpack 5 support?

Hi, I'm trying to update a project to Webpack 5, but I'm getting an error I suspect is from this plugin:

Building(node:30678) [DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning: Compilation.assets will be frozen in future, all modifications are deprecated.
BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
	Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
	Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.
    at /Users/osmestad/Code/webclient-app/node_modules/html-inline-css-webpack-plugin/build/core/base-plugin.js:34:39
    at Array.forEach (<anonymous>)
    at PluginForHtmlWebpackPluginV4.BasePlugin.prepare (/Users/osmestad/Code/webclient-app/node_modules/html-inline-css-webpack-plugin/build/core/base-plugin.js:30:33)
    at /Users/osmestad/Code/webclient-app/node_modules/html-inline-css-webpack-plugin/build/core/v4.js:69:27
    at eval (eval at create (/Users/osmestad/Code/webclient-app/node_modules/tapable/lib/HookCodeFactory.js:74:10), <anonymous>:17:16)
    at new Promise (<anonymous>)
    at AsyncSeriesWaterfallHook.eval [as promise] (eval at create (/Users/osmestad/Code/webclient-app/node_modules/tapable/lib/HookCodeFactory.js:74:10), <anonymous>:4:8)
    at AsyncSeriesWaterfallHook.lazyCompileHook (/Users/osmestad/Code/webclient-app/node_modules/tapable/lib/Hook.js:154:20)
    at /Users/osmestad/Code/webclient-app/node_modules/html-webpack-plugin/index.js:187:84
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

Versions used:
"webpack": "5.4.0"
"html-webpack-plugin": "4.5.0",
"mini-css-extract-plugin": "1.3.0",
"html-inline-css-webpack-plugin": "1.9.0",

Is Webpack 5 support planned?

html-webpack-plugin 5 peer dep

Please, can you update the package.json definition to support html-webpack-plugin 5?

"peerDependencies": {
    "html-webpack-plugin": "^3 || ^4 || ^5"
},

Otherwise:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/html-webpack-plugin
npm ERR!   html-webpack-plugin@"5.0.0" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer html-webpack-plugin@"^3.0.0 || ^4.0.0" from [email protected]
npm ERR! node_modules/html-inline-css-webpack-plugin
npm ERR!   html-inline-css-webpack-plugin@"*" from the root project

Thank you.

Html minification doesn't work in production mode

Hi, I use html-webpack-plugin (4.5.0) for html minification in production mode. But html doesn't minify if html-inline-css-webpack-plugin is applied.
Could you please advise is it possible to fix it without installing extra plugins?

removeLinkTag should replace all occurences of the css chunk

I hit on this while trying to get css preload to work in chrome and load normally in other browsers as suggested in a comment at SO.

The bug can be traced to this line.

The solution is to pass 'gi' parameter to RegExp object to find and 'remove' all occurrences of the chunk that needs to be inlined.

I fixed it locally and works for me. Cheers!

duplicated css while using webpack-dev-server

Hello everyone,
I've got an issue while using html-inline-css-webpack-plugin with webpack-dev-server.

What happens is that, everytime I change something inside the project files and the watcher reloads the page, I see the <style> tag inside the index.html appended after the old styles while I would like it to replace them.

Here is my webpack.config.js

const path = require( "path" );
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
const TerserJSPlugin = require( "terser-webpack-plugin" );
const OptimizeCSSAssetsPlugin = require( "optimize-css-assets-webpack-plugin" );
const HTMLInlineCSSWebpackPlugin = require( "html-inline-css-webpack-plugin" ).default;
const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' );

const devMode = process.env.NODE_ENV === 'development';

module.exports = {

    entry: {
        index: path.join( __dirname, "src", "index.js" )
    },

    output: {
        path: path.join( __dirname, "dist" ),
        filename: "bundle.js"
    },

    devServer: {
        host: '0.0.0.0',
        port: 9000,
        writeToDisk: true
    },

    optimization: {
        minimizer: [new TerserJSPlugin( {} ), new OptimizeCSSAssetsPlugin( {} )],
    },

    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin( {
            filename: 'index.html',
            template: path.join( __dirname, "src", "index.html" ),
            inject: true
        } ),
        new MiniCssExtractPlugin( {
            filename: devMode ? '[name].css' : '[name].[hash].css',
            chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
        } ),
        new HTMLInlineCSSWebpackPlugin()
    ],

    module: {
        rules: [
            {
                test: /\.(png|jpe?g|gif)$/,
                exclude: /(node_modules)/,
                use: ['file-loader'],
            },
            {
                test: /\.svg$/,
                exclude: /(node_modules)/,
                loader: 'svg-inline-loader'
            },
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                use: {
                    loader: "babel-loader",
                    options: { presets: ["@babel/preset-env"] }
                }
            },
            {
                test: /\.styl$/,
                exclude: /(node_modules)/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: { hmr: devMode },
                    },
                    //"style-loader",
                    "css-loader",   // translates CSS into CommonJS
                    "stylus-loader" // compiles Stylus to CSS
                ]
            }
        ]
    }
};

And here is my index.js

import "./css/index.styl";
import "./css/graphics.styl";
import "./js/polyfills.js"
import "./js/resumee_manager.js"

Am I missing something or is it a bug?

Thank you in advance!

how to inline css file in async module?

The sync module is already inline to the html except async module.
when I start the project , the runtime show the error that the css file can not find.

how to inline css file in async module?

Asset optimization

The plugin works well, except for the fact that it includes CSS before optimizations are made.

I'm using OptimizeCSSAssetsPlugin, but that doesn't seem to have an effect on the result.
Is there a way to include optimized CSS?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.