Webpack breaking change - javascript

I am trying to build a react app but each time I run npm start, I am greeted with this message
Module not found: Error: Can't resolve 'buffer' in '/Users/abdus/Documents/GitHub/keywords-tracker/node_modules/buffer-equal-constant-time'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
It gives the same message for a few different modules. I have tried npm installing these modules but the error persists

this is my webpack set up that works. you should install all the packages that listed in fallback:
// const path = require("path");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const webpack = require("webpack");
module.exports = {
mode: "development",
target: "web",
entry: ["regenerator-runtime/runtime", "./src/index.js"],
output: {
filename: "bundle.js",
path: path.join(__dirname, "dist"),
publicPath: "/",
},
resolve: {
extensions: [".js", ".css"],
alias: {
// add as many aliases as you like!
components: path.resolve(__dirname, "src/components"),
},
fallback: {
// path: require.resolve("path-browserify"),
fs: false,
assert: require.resolve("assert/"),
os: require.resolve("os-browserify/browser"),
constants: require.resolve("constants-browserify"),
stream: require.resolve("stream-browserify"),
crypto: require.resolve("crypto-browserify"),
http: require.resolve("stream-http"),
https: require.resolve("https-browserify"),
},
},
// devtool: "eval-cheap-source-map",
devtool: "eval",
module: {
rules: [
{ test: /\.(js|jsx)/, loader: "babel-loader", exclude: /node_modules/ },
{ test: /\.css$/, use: ["style-loader", "css-loader"] },
// {
// test: /\.m?js/,
// resolve: {
// fullySpecified: false
// }
// },
{
test: /\.(woff(2)?|ttf|eot|jpg|jpeg|png|gif)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[contenthash].[ext]",
outputPath: "fonts/",
},
},
],
},
{
test: /\.svg$/,
use: [
{
loader: "svg-url-loader",
options: {
limit: 10000,
},
},
],
},
{
test: /\.json5$/i,
loader: "json5-loader",
type: "javascript/auto",
options: {
esModule: true,
},
},
],
},
devServer: {
contentBase: path.join(__dirname, "build"),
historyApiFallback: true,
overlay: true,
},
plugins: [
new HtmlWebpackPlugin({
title: "NFT",
template: "src/index.html",
}),
// new CopyWebpackPlugin({
// patterns: [{ from: "assets", to: "assets" }],
// }),
],
};
you can get this webpack5-Boilerplate
Since there are too many polyfills, instead of manually installing all, you can use node-polyfill-webpack-plugin package. instead of fallback property
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
plugins: [
new HtmlWebpackPlugin({
title: "esBUild",
template: "src/index.html",
}),
// instead of fallback
new NodePolyfillPlugin(),
// new webpack.ProvidePlugin({
// process: "process/browser",
// Buffer: ["buffer", "Buffer"],
// React: "react",
}),
],

It seems like you are using a front-end react app and some dependency is internally using the buffer module which is only available in target: node under webpack. So you will need to add a polyfill for the same.
module.exports = {
resolve: {
fallback: {
buffer: require.resolve('buffer'),
}
},
}
You can check the docs here at webpack: https://webpack.js.org/configuration/resolve/#resolvefallback
From Webpack 5 onwards, webpack doesn't polyfill for browser-based applications.

Related

How to solve ChunkLoadError: Loading hot update chunk second_app failed in webpack 5?

