Can't resolve 'worker_threads' in create-react-app - node.js

I'm trying to use "worker_threads" in my react-app for some cpu-intensive works. but react-app can't find "worker_threads" in node.js library.
Here is my code:
const {Worker} = require('worker_threads');
const path = require('path');
function fibonacci_worker(n) {
return new Promise((resolve,reject) => {
const w1 = new Worker(path.join(__dirname,'/fib.js'), { workerData: n });
w1.on('message',e => resolve(e));
w1.on('error',e => reject(e));
});
}
"npm start" script throws following error: "Can't resolve 'worker_threads' in 'C:\path\to\fibonacci.js'"
node version: 12.13.0
react-scripts version: 3.2.0

React uses Node.js for runtime tasks such as compilation. You cannot use built-in Node.js tools in the own React app, since the app uses the scope and tools of the browser.
You can find more information about the (unexisting) multithreading of the browser in the following question:
Why doesn't JavaScript support multithreading?

Related

Jest cannot find dynamicly loaded ES6 module

The ipfs-core library is only available as ES6 Module, while the project uses CommonJS. Therefore I use a dynamic import.
If your application is not yet ESM or you are not ready to port it to ESM, you can use the dynamic import function to load ipfs at runtime from a CJS module.
See Migrating to ipfs#0.63 and ipfs-core#0.15
export const ipfsProviders = [
{
provide: 'IPFS',
useFactory: async (): Promise<any> => {
const IPFS = await import('ipfs-core');
return await IPFS.create({ start: false });
}
},
];
The application runs fine, but I'm unable to run tests with Jest for services where IPFS is a dependency.
Error: Cannot find module 'ipfs-core' from 'common/ipfs/ipfs.providers.ts'
How can I configure Jest, so it just treats ipfs-core as ES module, while seeing the rest of the code as CommonJs?

Puppeteer: TypeError: Readable is not a constructor

I have been trying to use Puppeteer#15.5.0 to generate a PDF on the server side in Node.js.
import { launch } from 'puppeteer';
...
const browser = await launch();
const page = await browser.newPage();
await page.setContent('COME ON!');
console.log(await page.content());
const pdfBuffer = await page.pdf();
The console.log statement gives me the expected output of <html><head></head><body>COME ON!</body></html>
It then runs into the following error:
Error:
TypeError: Readable is not a constructor
at getReadableFromProtocolStream (/Users/kaziehsanaziz/Work/DocSpace/repos/docspace-pay/.webpack/service/src/public-lambda.js:405775:12)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async Page.pdf (/Users/kaziehsanaziz/Work/DocSpace/repos/docspace-pay/.webpack/service/src/public-lambda.js:403129:26)
at async /Users/kaziehsanaziz/Work/DocSpace/repos/docspace-pay/.webpack/service/src/public-lambda.js:329729:31
Puppeteer cannot be bundled using Webpack. The issue was that I was trying to do just that. In my case, since I was using Serverless, the solution was to tell the serverless-bundle plugin to not bundle the Puppeteer.
bundle:
packager: yarn
esbuild: true
forceExclude:
- aws-sdk
- puppeteer
externals:
- puppeteer-core
- '#sparticuz/chrome-aws-lambda'
The forceExclude is doing the trick here for the local environment. The external is what's helping the Production environment.
I have also run into this issue. It occurs when webpack (v5 on my end) bundles puppeteer. I have solved it by explicitly declaring webpack ignore directive when importing a file which uses puppeteer. I did this via dynamic es import, but a static one could be done in a very similar way:
const loadModule = async (modulePath) => {
try {
return await import(/* webpackIgnore: true */ modulePath)
} catch (e) {
throw new ImportError(`Unable to import module ${modulePath}`)
}
}
const renderPdf = (await loadModule('../../renderPdf/index.js')).default
use require puppeteer instead of import puppeteer statement

React UnhandledSchemeError - "node:buffer" is not handled by plugins

