Running webpack throws 'Callback was already called' error - node.js

I just started learning webpack to manage dependencies in my project. I am trying to use it to build bundles for my typescript and javascript files. For the typescript files, I am using the ts-loader plugin for handling it. For CSS, I am using the mini-css-extract and an optimize-css-assets plugin. When I try to run webpack, I get the following error and I am not able to figure out what might be causing this error.
user#system spl % npm run build
> spl#1.0.0 build /Users/user/Downloads/spl
> webpack --config webpack.config.js
/Users/user/Downloads/spl/node_modules/neo-async/async.js:16
throw new Error('Callback was already called.');
^
Error: Callback was already called.
at throwError (/Users/user/Downloads/spl/node_modules/neo-async/async.js:16:11)
at /Users/user/Downloads/spl/node_modules/neo-async/async.js:2818:7
at processTicksAndRejections (internal/process/task_queues.js:79:11)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! spl#1.0.0 build: `webpack --config webpack.config.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the spl#1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/user/.npm/_logs/2020-05-14T14_23_32_985Z-debug.log
The following is my webpack.config file that I am using to build my dist files.
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
mode: 'production',
entry: "./static/js/index.js",
output: {
filename: "bundle.[contentHash].js", // File name with hash, based on content
path: path.resolve(__dirname, 'dist')
},
optimization: {
minimizer: [
new OptimizeCssAssetsPlugin(),
new TerserPlugin(),
new HtmlWebpackPlugin({
template: "./static/index.html",
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
removeComments: true
}
})
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[contentHash].css"
}),
new CleanWebpackPlugin(),
],
module: {
rules: [
{
test: /\.html$/,
use: [ "html-loader" ]
},
{
test: /\.[tj]s$/,
use: "ts-loader",
exclude: /(node_modules|tests)/
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
],
},
resolve: {
alias: {
src: path.resolve(__dirname, 'src'),
static: path.resolve(__dirname, 'static'),
},
extensions: [ '.ts', '.js' ]
}
}

I had the same issue and I realized that I was importing CSS file from my index.html file:
<link rel="stylesheet" href="./css/main.css">
although the CSS file should have been imported from entry file (index.js) using import:
import '../css/main.css';
so I deleted the line <link rel="stylesheet" href="./css/main.css"> and solved the problem.
You can see your HTML file and check if there are any assets imported from your HTML file. I hope it helped.

tl;dr: Upgrading webpack to a newer version solved it for me.
I went into node_modules/neo-async/async.js and modified the onlyOnce so that it gives a bit more descriptive stack trace like this:
/**
* #private
* #param {Function} func
*/
function onlyOnce(func) {
const defined = new Error('onlyOnce first used here')
return function(err, res) {
var fn = func;
func = () => {
console.error(defined);
throwError();
};
fn(err, res);
};
}
The stack trace points into webpack’s internal code, which, when I upgraded to the latest version, solves this issue.

I ran into this issue and was able to determine that the cause was circular dependencies in Typescript, not outdated dependencies as suggested by other answers here. This error appeared when I refactored code from import MyClass from "folder/file" into import { MyClass } from "folder".
I only considered this possibility after reading this post about differences in semantics between export default and other types of exports.

I had this issue and it was related to a recent downgrade someone had made to mini-css-extract-plugin. We are using pnpm, so this answer is specific to that. I had to delete the pnpm-lock.yaml file in the module I was trying to run out of spring boot dashboard in VSCode. This file is generated if it is missing, but for us anyway, it was committed to the repo. If that doesn't work for you, you might also consider deleting the npm-cache and .pnpm-store dirs. The locations of those files are configured in the .npmrc file in your user's home directory.