while setup a new project for development, the app is not hot reloading. The app consists of multiple apps separated in its different folders.Currently, there are 2 apps html_nodes_prototype and second_app in src/apps folder. Each app consist of index.html, style.css and main.js when I visit the link http://localhost:8080/second_app/second_app.html, the app shows but If I change something in src/apps/second_app/main.js. It doesn't hot reload, I've to manually reload to get changes. I've set up a webpack-dev-server. Error prompts in the console. I couldn't figure out what's wrong with the config file.
Error in console
[HMR] Update failed: ChunkLoadError: Loading hot update chunk second_app failed.
(missing: http://localhost:8080/second_app.5b0047c2bf2b48c8a084.hot-update.js)
at http://localhost:8080/second_app/second_app.bundle.js:987:26
at new Promise (<anonymous>)
at loadUpdateChunk (http://localhost:8080/second_app/second_app.bundle.js:982:20)
at http://localhost:8080/second_app/second_app.bundle.js:1411:29
at Array.forEach (<anonymous>)
at Object.__webpack_require__.hmrC.jsonp (http://localhost:8080/second_app/second_app.bundle.js:1406:22)
at http://localhost:8080/second_app/second_app.bundle.js:819:45
at Array.reduce (<anonymous>)
at http://localhost:8080/second_app/second_app.bundle.js:815:53
paths.js
const path = require("path");
module.exports = {
// Source files
src: path.resolve(__dirname, "../src"),
// Production build files
build: path.resolve(__dirname, "../dist"),
// public path
public: path.resolve(__dirname, "../public/"),
};
webpack.dev.js
const common = require("./webpack.common");
var HtmlWebpackPlugin = require("html-webpack-plugin");
const merge = require("webpack-merge").merge;
const paths = require("./paths");
module.exports = merge(common, {
mode: "development",
output: {
filename: "[name]/[name].bundle.js",
path: paths.build,
},
module: {
rules: [
{ test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"] },
{ test: /\.css$/, use: ["style-loader", "css-loader"] },
],
},
devServer: {
historyApiFallback: true,
// contentBase: paths.build,
open: true,
compress: true,
hot: true,
port: 8080,
},
plugins: [
new HtmlWebpackPlugin({
filename: "html_nodes_prototype/html_nodes_prototype.html",
title: "HTML Nodes",
template: "src/apps/html_nodes_prototype/index.html",
chunks: ["html_nodes_prototype", "vendor"],
}),
new HtmlWebpackPlugin({
filename: "second_app/second_app.html",
title: "Second app",
hot: true,
template: "src/apps/second_app/index.html",
chunks: ["second_app", "vendor"],
}),
],
});
webpack.common.js
const paths = require("./paths");
module.exports = {
mode: "development",
entry: {
html_nodes_prototype: paths.src + "/apps/html_nodes_prototype/main.js",
second_app: paths.src + "/apps/second_app/main.js",
vendor: paths.src + "/apps/_vendor/vendor.js",
},
module: {
rules: [{ test: /\.m?js$/, use: ["babel-loader"] }],
},
};
Adding runtimeChunk: 'single' to webpack.dev.js works for me. Found the answer here
module.exports = {
...,
optimization: {
runtimeChunk: 'single'
},
...
}

How do I disable webpack 4 code splitting?

I'm using webpack 4.43.0.
How do I prevent codesplitting from happening in webpack? All these files are created - 0.bundle.js up to 11.bundle.js (alongside the expected bundle.js), when I run webpack. Here's my webpack config:
/* eslint-env node */
const path = require('path');
module.exports = {
entry: './media/js/src/main.jsx',
mode: process.env.WEBPACK_SERVE ? 'development' : 'production',
output: {
path: path.resolve(__dirname, 'media/js'),
filename: 'bundle.js'
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
include: path.resolve(__dirname, 'media/js/src'),
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}
}
]
}
};
You can use webpack's LimitChunkCountPlugin to limit the chunk count produced by code splitting:
In your webpack.config.js file:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
],
...
};
You could also pass the --optimize-max-chunks option to the webpack command directly.
So, in your package.json file:
{
"scripts": {
"build": "webpack --optimize-max-chunks 1",
...
},
...
}
Now, when you run npm run build, webpack will build only one file (or "chunk").
// Full list of options: https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build
build: {
scopeHoisting: true,
vueRouterMode: 'history', // available values: 'hash', 'history'
showProgress: true,
gzip: false,
analyze: false,
distDir: 'dist',
productName:'pos_host_ui',
minify:true,
// Options below are automatically set depending on the env, set them if you want to override
// extractCSS: false,
// https://quasar.dev/quasar-cli/cli-documentation/handling-webpack
extendWebpack (cfg) {
const webpack = require('webpack');
cfg.plugins.push(
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
);
cfg.module.rules.push({
resourceQuery: /blockType=i18n/,
type: 'javascript/auto',
use: [
{ loader: '#kazupon/vue-i18n-loader' },
{ loader: 'yaml-loader' },
]
});
}

How to resolve to a non default javascript file

I am using webpack and typescript in my SPA along with the oidc-client npm package.
which has a structure like this:
oidc-client.d.ts
oidc-client.js
oidc-client.rsa256.js
When I import the oidc-client in my typescript file as below:
import oidc from 'oidc-client';
I want to import the rsa256 version and not the standard version, but I am unsure how to do this.
in my webpack config I have tried to use the resolve function but not I am not sure how to use this properly:
const path = require('path');
const ForkTsChecker = require('fork-ts-checker-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
const shell = require('shelljs');
const outputFolder = 'dist';
const destinationFolder = '../SPA/content';
if (shell.test('-d', outputFolder)) {
shell.rm('-rf', `${outputFolder}`);
}
if (shell.test('-d', destinationFolder)) {
shell.rm('-rf', `${destinationFolder}`);
}
module.exports = (env, options) => {
//////////////////////////////////////
/////////// HELP /////////////////////
/////////////////////////////////////
resolve: {
oidc = path.resolve(__dirname, 'node_modules\\oidc-client\\dist\\oidc- client.rsa256.slim.min.js')
};
const legacy = GenerateConfig(options.mode, "legacy", { "browsers": "> 0.5%, IE 11" });
return [legacy];
}
function GenerateConfig(mode, name, targets) {
return {
entry: `./src/typescript/main.${name}.ts`,
output: {
filename: `main.${name}.js`,
path: path.resolve(__dirname, `${outputFolder}`),
publicPath: '/'
},
resolve: {
extensions: ['.js', '.ts']
},
stats: {
children: false
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.ts\.html?$/i,
loader: 'vue-template-loader',
},
{
test: /\.vue$/i,
loader: 'vue-loader'
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'#babel/env',
{
"useBuiltIns": "usage",
"corejs": { version: 3, proposals: true },
"targets": targets
}
],
"#babel/typescript"
],
plugins: [
"#babel/transform-typescript",
[
"#babel/proposal-decorators",
{
"legacy": true
}
],
"#babel/plugin-proposal-optional-chaining",
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/proposal-class-properties",
"#babel/proposal-numeric-separator",
"babel-plugin-lodash",
]
}
}
}
]
},
devServer: {
contentBase: path.join(__dirname, outputFolder),
compress: true,
hot: true,
index: `index.${name}.html`,
open: 'chrome'
},
plugins: [
new ForkTsChecker({
vue: true
}),
new HtmlWebpackPlugin({
filename: `index.${name}.html`,
template: 'src/index.html',
title: 'Project Name'
}),
new MiniCssExtractPlugin({ filename: 'app.css', hot: true }),
new VueLoaderPlugin()
]
};
}
Please add an alias to specify the exact .js module you'd like to import, like this for example:
resolve: {
extensions: ['.ts','.js'],
modules: ['node_modules'],
alias: {
'oidc-client': 'oidc-client-js/dist/oidc-client.rsa256.slim'
}
}
If you don't specify an alias, webpack/ will follow node module resolution and we'll eventually find your module by going to
library oidc-client-js in node_modules and follow package.json main property which is "lib/oidc-client.min.js" and that's not what you want.

