Webpack 4 - Add css file to multiple html files - javascript

I want to bundle a couple of html files and add one css files into all of them. But my webpack configuration add only css and js bundled files to index.html
My files looks like this:
I want to add this main-hash.js and main-hash.css to all HTML files: about.html, index.html, contact.html
Also when I exclude index.html (comment below) from file-loader my index.html don't recognize paths for public folder /images. Any ideas ??
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/main.js',
output: {
filename: '[name]-[hash:8].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: '[name].[hash:8].css'
}),
new CleanWebpackPlugin()
],
module: {
rules: [
{
test: /.(js|jsx)$/,
include: [path.resolve(__dirname, 'src')],
loader: 'babel-loader',
options: {
plugins: ['syntax-dynamic-import'],
presets: [
[
'#babel/preset-env',
{
modules: false
}
]
]
},
exclude: '/node_modules/'
},
{
test: /\.(png|jpeg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
publicPath: './src/images',
outputPath: './assets',
name: '[name].[ext]'
}
}
]
},
{
test: /\.(html)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].html'
}
},
{ loader: 'extract-loader' },
{
loader: 'html-loader',
options: {
attrs: ['img:src']
}
}
],
// HERE
exclude: path.resolve(__dirname, './src/index.html')
},
{
test: /\.sass$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'sass-loader'
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/
}
},
chunks: 'async',
minChunks: 1,
minSize: 30000,
name: true
}
},
devServer: {
open: true
}
};

You can add multiple instances of the HtmlWebpackPlugin, one for each of your html files:
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html'
}),
new HtmlWebpackPlugin({
filename: 'about.html',
template: './src/about.html'
}),
new HtmlWebpackPlugin({
filename: 'contact.html',
template: './src/contact.html'
}),
new MiniCssExtractPlugin({
filename: '[name].[hash:8].css'
}),
new CleanWebpackPlugin()
],
This should inject the JS and CSS files into each html file.

Related

Webpack shows white screen

After I've added webpack in my react app, once the webpack started, it shows the white screen, and the whole bundle gets downloaded at one time. Even though I've done code splitting in react.
my webpack config:
/* eslint-disable no-un`enter code here`def */
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlWebpackInjectPreload = require("#principalstudio/html-webpack-inject-preload");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: path.resolve(__dirname, './index.js'),
devtool: "inline-source-map",
output: {
path: path.resolve(__dirname, "build"),
filename: "bundle.js",
publicPath: '/'
},
devServer: {
contentBase: path.resolve(__dirname, 'build'),
port: 4000,
hot: true,
},
resolve: {
extensions: [".*",".js", ".jsx", ".css"],
fallback: {
stream: false
}
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules)/,
use: ["babel-loader"],
},
{
test: /\.css$/,
exclude: /\.module\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.module\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: { importLoaders: 2, modules: true },
},
"postcss-loader",
],
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
use: [
{
loader: "url-loader",
options: {
limit: 8192,
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve('./index.html')
}),
new CleanWebpackPlugin(),
new HtmlWebpackInjectPreload({
files: [
{
match: /.*\.woff2$/,
attributes: { as: "font", type: "font/woff2", crossorigin: true },
},
{
match: /\.[a-z-0-9]*.css$/,
attributes: { as: "style" },
},
],
}),
],
};
The attached bundle image also gets larger up to 19MB. What's going wrong I'm not able to figure out.

How to ignore error js script tag from html on running webpack with HtmlWebpackPlugin?

How can i ignore the script tag in Html webpack plugin?
Because I have added this
<script src="cordova.js"/>
tag into my index.html template anonymously for my app development.
See my configuration in Webpack.config.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "www"),
filename: "./js/build/[name].build.js",
chunkFilename: "./js/build/[name].build.js",
// publicPath: "./js/build/",
},
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"],
},
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "./",
},
},
"css-loader?url=false",
"sass-loader",
],
},
{
test: /\.html$/,
use: ["html-loader"],
},
{
test: /\.(svg|png|jpeg|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "res",
},
},
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "./css/build/[name].css",
// chunkFilename: "../css/[id].css"
}),
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
// new BundleAnalyzerPlugin()
],
// devtool: "inline-source-map",
};
I just wanted to ignore the script on production and I have researched this many times but unfortunately I don't see any solution
So, if I got the problem right, you want to ignore a certain resource when bundling for production.
The html-loader has an option to filter sources based on attribute, attribute value, context file and anything you have available in you webpack.config.js.
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// Assuming you are passing arguments to your webpack config like argv.mode
const PRODUCTION = true;
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "www"),
filename: "./js/build/[name].build.js",
chunkFilename: "./js/build/[name].build.js",
// publicPath: "./js/build/",
},
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"],
},
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "./",
},
},
"css-loader?url=false",
"sass-loader",
],
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: {
sources: {
urlFilter: (attribute, value, resourcePath) => {
if (PRODUCTION && /cordova.js$/.test(value)) {
return false;
}
return true;
},
}
},
},
},
{
test: /\.(svg|png|jpeg|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "res",
},
},
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "./css/build/[name].css",
// chunkFilename: "../css/[id].css"
}),
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
// new BundleAnalyzerPlugin()
],
// devtool: "inline-source-map",
};
In the html module rule, I added an options property to html-loader with an example how you could ignore a certain resource with urlFilter. Check the html-loader docs on filtering resources
You will need to get a reference to the variables you passed to your cli like --mode eg. line 5-6. (Not in the current example) See webpack docs on env vars.

