4

I am trying to inject css file into my index.html. Currently my web pack does the following

  1. Converts my SASS into CSS
  2. Name the css file with hash (e.g. optionA-32d6cb.css)
  3. Places into ./dist folder

output of the folder structure:

- Dist
   - OptionA
        - optionA-hash.css

   - OptionB
        - optionB-hash.css

   - index.html //How to inject above css into this file?

I am new to HtmlWebpackPlugin my question is how do i inject above dynamic css files into the index.html? so that in the head section i have the following:

<link href="optionA-32d6cb.css" rel="stylesheet">
<link href="optionB-w2d6cb.css" rel="stylesheet">

My webpack.config.js file:

module.exports ={
entry: ['path_to_scss_file'],// SASSfile which contains import statment with wildcard to get all sass in given directory
output: {
    filename: "[name].min.js",
    path: path.resolve(__dirname, 'dist/'),
},
plugins:[
    new HtmlWebpackPlugin({
        template: './src/index.html'
    })
],
module:{
    rules: [
        {
            test: /\.scss$/,
            use: [
                {
                    loader: 'file-loader',
                    options:{
                        name:'[name]/[name]-[contenthash].css',
                    }
                },
                {
                    loader: 'sass-loader',
                    options: {
                      sassOptions: {
                             importer: globImporter(), 
                     //my sass files uses wildcard to import all sass files
                      },
                     },
                }
            ]
        }
    ]
}

2 Answers 2

2

You can use webpack-manifest-plugin to solve this issue which will create a manifest.json file inside the dist/ folder.

The manifest.json file will contain all the mappings like this

{
    "app.css": "css/app.dc4d6b6c65b4f5ff351e.css"
}

and then use HtmlWebpackPlugin, it will do the job every time you build, it will inject the correct files to index.html by referring to manifest.json

Refer https://github.com/anandgupta193/react-enterprise-starter-kit for an exact working implementation in webpack/webpack.common.config.js file. (use node 12.x to create a build in the starter kit)

enter image description here

Note: Remove your scripts and link tags from the index.html template, it will get injected automatically.

8
  • 1
    Thank you for the comment, how is the manifest.json file linked to the index.html. I dont see it on your code that part? i am able to generate the manifest on the dist which contains the reference as shown on your answer but its not linked to the index.html Commented Jul 30, 2020 at 8:47
  • HtmlWebpackPlugin automatically injects all assets (e.g. bundle.js, main.css) with the correct HTML tags. Please remove all scripts and link tags from your template HTML (refer: public/index.html in react-enterprise-starter-kit) Also, try to put inject: true option in your HtmlWebpackPlugin config object. Commented Jul 30, 2020 at 14:48
  • 1
    Still not working, can you try taking a look at my work please i created a link for you dropbox.com/t/kq47CfdoXAH0yW7G Commented Jul 30, 2020 at 15:41
  • There was an issue with the way you were processing your SCSS files. Scss files will need SCSS loader and CSS loader to finally convert it to CSS. Also, we need ExtractCssChunks plugin for properly creating CSS chunks. Please refer: dropbox.com/s/3cr4d40z9nkc1km/webpack-demo-solved.zip?dl=0 Please have a look at the code and let me know if this issue is solved. Commented Jul 30, 2020 at 19:21
  • Excellent work Anand thank you so much this is alot better but i want the css not to be combined into one? how can i have css per file name so its app.css and legacy.css? it should match based on the sass filenames? Commented Jul 30, 2020 at 20:55
0

The value of entry should be a path to a .js file: docs

And I recommend to use mini-css-extract-plugin. It will extract your CSS into separate files

Then your webpack.config could look like this:

'use strict';

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: {
    app: './main.js',
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].[hash].js',
  },
  module: {
    rules: [
      {
        test: /\.(scss|css)$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin(),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, './index.html'),
    }),
  ],
};

main.js

import './style.scss';

style.scss

body {
  background: #fefefe;
}

If you want your css files in a special path in your /dist folder, you can define options for the plugin

5
  • This wouldnt work for me because i am using globbing in my sass file to import all sass in given directory. I am currently using GlobImporter in my sass-loader, the above would fail as it wouldnt respect the wildcard (*) Commented Jul 30, 2020 at 11:30
  • You could replace your glob import with webpack's require.context: webpack.js.org/guides/dependency-management/#requirecontext Then this setup works and you don't have to explizit import every file
    – JohMun
    Commented Jul 30, 2020 at 11:41
  • Do you have an example of how to achieve this because i am new to webpack and not exactly sure how do i use this context as part of the webpack config Commented Jul 30, 2020 at 12:25
  • with require.context, you can import all you .scss files inside your script e.g.: main.js ``` const context = require.context('./styles', false, /\.scss$/); ```
    – JohMun
    Commented Jul 31, 2020 at 13:12
  • With require.context you can import all .scss inside you script: main.js const context = require.context('./styles', false, /\.scss$/); context.keys().map(context); here is also an example: webpack.js.org/guides/dependency-management/#context-module-api
    – JohMun
    Commented Jul 31, 2020 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.