For me, the issue came after upgrading css-loader. Downgrading it back to the original version did the trick for me
diff --git a/package.json b/package.json
index 7151c509..b0eba48b 100644
--- a/package.json
+++ b/package.json
## -111,7 +111,7 ##
"webpack-merge": "^4.1.3"
},
"devDependencies": {
- "css-loader": "^6.5.1",
+ "css-loader": "^1.0.0",

Related

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default

I'm trying to use Socket.io in my Laravel/Vue.js app. But I'm getting this error when running npm run dev.
Module not found: Error: Can't resolve 'path' in '/home/nicolas/LaravelProjects/Chess/node_modules/socket.io/dist'
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.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
- install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "path": false }
webpack compiled with 9 errors
I tried changing the webpack.config.js file by adding resolve.fallback: { "path": false }, but it doesn't seem to help. It is possible that I'm doing it wrong since I have 4 webpack.config.js files in my project (I don't know why).
Maybe can I downgrade webpack? Thanks!
This fix worked for me (Vue 3):
In vue.config.js, add:
const { defineConfig } = require('#vue/cli-service')
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
plugins: [
new NodePolyfillPlugin()
]
}
})
Followed by npm install node-polyfill-webpack-plugin
I had this problem in ReactJS with create-react-app(facebook) but other packages (crypto-browserify)
Solution:
First install the necessary packages in this problem "path-browserify" but in my case "crypto-browserify"
Modify webpack.config.js in reactjs with create-react-app this file is inside:
node_modules/react-scripts/config/webpack.config.js
Search module.exports and inside this function there is a return:
module.exports = function (webpackEnv) {
...
return {
...
resolve: {
...
fallback: {
// Here paste
path: require.resolve("path-browserify"),
// But in mi case I paste
crypto: require.resolve("crypto-browserify"),
}
}
}
}
Note: This solution works, but when the webpack project starts it shows warnings
Pd: I am not native speaker English, but I hope understand me.
I have the same issue in React (feb-2022) using Real (realm-web) from Mongo.
I solve this in two steps:
npm i stream-browserify crypto-browserify
create fallback object into webpack.config.js at node_modules/react-scripts/config/webpack.config.js
module.exports = function (webpackEnv) {
...
return {
...
resolve: {
...
fallback: { // not present by default
"crypto": false,
"stream": false
}
}
}
I have the same issue with crypto. Some say that adding a proper path in TS config (and installing a polyfill) should resolve the issue.
tsconfig.json
{
"compilerOptions": {
"paths": {
"crypto": [
"./node_modules/crypto-browserify"
],
}
Details https://github.com/angular/angular-cli/issues/20819
I'm still fighting with crypto, but above link might help in your struggles.
I had the same issue, Strangely an import {script} from 'laravel-mix' in my app.js. I removed it and everything went back to normal.
I could not get the other answers to work with React on a new project with rss-parser. The error messages aren't clear. I fixed it by adding this line to the webpack configuration:
resolve: {
extensions: ['.tsx', '.ts', '.js'],
fallback: { "http": false, "browser": false, "https": false,
"stream": false, "url": false, "buffer": false, "timers": false
}
},
Watch out for this import in your app.js. Removing it fixed my issue.
use the version of webpack 4.46.0 to remove the error
I had to delete this line in a Vue component to solve the problem:
import { ContextReplacementPlugin } from "webpack";
If you use create-react-app(cra)
You have to overwrite the default webpack file
to do that you need to install a package like "react-app-rewired" that
will help overwriting and merge your configuration with the ones were
added by react scripts
First
npm install --D react-app-rewired
create a new file in the root directory called "config-overrides.js"
Install(using npm) and Add the required dependencies to the created config file
npm i -D path-browserify
install other packages as the error message shows
const webpack = require('webpack');
module.exports = function override(config) {
const fallback = config.resolve.fallback || {};
Object.assign(fallback, {
path: require.resolve('path-browserify'),
add others as shown in the error if there are more
});
config.resolve.fallback = fallback;
config.plugins = (config.plugins || []).concat([
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
}),
]);
return config;
};
Update your package.json scripts
"scripts": {
"build": "react-app-rewired build",
....
"start": "react-app-rewired start",
"test": "react-app-rewired test"
},
Also please note that a new version of react-scripts(newer than 5.0.1) might solve the issue.
had this issue in a react-app.
installation of stream-browserify crypto-browserify didn't work for me
went through with hjpithadia's answer in Reactjs with a slight change in webpack.config.js
install the package
npm install node-polyfill-webpack-plugin
find the webpack configuration file here
node_modules/react-scripts/config/webpack.config.js
import the package
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
search for module.exports
in plugin array add this new NodePolyfillPlugin(),
module.exports = function (webpackEnv) {
...
return {
...
plugins: [
new NodePolyfillPlugin(),
...
]
}
}
For React apps, if you don't need the module make sure webpack ignores it.
install craco https://craco.js.org/docs/getting-started/
create a craco.config.js in the root of your project, mine looks like this:
module.exports = {
webpack: {
configure: (webpackConfig) => {
webpackConfig.resolve.fallback = webpackConfig.resolve.fallback || {}
webpackConfig.resolve.fallback.zlib = false
webpackConfig.resolve.fallback.http = false
webpackConfig.resolve.fallback.https = false
webpackConfig.resolve.fallback.stream = false
webpackConfig.resolve.fallback.util = false
webpackConfig.resolve.fallback.crypto = false
return webpackConfig;
},
}
};
I resolved similar issue:
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.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }
Installing the npm i stream-browserify --save-dev
Making the custom webpack.config.js file containing:
module.exports = {
resolve: {
fallback: { stream: require.resolve("stream-browserify") },
},
};
Installing the npm install #angular-builders/custom-webpack --save-dev
Assigning (angular.json: projects -> <proj_name> -> architect -> build -> options)
"customWebpackConfig": {
"path": "./webpack.config.js"
}
Changing the: build / serve / extract-i18n / test – as of your needs – to use custom Webpack config:
"builder": "#angular-builders/custom-webpack:browser",
I finally found the solution. With laravel, you have to change the webpack.mix.js file and not webpack.config.js.