React + Webpack: "RuntimeError: memory access out of bounds"

I've recently developed a react + webpack application that is deployed using
AWS Amplify. I've been getting a strange error that is logged on Sentry, but can't
find a way to replicate the bug.
RuntimeError: memory access out of bounds
I suspect it has something to do with my webpack configuration, but I don't know whats wrong.
I never used wasm, but it seems to be related to it.
Here is my production level webpack configuration.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const env = require('../environment/prod.env');
const commonPaths = require('./paths');
const webpack = require('webpack');
const SentryWebpackPlugin = require('#sentry/webpack-plugin');
module.exports = {
mode: 'production',
devtool: 'source-map',
output: {
filename: `${commonPaths.jsFolder}/[name].[hash].js`,
path: commonPaths.outputPath,
chunkFilename: `${commonPaths.jsFolder}/[name].[chunkhash].js`,
},
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
cache: true,
sourceMap: true,
}),
new OptimizeCSSAssetsPlugin(),
],
splitChunks: {
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'initial',
},
async: {
test: /[\\/]node_modules[\\/]/,
name: 'async',
chunks: 'async',
minChunks: 4,
},
},
},
runtimeChunk: true,
},
module: {
rules: [
{
test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env': env,
}),
new MiniCssExtractPlugin({
filename: `${commonPaths.cssFolder}/[name].css`,
chunkFilename: `${commonPaths.cssFolder}/[name].css`,
}),
],
};
Here is also my common webpack configuration
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const commonPaths = require('./paths');
module.exports = {
context: commonPaths.srcPath,
entry: commonPaths.entryPath,
output: {
path: commonPaths.outputPath,
filename: 'js/[name].js',
},
resolve: {
extensions: ['.ts', '.js', '.html', '.vue'],
alias: {
'~': commonPaths.srcPath,
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
include: commonPaths.srcPath,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
plugins: ['react-hot-loader/babel'],
},
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/img/[name].[hash:8].[ext]',
publicPath: '/',
},
},
],
},
{
test: /\.(mp3)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/audio/[name].[hash:8].[ext]',
publicPath: '/',
},
},
],
},
{
test: /\.(ttc|ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/fonts/[name].[hash:8].[ext]',
publicPath: '/',
},
},
],
},
],
},
serve: {
content: commonPaths.entryPath,
dev: {
publicPath: commonPaths.outputPath,
},
open: true,
},
resolve: {
modules: ['src', 'node_modules', 'bower_components', 'shared', '/shared/vendor/modules'],
extensions: ['*', '.js', '.jsx'],
},
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({
favicon: './icon.png',
template: commonPaths.templatePath,
}),
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'async',
}),
],
};
Any help would really help. Thanks.
Try to restart your server and make sure you reinstall node modules.

Webpack 2 extracted stylesheet doesn't load until I manually change the file in chrome console (AngularJS)

I am trying to integrate Webpack 2 into the build process of an AngularJS 1.6 application. I am actually trying to extract the CSS from the generated HTML using the ExtractTextPlugin.
The problem is when I extract the CSS file using the ExtractTextPlugin:
The CSS is extracted into an external file styles.css but it isn't loaded on the page unless I make a change on the CSS file in the chrome console (Even just adding a space) Here I added a space and the CSS was loaded.
I don't understand why isn't the CSS loaded on first run and why does it load when I make any small change.
More Details:
I have been following this tutorial on SurviveJS and other tutorials on the survivejs website and main Webpack website.
This is my current Webpack Configuration file:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack')
const path = require('path')
const ngAnnotatePlugin = require('ng-annotate-webpack-plugin');
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');
const fs = require('fs');
const gracefulFs = require('graceful-fs');
const TypedocWebpackPlugin = require('typedoc-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const cssnano = require('cssnano');
const posthtml = require('posthtml');
gracefulFs.gracefulify(fs);
module.exports = {
entry: {
main: './src/index.ts'
},
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, '../dist'),
publicPath: '../'
},
plugins: [
new CleanWebpackPlugin(['dist'], {
root: __dirname + "/../",
verbose: true
}),
new ngAnnotatePlugin({
add: true
}),
new webpack.optimize.UglifyJsPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.jquery': 'jquery'
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
return module.context
&& (module.context.indexOf('node_modules') !== -1 || module.context.indexOf('bower_components') !== -1);
}
}),
//CommonChunksPlugin will now extract all the common modules from vendor and main bundles
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest'
}),
new webpack.LoaderOptionsPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
inject: 'body',
hash: true
}),
new CopyWebpackPlugin([{
context: 'raw/',
from: '**/*',
}]),
new OptimizeCssAssetsPlugin({
cssProcessor: cssnano,
cssProcessorOptions: {
discardComments: {
removeAll: true
}
},
canPrint: true
}),
new ExtractTextPlugin("styles.css")
],
module: {
loaders: [
{
test: /\.ts(x?)$/,
loader: 'ts-loader'
},
{
test: /\.less$/i,
use: ExtractTextPlugin.extract({
fallback: ['style-loader', 'css-loader', 'less-loader'],
use: ['css-loader', 'less-loader']
})
},
{
test: /\.html$/,
exclude: /node_modules/,
use: [
{
loader: 'html-loader',
options: {
minimize: true
}
}
]
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-woff'
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader'
},
{
test: /\.(gif|png|jpe?g|svg|ico)$/i,
loaders: [
'file-loader',
{
loader: 'image-webpack-loader',
query: {
mozjpeg: {
progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
pngquant: {
quality: '75-90',
speed: 3,
},
}
}
]
},
{
test: /\.ts$/,
enforce: "pre",
loader: 'tslint-loader'
},
{
test: /^((?!\.spec\.ts).)*.ts$/,
enforce: "post",
exclude: /(node_modules|bower_components)/,
loader: 'istanbul-instrumenter-loader'
}
]
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
modules: [path.resolve(__dirname, "src"), "node_modules", "bower_components"]
}
};

