Reputation: 747
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
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:
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