setup webpack config in nextJS (next.config.js)

I'm working with NextJS and using react-data-export plugin to generate xls files.
in the description it says :
This library uses file-saver and xlsx and using
json-loader will do the magic for you.
///webpack.config.js
vendor: [
.....
'xlsx',
'file-saver'
],
.....
node: {fs: 'empty'},
externals: [
{'./cptable': 'var cptable'},
{'./jszip': 'jszip'}
]
but I have no idea how to implement it and got error like this :
The static directory has been deprecated in favor of the public directory. https://err.sh/vercel/next.js/static-dir-deprecated
Defining routes from exportPathMap
event - compiled successfully
> Ready on http://localhost:80 or http://localhost
> Ready on https://localhost:443 or https://localhost
event - build page: /menu_accounting/ReportGross
wait - compiling...
error - ./node_modules/react-export-excel/node_modules/xlsx/xlsx.js
Module not found: Can't resolve 'fs' in '/home/ahmadb/repos/lorry-erp/node_modules/react-export-excel/node_modules/xlsx'
Could not find files for /menu_accounting/ReportGross in .next/build-manifest.json
I had the same problem, the solution for me was this:
Install this packages (if you installed, ignored this)
npm install file-saver --save
npm install xlsx
npm install --save-dev json-loader
Add this to your nextjs.config.js
const path = require('path')
module.exports = {
...
//Add this lines
webpack: (config, { isServer }) => {
// Fixes npm packages that depend on `fs` module
if (!isServer) {
config.node = {
fs: 'empty'
}
}
return config
}
}

Unable to implement webpack in project with node-red

I am trying to implement webpack in my project which contains node-red. However, I keep getting the following warning. Please suggest how to solve this error -
WARNING in ./node_modules/node-red/red/runtime/storage/localfilesystem/projects/git/node-red-ask-pass.sh 1:26
Module parse failed: Unexpected token (1:26)
You may need an appropriate loader to handle this file type.
> "$NODE_RED_GIT_NODE_PATH" "$NODE_RED_GIT_ASKPASS_PATH" "$NODE_RED_GIT_SOCK_PATH" $#
|
# ./node_modules/node-red/red/runtime/storage sync ^\.\/.*$ ./localfilesystem/projects/git/node-red-ask-pass.sh
# ./node_modules/node-red/red/runtime/storage/index.js
# ./node_modules/node-red/red/runtime/index.js
# ./app.js
My webpack.config.js is -
const path = require('path');
var nodeExternals = require('webpack-node-externals');
module.exports = {
target: 'node',
externals: [nodeExternals()],
entry: './app.js',
output: {
path: path.resolve(__dirname, './output'),
filename: 'bundle.js'
},
resolve: {
extensions: ['.js','.json', '.sh'],
modules: [
'node_modules'
],
},
module: {
rules: [
{
test:/\.css$/,
use:['style-loader','css-loader']
},
{
test: /\.coffee$/,
use: [ 'coffee-loader' ]
}
]
}
};
For Webpack, every file is a .js. In order to handle other extensions, like .css or .sh, you're supposed to use a loader, like you did with css-loader, that will tranform CSS rules into JS.
The issue you're facing is that you've got an import chain (./app.js -> .../index.js -> .../index.js -> .../node-red-ask-pass.sh), so Webpack will, at some point, will import a .sh file, but will throw an error because shell code is obviousouly invalid JavaScript. that is why you're seeing the error that you have.
By the way, I couldn't reproduce the issue you're facing:
npm init -y
npm i node-red
# ./node_modules/node-red/red is not a directory
So it was probably a node-red bug. Update the package to the latest version.

My tsconfig.json cannot find a module in my node_modules directory, not sure what is wrong

