I'm trying to load in audiosprite in my React app which is running on a Webpack server and I'm getting the following error:
Module not found: 'child_process' in
C:\Users\BenLi\Desktop\development
projects\app\node_modules\audiosprite
Have no idea what this could be or why it's occurring with this module as apparently, Webpack should not throw child_process errors as it comes with it.
I'm including it in my app like so:
import audiosprite from 'audiosprite';
The error in coming from here in the file:
function spawn(name, opt) {
opts.logger.debug('Spawn', { cmd: [name].concat(opt).join(' ') })
return require('child_process').spawn(name, opt)
}
How do I fix this error?
TL;DR
There is no way around this unless you (maybe) switch to Browserify (need to test this myself) which offers a browserify-fs module. Since the browser has no access to the file system or child processes anyways, the module audiosprite can't be used in this usecase. The browser cannot do what it's incapable of.
Explanation
This is because of Webpack. Webpack, by default, is designed to compile code to run in a web-browser environment. The whole reason it exists is to bundle everything up to be browser-friendly (hence the name "web pack").
Node offers some built-in modules such as child_process, path, os, fs, etc. that only exist in a Node environment. When Webpack comes along and tries to bundle code for the browser, the browser does not have access to these modules. Thus, when modules such as audiosprite use child_process, Webpack bundles them for the web by default and you no longer have access to these modules. This explains why the error reports that the "module is not found".
"Solutions"
A "fix" is to specify your Webpack configuration to compile for usage in a Node-like environment, where you do have access to these built-in modules. That way, Webpack won't mess with the built-in modules and child_process can be used. You can do this by specifying the target option. From the Webpack Configuration documentation:
target
"web" Compile for usage in a browser-like environment (default)
"node" Compile for usage in a node.js-like environment (use require to load chunks)
(documentation cut for brevity)
But there's a consequence. Because of you setting your target as a Node environment, require will not work when using the browser as there is no require in the browser environment.
What you can do is keep the target environment the same ("web" by default) and try to mock the module for what you need. With the node option:
node
Include polyfills or mocks for various node stuff:
<node buildin>: true, "mock", "empty" or false
And apply it to the Webpack configuration file:
node: {
fs: "mock"
}
But this will error out telling you:
Error: No browser version for node.js core module 'fs' available
So this is just by design. There is nothing you can do because bundling for the browser environment will inevitably forbid you from accessing the file system because it can't. You can't provide a browser mock for a module which does things that are impossible in the browser. The same goes for child_process and others.
Edit: I've been looking for some alternatives, and Browserify may or may not work. They do offer a browserify-fs module as a replacement to Node's fs. I have yet to test this so I'm not sure if it could be useful but it looks better than what Webpack does now.
I guess you have to let NPM install the dependency
just
npm install --save autiosprite
Related
I tried so but I have a 'require is not defined' error. I can't find information about that, can someone enlighten the noob in me please?
It's possible, but you have to be careful. Trying to require() a package means that node will try to locate its files in your file system. A chrome extension only has access to the files you declare in the manifest, not your filesystem.
To get around this, use a module bundler like Webpack, which will generate a single javascript file containing all code for all packages included through require(). You will have to generate a separate module for each component of your chrome extension (e.g. one for the background page, one for content scripts, one for the popup) and declare each generated module in your manifest.
To avoid trying to setup your build system to make using require() possible, I suggest starting with a boilerplate project. You can check out my extension to see how I do it.
An updated answer for 2022
Short answer: yes, you can require/import packages. Rather than going through the tedious work of setting up & configuring a bundler like Webpack on your own (especially if you have no experience with them), there are now build tools you can use to create the boilerplate "scaffolding" for a Chrome extension:
Extension CLI -- this one is well-documented and you can also reference the source code of some Chrome extensions that have used this tool (READ: learn how others have set up their code).
Chrome Extension CLI
Benefits of using them:
New projects are initiated with a default project file structure. Super helpful.
They support modern Javascript (ES6, ES2021), so modules work fine.
They already have bundlers integrated and pre-configured (Webpack in both above cases I think). You therefore don't need to install and configure any on your own.
You can use npm as normal to install any packages/dependencies you need.
Then of course, let the official documentation for Chrome Extensions guide you through the rest.
It's not possible to require node modules directly within a chrome extension. However, it is possible to bundle node applications and packages into the browser for use with your extensions. See here for more: Is it possible to develop Google Chrome extensions using node.js?
Yes, It is possible with esm npm packages.
require is commonjs module loader.
Browser doesn't support commonjs modules system
so that this error showed.
Method 1:
Run npm init -y and add "type" :"module" in your package.json.
create path.js file
add this line in path.js
const fullPath = await import.meta.resolve("npm-pkg-name");
const path = fullPath?.match(/(/node_modules.*)/)[0];
console.log(path);
add this line inside package.json
"path": "node --experimental-import-meta-resolve path.js",
Copy console output text. Replace package name with this copied path.
Method 2:
Install other npm package to find and replace
npm packages' virtual path to real path so that chrome browser will find it.
Install Path-fixxer
Add this line in path.js
import setAllPkgPath from "path-fixxer";
setAllPkgPath();
then run command : npm run path.
Now open browser to test it.
I have a node module that I am building, and I want it to be able to execute on the server (in nextjs server side rendering) and the client (call additional lifecycle methods in the UI). This same module also needs to work when used purely as a js library that can be included in a <script> tag on the page. This module depends on the uuid module, which has logic in it to check if it is running in a browser or server context, and use the proper random number generators/crypto libraries that are available in that context.
If I don't specify a target in my webpack config, the bundle works great in a client browser. It includes the webpack browser logic just fine. But it doesn't work in the server case - webpack removed the server capable logic in the uuid module.
If I target: 'node' in my webpack config - it executes just fine as a node module on the server and the client. It seemingly included all of the logic this time. But now it doesn't work if included just as a script tag on the page. I get ReferenceError: require is not defined from the file that depends on the uuid module.
It seems like the uuid module should handle these different environments just fine, but webpack is messing with that. How can I let that module resolve the proper implementation at runtime?
I unfortunately do not have a minimally reproducible example, or additional code to share at this time. I figured someone might have run into this with webpack (or even webpack and the uuid module) and know the solution.
I was trying to do this by building a single version of the package, but I don't think that is possible.
What is possible is building multiple versions, and then hosting the web bundle via unpkg or jsdelivr via an entry in package.json. Those entries can point to the target: 'web' version of the package, while the npm package can point to the target: 'node' version.
Is there any way to get what all libraries/script/modules included in webpack bundle from developer's console(you can consider a website is already running and you don't have access to its codebase) and also know there npm module version ?
Webpack does not keep the module versions, which is normal because you would not need it in production.
However, you can try to get the dependencies by parsing the vendor file and looking at all the imports and require statements.
I'm using Webpack to bundle dependencies, one of which is the emailing service postmark. This service depends upon something called child_process that apparently ships with node.
The problem is, when I attempt to run webpack to bundle my app, it complains:
Module not found: Error: Cannot resolve module 'child_process' in ...
Most of the answers online say that, in response to this error, I should add the line:
node: {
child_process: 'empty'
}
to my webpack config. But this makes no sense, because then webpack just doesn't try to look for child_process, and consequently, when I run my app, I get the following error:
Uncaught TypeError: exec is not a function
which is an error from postmark (the service that relies upon child_process) complaining that the exec function within the child_process module doesn't exist.
Thus, I'm wondering how I can include the child_process module in my build without webpack complaining?
Front-end developer of Postmark here.
It looks like you're trying to bundle postmark.js into your client-side JavaScript but https://github.com/wildbit/postmark.js is a Node.js library. This means it will not run in the browser and requires a running Node.js server.
The main reason for not supporting browser environment is security. As you can see in this example:
var postmark = require("postmark");
var client = new postmark.Client("<server key>");
it requires you to insert the auth token. Bundling this with your client-side JS would expose it and allow everyone access your postmark account API.
Hope this clarifies it.
In a project where I am using Gulp and Browserify, anytime I try to require dust library (dustjs) in my script, Browserify throws an error: "process.binding is not supported".
Note: Browserify throws the same error whether dust is Installed from npm or called in and added via 'browserify-shim' in package.json.
Thanks for your help.
Browserify only shims certain common Node-specific properties. As said in the process documentation:
This module mostly exists to provide the nextTick functionality and nothing more. We keep this module lean because it will often be included by default by tools like browserify when it detects a module has used the process global.
It also defines a few other properties to prevent undefined errors from being thrown. binding and chdir intentionally throw errors, however.