I have webpack in my plain HTML, CSS, and Javascript application. I use webpack to convert scss to CSS. I want my javascript to be the same untouched in my dist folder, as I want to edit it later my wordpress projects. Webpack is adding a lot of code, which makes the JS files hard to edit later. Here is my config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { HotModuleReplacementPlugin } = require("webpack");
const HtmlWebpackPartialsPlugin = require("html-webpack-partials-plugin");
module.exports = {
mode: "development",
entry: {
index: "./src/js/index.js",
about: "./src/js/about.js",
courses: "./src/js/courses.js",
contactUs: "./src/js/contact-us.js",
},
output: {
filename: "js/[name].bundle.js",
path: path.resolve(__dirname, "dist"),
assetModuleFilename: "images/[name][ext]",
},
devServer: {
static: { directory: path.join(__dirname, "dist") },
port: 9000,
hot: true,
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
}),
new HtmlWebpackPlugin({
title: "Leads",
filename: "index.html",
template: "./src/pages/index.html",
chunks: ["index"],
}),
new HtmlWebpackPlugin({
title: "Leads About",
filename: "about-us.html",
template: "./src/pages/about-us.html",
chunks: ["about"],
}),
new HtmlWebpackPlugin({
title: "Courses",
filename: "courses.html",
template: "./src/pages/courses.html",
chunks: ["courses"],
}),
new HtmlWebpackPlugin({
title: "Contact Us",
filename: "contact-us.html",
template: "./src/pages/contact-us.html",
chunks: ["contactUs"],
}),
new HtmlWebpackPartialsPlugin({
path: path.join(__dirname, "./src/partials/footer.html"),
location: "partialfooter",
template_filename: [
"index.html",
"about-us.html",
"courses.html",
"contact-us.html",
],
}),
new HtmlWebpackPartialsPlugin({
path: path.join(
__dirname,
"./src/partials/components/infrastructure.html"
),
location: "infrastructure",
template_filename: [
"index.html",
"about-us.html",
"courses.html",
"contact-us.html",
],
}),
new HotModuleReplacementPlugin(),
],
module: {
rules: [
{
test: /\.js$/,
exclude: "/node_modules",
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"],
},
},
},
{
test: /\.s[ac]ss$/i,
use: [
MiniCssExtractPlugin.loader,
// Creates `style` nodes from JS strings
// "style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
},
],
},
optimization: {
minimize: false,
},
};
How can I get webpack to convert my sass files, but simply copy my JS files?
Perhaps you could use copy-webpack-plugin https://webpack.js.org/plugins/copy-webpack-plugin/ to copy files from your src static folder to your build destination folder. Roughly like this -
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
],
};
The code that Webpack adds can allow many features for JavaScript like transpiling ES6 JavaScript to ES5, bundling, code-splitting and dynamic imports. But if you don't need them a straight copy might do.
Related
Due to how the (legacy) project is currently set up, I cannot benefit from the caching capabilities of webpack in the standard way, but instead have to generate the scripts in empty files (like main.html5 example) and include those in the project's head or body.
That works just fine with the config I currently have but I find myself lacking the capability to reference the main.[hash].js and main.[hash].css extracted by mini-css-extract-plugin in seperate ejs files so that i could include each generated html5 in different locations of my html5 template (link tag in head and script in body).
webpack.common.js :
module.exports = {
entry: {
main: path.resolve(__dirname, "./react/src/Index.js"),
styles: path.resolve(__dirname, "./react/src/Styles.js"),
vendor: path.resolve(__dirname, "./react/src/Vendor.js"),
},
output: {
path: path.resolve(__dirname, "./dist"),
filename: "[name].[contenthash].js",
assetModuleFilename: "images/[hash][ext][query]",
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "./react/main.ejs"),
filename: "main.html5",
inject: false,
publicPath: "/dist/",
chunks: ["main"], // would be great to only reference .js here, then create another instance for .css
}),
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
}),
],
main.ejs only has :
<%= htmlWebpackPlugin.tags.headTags %>
Generated main.html5 file :
<script defer="" src="/dist/main.534ca9564003f8d93251.js"></script><link href="/dist/main.0864e3dfa0f6edc21e68.css" rel="stylesheet">
Then i include main.html5 into my project's template like so:
<body>
// ---- html code goes here
<?php include_once 'dist/main.html5'; ?>
</body>
The problem is that this loads both tags at the end of the body tag whereas i would like to include the css in the head tags.So Ideally, I would have 2 html5 files generated. One containing script tag and the other the link tag. I have read the documentation for webpack but fail to see any possible solution that would work for my case. If i could exclude tags from the ejs file that could be a solution but i fail to find anything about that in the HtmlWebpackPlugin Documentation.
So, I found out about html-webpack-exclude-assets-plugin which is doing exactly what i want but unfortunately it is not working and has not been updated for about 5 years. Thankfully, there is an alternative with html-webpack-skip-assets-plugin. Here is how I use it :
webpack.common.js :
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlWebpackSkipAssetsPlugin =
require("html-webpack-skip-assets-plugin").HtmlWebpackSkipAssetsPlugin;
module.exports = {
entry: {
main: path.resolve(__dirname, "./react/src/Index.js"),
},
output: {
path: path.resolve(__dirname, "./dist"),
filename: "[name].[contenthash].js",
assetModuleFilename: "images/[hash][ext][query]",
},
optimization: {
minimizer: [`...`, new CssMinimizerPlugin()],
splitChunks: {
cacheGroups: {
styles: {
name: "styles",
type: "css/mini-extract",
chunks: "all",
enforce: true,
},
},
},
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "./react/vendor.ejs"),
filename: "vendor.html5",
inject: false,
publicPath: "/dist/",
chunks: ["vendor"],
excludeAssets: [
/\/dist\/styles.*.css/,
(asset) => asset.attributes && asset.attributes["x-skip"],
],
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "./react/styles.ejs"),
filename: "styles.html5",
inject: false,
publicPath: "/dist/",
chunks: ["main"],
// excludeAssets: [/\.css$/i]
excludeAssets: [
/\/dist\/main.*.js/,
(asset) => asset.attributes && asset.attributes["x-skip"],
],
}),
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
}),
new HtmlWebpackSkipAssetsPlugin(),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.css$/i,
exclude: /node_modules/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
type: "asset/resource", //* less performance heavy than asset/inline
},
{
test: /\.(woff(2)?|eot|ttf|otf|svg)$/i,
type: "asset/inline", //* only for small assets. if webpack complains about asset size limit, change to asset/ressource type or asset. Had these as inline before (woff(2)?|eot|ttf|otf|svg),
},
],
},
There you go, we can now generate the css link tag in an html file of its own and include it wherever needed in our project's .html5 template.
I create a BLOB file and write JavaScipt code there, then create a URL and import the module from it.
const myJSFile = new Blob( [ 'export default true;' ], { type: 'application/javascript' } );
const myJSURL = URL.createObjectURL( myJSFile );
import( myJSURL ).then(async ( module ) => {
console.log( module.default );
});
This works great in the browser console. However, I am having a problem when building a project using Webpack.
I suspect the problem is with WebPack or Babel configuration.
Webpack common config:
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
// Where webpack looks to start building the bundle
entry: [
'core-js/modules/es6.promise',
'core-js/modules/es6.array.iterator',
'./src/main.js',
],
target: 'web',
// Where webpack outputs the assets and bundles
output: {
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: '[name].[contenthash].[ext]',
filename: '[name].[contenthash].bundle.js',
chunkFilename: '[id].[chunkhash].bundle.js',
// publicPath: '/',
},
// Determine how modules within the project are treated
module: {
rules: [
{
test: /\.(gif|png|jpe?g)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/images/'
}
}
]
},
// JavaScript: Use Babel to transpile JavaScript files
{ test: /\.js$/, use: ['babel-loader'] },
// Images: Copy image files to build folder
{ test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource' },
// Fonts and SVGs: Inline files
{ test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline' },
],
},
// Customize the webpack build process
plugins: [
// Generates an HTML file from a template
new HtmlWebpackPlugin({
// template: path.resolve(__dirname, 'src/index.html'), // шаблон
template: 'src/index.html',
// filename: 'index.html', // название выходного файла
// inject: false, // true, 'head'
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
},
// chunks: 'all',
// excludeChunks: [],
}),
new CopyWebpackPlugin(
{
patterns: [
{ from: 'src/assets', to: 'assets' },
// { from: 'src/components', to: 'components' },
]
}
),
],
resolve: {
// modules: [path.resolve(__dirname, 'src'), 'node_modules'],
extensions: ['.js', '.jsx', '.json', '.ts'],
alias: {
'#': [
path.resolve(__dirname, 'src'),
'./src/main.js'
],
},
},
}
Babel config
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
esmodules: true,
},
},
],
],
plugins: [
'#babel/plugin-proposal-class-properties',
'#babel/plugin-transform-runtime',
"#babel/plugin-syntax-dynamic-import"
]
};
I've used require-from-string before, which internally uses the native Module module to achieve this.
Speaking generally, Blobs don't really interoperate well between browser and node land, and modules are also not treated identically.. so it's not a surprise that blob+module has problems. :)
Why can't I embed images in webpack with HTML img tags?
Below is the content of webpack.config.js.
// webpack.config.js
const {
CleanWebpackPlugin,
} = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = [{
mode: 'development',
entry: {
'px.bundle': ['./src/index.js'],
},
output: {
path: path.resolve(__dirname,'dist'),
filename: '[name].js'
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
}
]
},
devServer: {
static : {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 9000
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ["**/*", "!assets/**/*", "!resources/**/*"],
}),
new MiniCssExtractPlugin({
filename: 'style.css',
}),
new HtmlWebpackPlugin({
title: 'Project Demo',
minify: {
collapseWhitespace: true
},
hash: true,
template: './src/index.html'
}),
],
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000,
},
}, {
mode: 'product',
entry: {
'px.bundle': ['./src/index.js'],
},
output: {
path: path.resolve(__dirname,'dist'),
filename: '[name].js',
},
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ["**/*", "!assets/**"],
cleanOnceBeforeBuildPatterns: ["**/*", "!resources/**"],
cleanAfterEveryBuildPatterns: ['dist'],
}),
new MiniCssExtractPlugin({
filename: 'style.css',
}),
new HtmlWebpackPlugin({
title: 'Project Demo',
minify: {
collapseWhitespace: true
},
hash: true,
template: './src/index.html'
}),
],
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000,
},
},
];
And below is the code including the contents of index.html.
<img class="header__logo" src="img/ico_logo.png" alt="company logo" />
If enter the npm run dev command like this, the contents of img/ico_logo.png are not output properly. Of course, I checked that the file is properly located in the path.
Change the above code to the following,
<img class="header__logo" alt="company logo" />
If I include the following in my css
.header__logo{
content:url('../img/ico_logo.png')
}
If enter the npm run dev command, I can see that it works properly.
If specify src as an img tag in HTML, webpack cannot include the image.
I don't know if the webpack setting is wrong or if webpack works normally only through the url in css.
I'm wondering if for some reason webpack is not embedding the logo image properly, and how can I fix it?
you can try with this
{
test: /\.(jpg|jpeg|png|gif|pdf|ico)$/,
use: [
{
loader: "file-loader",
options: {
name: "images/[name].[ext]",
},
},
],
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: {
minimize: true,
},
},
],
},
I think the reason is that webpack can't read HTML, although you had used HtmlWebpackPlugin. It just helps you to extract the HTML to a file, but it looks like it doesn't read the content.
I had the same problem, but I solved it by adding use html-loader.
I increase a new object into rules.
,{
test: /\.html$/i,
loader: 'html-loader'
}
And it works.
And also, the file-loader has been replaced by Asset Modules in webpack 5.
Hope this could help you, sincerely.🙂
Hi I have the following problem with my Webpack Config:
I want to have 3 different .js files from my src folder. Each file is supposed to be connected to only the corresponding html file with the same name:
Example: I want app.html only to inject app.js and not index.js and register.js as well.
As for now, Webpack generates 3 html files and 3 .js files, however every .html file gets referenced all 3 .js files, which breaks my code, since I don't have the corresponding id's for eventlisteners in index that the code written app.js.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: ['./src/js/index.js'],
register: ['./src/js/register.js'],
app: ['./src/js/app.js'],
},
output: {
filename: '[name].js',
path: __dirname + '/dist',
},
devServer: {
contentBase: './dist'
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
chunks: 'index',
template:'./src/index.html',
filename: './src/index.html'
}),
new HtmlWebpackPlugin({
inject: true,
chunks: 'register',
template:'./src/register.html',
filename: './src/register.html'
}),
new HtmlWebpackPlugin({
inject: true,
chunks: 'app',
template:'./src/app.html',
filename: './src/app.html'
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
Here you have an example adding one chunks to the html
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const config = [{
site: 'index'
}, {
site: 'register'
}, {
site: 'app'
}];
const entryHtmlPlugins = config.map(({
site
}) => {
return new HtmlWebPackPlugin({
filename: `${site}.html`,
chunks: [site],
});
});
module.exports = {
mode: 'production',
entry: {
index: './src/js/index.js',
register: './src/js/register.js',
app: './src/js/app.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, './dist'),
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
}, ],
},
plugins: [...entryHtmlPlugins],
};
I'm new to Webpack/Babel and trying to leverage it to improve the lighthouse performance of a front-end website that utilizes React.
I ran the lighthouse scan and found a recommendation to remove unused javascript with the main component of this being Babel's asyncToGenerator.js.
Looking at my webpack output, I see the following:
WARNING in entrypoint size limit: The following entrypoint(s) combined
asset size exceeds the recommended limit (244 KiB). This can impact
web performance. Entrypoints: main (543 KiB)
vendors-node_modules_babel_runtime_helpers_asyncToGenerator_js-node_modules_babel_runtime_hel-<hash>.css
vendors-node_modules_babel_runtime_helpers_asyncToGenerator_js-node_modules_babel_runtime_hel-<hash>.js
main.css
main.js
webpack.js:
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require( 'path' );
const WebpackPwaManifest = require('webpack-pwa-manifest');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const PreloadWebpackPlugin = require('preload-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
context: __dirname,
entry: [
// "core-js/modules/es.promise",
// "core-js/modules/es.array.iterator",
'./src/index.js',
],
output: {
path: path.resolve( __dirname, 'build' ),
filename: '[name].js',
publicPath: '/',
chunkFilename: '[id].[chunkhash].js'
},
optimization: {
chunkIds: "named",
splitChunks: {
chunks: 'all',
},
},
devServer: {
historyApiFallback: true
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
cacheDirectory: true
}
}
},
{
test: /\.(png|svg|jpg|jpeg|gif|ico)$/,
exclude: /node_modules/,
use: ['file-loader?name=[name].[ext]'] // ?name=[name].[ext] is only necessary to preserve the original file name
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve( __dirname, 'public/index.html' ),
filename: 'index.html',
favicon: 'public/favicon.ico',
title: 'Title'
}),
new PreloadWebpackPlugin({
rel: 'preload',
include: 'initial'
//include: 'initial',//'asyncChunks',//'initial',//'allChunks',
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name]-[id].css',
}),
new WebpackPwaManifest({
short_name: "Name",
name: "Name",
description: 'desc',
icons: [
{
src: path.resolve('public/favicon.ico'),
sizes: [64, 32, 24, 16]
},
],
start_url: "https://<url>.com/",
display: "browser",
theme_color: "#66fcf1",
background_color: "#1f2833"
}),
new CopyPlugin({
patterns: [
{ from: './src/serviceWorker.js', to: './serviceWorker.js' },
{ from: './public/offline.html', to: './offline.html' },
{ from: './public/manifest.json', to: './manifest.json' },
{ from: './public/manifest.json', to: './asset-manifest.json' },
{ from: './public/logo-png-192.png', to: './logo-png-192.png' },
{ from: './public/logo-png-512.png', to: './logo-png-512.png' },
{ from: './public/maskable_icon.png', to: './maskable_icon.png' },
],
}),
]
};
.babelrc
{
"presets": [
[
"#babel/preset-env", {
"modules": "auto",
"targets": "> 0.25%, not dead"
}
],
"#babel/preset-react"
],
"plugins": [
"#babel/plugin-proposal-class-properties",
[
"#babel/plugin-transform-runtime",
{
"regenerator": true
}
],
"#babel/plugin-syntax-dynamic-import"
]
}
What can I do to only include the asyncToGenerator when needed/only include what is needed?
The page does read from cloudfront and uses lazy loading.
Thoughts?