Frenz
Frenz

Reputation: 747

Webpack: Copy a static html file and insert the generated bundle css file as link tag

I have a static html file that I want to get copied to the destination bundle folder. I'm currently using the CopyWebpackPlugin and the copy part works fine. However, I also want to inject the css bundle file that is generated to be injected as a link tag. For example if the generated bundle css file is 1018ada2.css then it should insert the below text into the head of the static html

<link href="/1018ada2.css?3a0aa923c93170e65ee4" rel="stylesheet">

Below is my webpack copy plugin code.

new CopyWebpackPlugin({
  patterns: [
    {
      from: './src/my-static.html',
      to: path.resolve(__dirname, '..', './build/my-static.html'),
    },
  ],
}),

How can I achieve this? Webpack already does this automatically for the index.html file, so I believe it should be possible.

Appreciate any help on this.

Upvotes: 1

Views: 679

Answers (1)

Frizzant
Frizzant

Reputation: 768

You could try something like this. This example enables the use of multiple HTML files, and will inject CSS & JS into the head of your HTML file automatically.

(The CSS file in the image is missing, since it is actually residing in another place in my project. So just adjust the path to where ever yours is.)

Folder structure:

enter image description here

package.json:

{
  "name": "htmlcsssync",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "private": true,
  "engines": {
    "node": ">=18.4.0"
  },
  "scripts": {
    "build": "webpack",
    "dev": "webpack serve --open"
  },
  "author": "Frizzant",
  "license": "MIT",
  "devDependencies": {
    "add": "^2.0.6",
    "css-loader": "^6.7.1",
    "html-loader": "^4.1.0",
    "html-webpack-plugin": "^5.5.0",
    "lodash-template-webpack-loader": "^1.0.2",
    "resolve-url-loader": "^5.0.0",
    "sass": "^1.53.0",
    "sass-loader": "^13.0.2",
    "style-loader": "^3.3.1",
    "webpack": "^5.73.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.9.3",
    "webpackbar": "^5.0.2"
  },
  "dependencies": {
    "lodash": "^4.17.21"
  }
}

webpack.config.js:

import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import WebpackBar from 'webpackbar'; // adds a nicer loading bar. You can remove this.
const htmlPageNames = ['index', 'teaser'];
let entryPoints = {};
    
/**
 * Creates a new entry for each page provided in htmlPageNames
 */
let multipleHtmlPlugins = htmlPageNames.map(name => {
    return new HtmlWebpackPlugin({
        template: `./html/${name}.html`, // relative path to the HTML files
        filename: `${name}.html`, // output HTML files
        chunks: [`${name}`] // respective JS files
    })
});

/**
 * Example output
 * Using the same JS file for both pages
 */
htmlPageNames.map(name => {
    entryPoints = {...entryPoints, [name]: './index.js'};
});

export default{
    mode: 'development',
    entry: entryPoints,
    // not meant for production
    devtool: 'inline-source-map',
    devServer: {
        static: ['./dist', './html'],
        open: true,
    },
    plugins: [
        new WebpackBar({
            name: 'frizzants webpack app',
            color: '#00D4B4'
        })
    ].concat(multipleHtmlPlugins),
    output: {
        assetModuleFilename: "[name]_[hash:4][ext]",
        filename: '[name].js',
        path: path.resolve('dist'),
        clean: true,
    },
    module: {
        rules: [
            {
                test: /\.s[ac]ss$/i,
                use: [
                    // Creates `style` nodes from JS strings
                    "style-loader",
                    // Translates CSS into CommonJS
                    "css-loader",
                    {
                        // Rewrites URLs
                        loader: 'resolve-url-loader',
                        options: {}
                   },
                    {
                        // Compiles Sass to CSS
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true, // <-- !!IMPORTANT!!
                        }
                    },
                ],
            },

            {
                test: /\.html$/i,
                loader: "html-loader",
                options: {},
            },
        ],
    },
    optimization: {
        runtimeChunk: 'single',
    },
};

index.js:

import 'index.scss';

function run() {
    /** Run some Javascript here */
    console.log('Hello from webpack');
}

run();

Upvotes: 1

Related Questions