Webpack externals failing to resolve in parent project

I have a library, this library is React component library so it depends on react and react-dom. It also depends on react-router-dom (and transitively react-router).
These are packages the parent project provides. I don't want them in the bundle. This library is generated using webpack so I have added them to the externals configuration in the libraries webpack configuration, which is below (Webpack v4.4)
const webpack = require("webpack");
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: "commonjs",
},
externals: {
"react-router": {
"commonjs": "react-router",
"commonjs2": "eact-router",
"amd": "react-router",
"root": "react-router"
},
"react-router-dom": {
"commonjs": "react-router-dom",
"commonjs2": "react-router-dom",
"amd": "react-router-dom",
"root": "react-router-dom"
},
"react": {
"commonjs": "react",
"commonjs2": "react",
"amd": "react",
"root": "React"
},
"react-dom": {
"commonjs": "react-dom",
"commonjs2": "react-dom",
"amd": "react-dom",
"root": "ReactDOM"
}
},
// devtool: "cheap-eval-source-map",
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env", "#babel/preset-react"],
plugins: [
"#babel/plugin-transform-flow-strip-types",
"#babel/plugin-proposal-object-rest-spread",
"transform-class-properties",
],
},
},
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{ loader: "css-loader", options: { minify: true } },
"sass-loader",
],
}),
},
{
// Match woff2 in addition to patterns like .woff?v=1.1.1.
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "url-loader",
options: {
// Limit at 50k. Above that it emits separate files
limit: 50000,
// url-loader sets mimetype if it's passed.
// Without this it derives it from the file extension
mimetype: "application/font-woff",
// Output below fonts directory
name: "./fonts/[name].[ext]",
},
},
],
},
{
test: /\.svg$/,
use: [
{
loader: "svg-inline-loader",
options: {
removeSVGTagAttrs: false,
},
},
],
},
{
test: /\.(png|jp(e*)g)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]
},
],
},
plugins: [
new ExtractTextPlugin("styles.css"),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: require("cssnano"),
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true,
}),
new webpack.optimize.AggressiveMergingPlugin(),
],
};
However, when I include the output of the library in the parent project it complains during the build phase that
ERROR in ../moss/dist/bundle.js
Module not found: Error: Can't resolve 'react-router' in '/Users/ubermouse/code/moss/dist'
# ../moss/dist/bundle.js 19655:223-261
# ./matai/static_src/js/containers/App.js
# ./matai/static_src/js/containers/Root.js
# ./matai/static_src/js/index.js
# multi ./matai/static_src/js/utils/polyfills.js ./matai/static_src/js/index.js
I get the above error for both react-router and react-router-dom. I do not get it for react or react-dom.
What is going on here? Am I using externals wrong? Why does it work for react/react-dom? Are they just not required yet? Can externals not pull dependencies from the parents node_modules? I've been tearing my hair out over this for hours :(
One thing I have noticed, react-router/react-router-dom have a module property in their package.json so their ESModule gets loaaded. react/react-router does not. I don't know if this changes anything, but it is something.
Our parent projects webpack config for completeness
const webpack = require('webpack');
const path = require('path');
const config = require('./frontend.config');
/**
* Base Webpack config, defining how our code should compile.
*/
module.exports = {
entry: {
vendor: [
"moment",
"react",
"react-dom",
"react-intl",
"react-intl-redux",
"react-redux",
"react-leaflet",
"react-router",
"react-router-dom",
"react-router-redux",
"redux",
"redux-observable",
"rxjs",
],
matai: [
path.join(config.paths.js, 'utils', 'polyfills.js'),
path.join(config.paths.js, 'index.js'),
],
},
output: {
path: path.join(config.paths.build_js),
filename: '[name].js',
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
minChunks: Infinity,
// (with more entries, this ensures that no other module
// goes into the vendor chunk)
}),
],
module: {
rules: [
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.js$/,
enforce: 'pre',
use: ['eslint-loader'],
include: path.join(config.paths.js),
},
{
test: /\.js$/,
use: ['babel-loader'],
exclude: [/node_modules/],
},
],
},
stats: {
// Set the maximum number of modules to be shown
maxModules: 3,
// Add chunk information (setting this to `false` allows for a less verbose output)
chunks: false,
// Add the hash of the compilation
hash: false,
// `webpack --colors` equivalent
colors: true,
// Add information about the reasons why modules are included
reasons: false,
// Add webpack version information
version: false,
},
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
fs: 'empty',
net: 'empty',
tls: 'empty',
},
};