How can I stop HTML being output to the compiled app.js?

I am using Webpack 2 for my portfolio website, but it's not an SPA - therefore, the intention is not to output everything into my bundled JS.
I have a few entry points for the .pug, .scss and .js files. Like so:
entry: {
app: [
path.resolve(__dirname, 'src/pug/app.pug'),
path.resolve(__dirname, 'src/js/app.js'),
path.resolve(__dirname, 'src/scss/app.scss')
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].js'
}
However, when looking at the source for the app.js, I see the rendered HTML from my .pug files.
For the .pug compiling, I'm using HtmlWebpackPlugin. I guess the easiest way for me to explain what's going on is to show you the webpack.config.babel.js file:
import webpack from 'webpack';
import path from 'path';
import autoprefixer from 'autoprefixer';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import SvgStorePlugin from 'external-svg-sprite-loader/lib/SvgStorePlugin';
import bourbon from 'bourbon';
import neat from 'bourbon-neat';
const extractScss = new ExtractTextPlugin({
filename: 'css/[name].css',
allChunks: true
});
const config = {
entry: {
app: [
path.resolve(__dirname, 'src/pug/app.pug'),
path.resolve(__dirname, 'src/js/app.js'),
path.resolve(__dirname, 'src/scss/app.scss')
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].js'
},
module: {
rules: [
{
test: /\.pug$/,
use: [
{
loader: 'html-loader'
},
{
loader: 'pug-html-loader',
options: {
pretty: false,
exports: false
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
['es2015']
]
}
}
]
},
{
test: /\.(jpe?g|png|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '/images/[name].[ext]'
}
},
{
loader: 'image-webpack-loader',
options: {
progressive: false,
optipng: {
optimizationLevel: 7,
quality: '90',
speed: 5
},
mozjpeg: {
quality: 90
},
gifsicle: {
interlaced: false
}
}
}
]
},
{
test: /\.svg$/,
use: [
{
loader: 'external-svg-sprite-loader',
query: {
name: 'svg/sprite.svg',
iconName: '[name]'
}
}
]
},
{
test: /\.scss$/,
use: extractScss.extract([
{
loader: 'css-loader'
},
{
loader: 'postcss-loader',
options: {
plugins() {
return [
autoprefixer({
browsers: ['last 2 versions', 'Explorer >= 9', 'Android >= 4']
})
];
}
}
},
{
loader: 'sass-loader',
options: {
includePaths: [
bourbon.includePaths,
neat.includePaths
]
}
}
])
}
]
},
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
stats: 'errors-only',
open: false
},
plugins: [
new SvgStorePlugin(),
new HtmlWebpackPlugin({
title: 'Portfolio',
minify: {
collapseWhitespace: true
},
hash: true,
template: 'src/pug/app.pug',
filetype: 'pug',
filename: 'index.html'
}),
extractScss
]
}
process.traceDeprecation = false;
export default config;
I don't see any CSS in the app.js bundle and the entry point is setup just the same, so might it have something to do with the HtmlWebpackPlugin itself? Perhaps I'm not understanding how this works correctly and my configuration is wrong.
I'm new to Webpack (coming from Gulp), so please bear with me if the answers to my questions seem rather obvious.
Thanks for your help.
Update:
For reference, my project structure is as follows:
And I would call an image from my .pug file in /pug/components/example.pug with a path like img(src="../images/example.jpg"). This worked prior to removing .pug as an entry point in the Webpack config as user Tatsuyuki suggested below.
Do not add the template as an source:
app: [
// path.resolve(__dirname, 'src/pug/app.pug'),
path.resolve(__dirname, 'src/js/app.js'),
path.resolve(__dirname, 'src/scss/app.scss')
]
Instead, specify the template option for HtmlWebpackPlugin:
new HtmlWebpackPlugin({
template: 'src/index.pug'
})
Reference

Categories

Resources