I'm trying to use a package in my React project that will allow me to make API calls (axios, node-fetch, got etc.)
When these packages are not installed, the app runs properly. When any of them are installed and called in the code, I'm facing the error as follows:
Ignoring the warnings, I believe the problem has its roots from the output below:
Failed to compile.
Module build failed: UnhandledSchemeError: Reading from "node:buffer" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.
I tried everything. Reinstalled node_modules. Created a clean test app, tried there. Also did my research, didn't find any relevant, clear solution on this. Nothing helped.
What am I doing wrong??
DomException file content:
/*! node-domexception. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
if (!globalThis.DOMException) {
try {
const { MessageChannel } = require('worker_threads'),
port = new MessageChannel().port1,
ab = new ArrayBuffer()
port.postMessage(ab, [ab, ab])
} catch (err) {
err.constructor.name === 'DOMException' && (
globalThis.DOMException = err.constructor
)
}
}
module.exports = globalThis.DOMException
npm version: 8.5.5
node version: 16.15.0
You can work around this with this Webpack configuration:
plugins: [
new webpack.NormalModuleReplacementPlugin(/node:/, (resource) => {
resource.request = resource.request.replace(/^node:/, "");
}),
]

Error when connecting to SQL Server in deno: 'cannot find module crypto'

I'm trying to port a nodejs MS SQL Server application to deno. I'm using the node compatibility library to allow the use of npm mssql package:
import { createRequire } from "https://deno.land/std/node/module.ts";
const require = createRequire(import.meta.url);
const sql = require('mssql')
async () => {
try {
await sql.connect('mssql://user:pwd#host/database')
const result = await sql.query`select * from the_table`
console.dir(result)
} catch (err) {
console.log('Error:', err)
}
}
However I'm getting an error:
error: Uncaught Error: Cannot find module 'crypto' Require stack:
C:\WORK\LEARN\DENO\node_modules\tedious\lib\connection.js
C:\WORK\LEARN\DENO\node_modules\tedious\lib\tedious.js
C:\WORK\LEARN\DENO\node_modules\mssql\lib\tedious.js
Note: upgrading to the latest version of mssql helped, getting a different error, 'unable to find module tty', which I think I can figure out.
The crypto library internal to Node is used internally by the mssql library, however this isn't fully ported to Deno yet as you can see here
https://deno.land/std#0.83.0/node

Accessing filesystem in Angular 2 app using Electron

I know that Angular 2 is run on a web browser, which does not have access to the file system.
However, I'm using Electron as my front-end, and also running the app via electron:
"build-electron": "ng build --base-href . && cp src/electron/* dist",
"electron": "npm run build-electron && electron dist"
Therefore, I run it with npm run electron which at the very end runs electron dist.
Since I'm running through electron and not ng I would think that I should be able to access the filesystem. However, when I do:
import * as fs from 'fs'
I get an error:
ng:///AppModule/AppComponent_Host.ngfactory.js:5 ERROR TypeError: __WEBPACK_IMPORTED_MODULE_0_fs__.readFileSync is not a function(…)
Similarly, when I try: var fs = require('fs');
I get:
ng:///AppModule/AppComponent_Host.ngfactory.js:5 ERROR TypeError: fs.readFileSync is not a function
This is the call resulting in the error:
this.config = ini.parse(fs.readFileSync('../../CONFIG.ini', 'utf-8'))
Does anyone have any idea what's causing this?
Thanks.
Solved it by:
1) Eject webpack: ng eject
2) Add target: 'electron-renderer' to the module.exports array inside webpack.config.js
3) Require remote, since we're in the renderer, but fs is only available in the main process (Read more): var remote = require('electron').remote;
4) Require fs (this time using remotes implementation of require): var fs = remote.require('fs');
And now it works!
I am using
Angular CLI: 7.0.7
Node: 8.12.0
OS: win32 x64
Angular: 7.0.4
I tried the ng eject method it didn't work in my case, it is disabled by default and will be removed completely in Angular 8.0
Error message: The 'eject' command has been disabled and will be removed completely in 8.0.
It worked for me by creating a file called native.js in the src folder and insert the following:
`window.fs = require('fs');
Add this file to the angular-cli.json scripts array:
"scripts": [
"native.js"
]
Add the following lines to polyfills.ts:
`declare global {
interface Window {
fs: any;
}
}`
After that you can access the filesystem with:
`window.fs.writeFileSync('sample.txt', 'my data');`
credits
As I understand it, you build the application with Webpack.
You can expose all Node modules via the externals array in your webpack config.
module.exports = {
"externals": {
"electron": "require('electron')",
"child_process": "require('child_process')",
"fs": "require('fs')",
"path": "require('path')",
...
}
}
Since they are provided through the Webpack externals, one does not have to require them but use them with imports.
import * as fs from 'fs'
You can read more about this problem in my article.
I'm late to the party but I also stumbled upon this problem recently. To the late comers, you can use ngx-fs
https://github.com/Inoverse/ngx-fs
Usage:
const fs = this._fsService.fs as any;
fs.readdir("\\", function (err, items) {
if (err) {
return;
}
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
}
});
I had the same problem and could solve it in an easier way:
Just download this project as start, the 'require'-s are already in the webpack.config.js file (along with the integration of angular, electron and so on):
https://github.com/maximegris/angular-electron
import 'fs' into home.ts (or into any other component) as mentioned by #Matthias Sommer above:
import * as fs from 'fs'
Use 'fs' :)

Resources