Async Code Splitting Webpack - Unexpected Token

I was just following this guide
I have this code:
import React, { PropTypes, Component } from 'react';
import('contact-page').then(() => {});
I get this output:
This is my webpack file:
var webpack = require('webpack');
var packages = require('./package.json');
var path = require('path');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require('html-webpack-plugin');
var filterDependencies = ['normalize.css', 'font-awesome'];
var dependencies = Object.keys(packages.dependencies).filter(f => !filterDependencies.some(fd => fd === f));
module.exports = {
entry: {
main: './src/index.js',
vendor: dependencies
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
minChunks: Infinity,
}),
new ExtractTextPlugin("styles.css"),
new HtmlWebpackPlugin({
template: 'index.html'
})
],
module: {
rules: [
{
test: /\.js?$/,
use: [ 'babel-loader', ],
exclude: /node_modules/
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
}),
exclude: /node_modules/
},
{
test: /(\.png|\.jpg|\.otf)$/,
use: ['file-loader?name=[name].[ext]&publicPath=assets/&outputPath=assets/']
}
]
},
performance: {
hints: "warning", // enum
maxAssetSize: 200000, // int (in bytes),
maxEntrypointSize: 400000, // int (in bytes)
assetFilter: function (assetFilename) {
// Function predicate that provides asset filenames
return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
}
},
devtool: "source-map", // enum
target: "web", // enum
stats: "errors-only",
devServer: {
proxy: { // proxy URLs to backend development server
'/api': 'http://localhost:3000'
},
contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location
compress: true, // enable gzip compression
historyApiFallback: true, // true for index.html upon 404, object for multiple paths
hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin
https: false, // true for self-signed, object for cert authority
noInfo: true, // only errors & warns on hot reload
// ...
}
};
For dynamin import I'm using babel-plugin-syntax-dynamic-import library - https://www.npmjs.com/package/babel-plugin-syntax-dynamic-import
After installation you have to extend module.rules sets to something like (as long as you want to mix es2015 and react):
module: {
rules: [
{
test: /\.js?$/,
use: {
loader: 'babel-loader',
options: {
presets: [['es2015', "react"]],
plugins: ['syntax-dynamic-import']
},
},
exclude: /node_modules/
},
},
It is described in tutorial https://webpack.js.org/guides/code-splitting-async/#usage-with-babel more detailed.

Categories