I have the following hierarchy:
dist/
|- BuildTasks/
|- CustomTask/
- CustomTask.js
node_modules/
source/
|- BuildTasks/
|- CustomTask/
- CustomTask.ts
- tsconfig.json
Additionally, I am trying to create a VSTS Task extension for internal (private) usage. Originally, I had my tsconfig.json at my root directory, and everything worked just fine on my local machine. The problem is that a VSTS Extension requires all the files to be included in the same directory as the task folder itself. See https://github.com/Microsoft/vsts-task-lib/issues/274 for more information:
you need to publish a self contained task folder. the agent doesnt run
npm install to restore your dependencies.
Originally, I had a this problem solved by include a step to copy the entire node_modules directory into each Task folder, in this case my CustomTask folder which contains my JS file. But, this seems a bit much considering that not every task I am writing has the same module requirements.
My idea was to create a tsconfig.json in each of the Task folders which would specify to create a single output file containing all of the dependent modules, but unfortunately it is not working:
{
"compilerOptions": {
"baseUrl": ".",
"target": "ES6",
"module": "system",
"strict": true,
"rootDir": ".",
"outFile": "../../../dist/BuildTasks/CustomTask/CustomTask.js",
"paths": {
"*" : ["../../../node_modules/*"]
}
}
}
Prior to adding the "paths", I was getting the following errors:
error TS2307: Cannot find module 'vsts-task-lib/task'.
error TS2307: Cannot find module 'moment'.
After adding the paths, I still get the error that it cannot find the module 'moment', which is in my node_modules directory. Also, when I look at the output JS it seems that it didn't include the 'vsts-tasks-lib' code necessary, maybe because it still had an error in regards to the 'moment' module? Not sure what I missed?
Using webpack to compile JavaScript modules, simple sample:
webpack.config.js:
const path = require('path');
module.exports = {
entry: './testtask.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
node: {
fs: 'empty'
},
target: 'node'
};
After that, there are just bundle.js and task.json in task folder.
Update: sample code in testtask.ts:
import tl = require('vsts-task-lib/task');
import fs = require('fs');
console.log('Set variable================');
tl.setVariable('varCode1', 'code1');
tl.setTaskVariable('varTaskCode1', 'taskCode1');
var taskVariables = tl.getVariables();
console.log("variables are:");
for (var taskVariable of taskVariables) {
console.log(taskVariable.name);
console.log(taskVariable.value);
}
console.log('##vso[task.setvariable variable=LogCode1;]LogCode1');
console.log('end========================');
console.log('current path is:' + __dirname);
fs.appendFile('TextFile1.txt', 'data to append', function (err) {
if (err) throw err;
console.log('Saved!');
});
console.log('configure file path:' + process.env.myconfig);
console.log('configure file path2:' + process.env.myconfig2);

Packaging Keytar with an Electron app

I'm using electron-builder (16.6.2) to package my electron application which includes keytar (3.0.2) as a prod dependency.
package.json file includes:
"scripts": {
"postinstall": "install-app-deps",
"compile:dev": "webpack-dev-server --hot --host 0.0.0.0 --config=./webpack.dev.config.js",
"compile": "webpack --config webpack.build.config.js",
"dist": "yarn compile && build"
},
"build": {
"appId": "com.myproject",
"asar": true,
"files": [
"bin",
"node_modules",
"main.js"
]
}
When I run the .app on the same system it runs fine. When I try running it on a different system (or deleting my node_modules) it fails to find keytar.node. When keytar is built, it includes a fully qualified path to that image for my system. I get the following error in the console:
Uncaught Error: Cannot open /Users/Kevin/Work/myproject/node_modules/keytar/build/Release/keytar.node
Error: dlopen(/Users/Kevin/Work/myproject/node_modules/keytar/build/Release/keytar.node,
1): image not found
I must be missing a step in the build process.
As it turns out, I was using keytar in the renderer process. I moved keytar into the main process (which doesn't go through Webpack / Babel) and gets packed correctly by electron-builder.
main.js
ipcMain.on('get-password', (event, user) => {
event.returnValue = keytar.getPassword('ServiceName', user);
});
ipcMain.on('set-password', (event, user, pass) => {
event.returnValue = keytar.replacePassword('ServiceName', user, pass);
});
Then from the renderer process I can call
const password = ipcRenderer.sendSync('get-password', user);
or
ipcRenderer.sendSync('set-password', user, pass);
window.require("electron").remote.require("keytar")
Since you are working on renderer process and want to use native api from system or main process.
Update:
I found (as per the OP) that transpiling my main thread code (which uses keytar) resulted in calls to keytar functions returning TypeError: keytar.findPassword is not a function.
I had to use webpack-asset-relocator-loader to bundle keytar successfully:
npm i -DE #vercel/webpack-asset-relocator-loader
Add the following rule to your webpack.config.js:
module: {
rules: [{
test: /\.node$/,
parser: { amd: false },
use: {
loader: "#vercel/webpack-asset-relocator-loader",
options: {
outputAssetBase: "native_modules"
}
}
},
// <other rules>
],
// rest of config
}
Solution found in this Github issue.
The information below still stands for including binary assets in your webpack build.
If you have to transpile code that requires a binary file, you can add file-loader to your webpack config.
Install
npm i -D file-loader
or
yarn add -D file-loader
webpack config (to include a .dat file)
...,
module: {
rules: [{
...
}, {
test: /\.dat$/,
use: {
loader: "file-loader"
}
}]
},
...
If you want to preserve the filename, you can pass name options to the loader:
use: {
loader: "file-loader",
options: {
name: "[name].[ext]"
}
}
More information on the file-loader Github repo.

Resources