How to point webpack to a specific node_modules folder - web

I am trying to build a grpc web client and I need to pack the code to resolve the require statements.
I have compiled the protos to js and it works if I have them in the current folder where I have installed the node modules.
The problem is if I have the compiled proto in some other place and I require them from there, webpack looks for the node modules in that path.
From my client.js
working version:
const {StopRequest, StopReply} = require('./work_pb.js');
Problematic version:
const {StopRequest, StopReply} = require('../../../messages/proto/output/work_pb.js');
In this last case it looks for the node modules in ../../../messages/proto/output/.
The node modules are installed in the current path where my client.js is and from where I ran npx webpack client.js.
ERROR in /home/xxx/yyy/zzz/messages/proto/output/work_pb.js
Module not found: Error: Can't resolve 'google-protobuf' in '/home/xxx/yyy/zzz/messages/proto/output'
# /home/xxx/yyy/zzz/messages/proto/output/work_pb.js 11:11-37
# ./client.js
How do I tell webpack to look in the current path for the node modules and not in the path of the compiled proto?

You can specify resolve.modules to customize the directory, where Webpack searches for modules with absolute import paths:
// inside webpack.config.js
const path = require('path');
module.exports = {
//...
resolve: {
modules: [path.resolve(__dirname, 'node_modules'), 'node_modules']
}
};
This will let node_modules inside your project root (where webpack config resides) take precedence over the default setting "node_modules", which resolves paths via node module resolution algorithm.
More infos: Webpack docs: Module Resolution

Related

webpack doesn't bundle node modules

I want to require a module from node_modules and I want to bundle it (for test purposes), but Webpack behaves as if it is added to externals.
// no externals or any plugin used
let config = {
mode: 'none',
target: 'node',
entry: {
output: `/example.js`,
},
resolve: {
extensions: ['.js'],
},
output: {
path: './dist',
},
};
// exampl.js
require('path')
// dist/output.js
require('path');
Expected behavior
the node module path to be bundled
actual behavior
Webpack keep require('path');
This is by design. When you set target: 'node' in webpack config, webpack will not bundle the built-ins module of Node.js. path is a built-in module of Node.js, it doesn't come from the node_modules directory.
using node webpack will compile for usage in a Node.js-like environment (uses Node.js require to load chunks and not touch any built in modules like fs or path).
See targets

How to dynamically import package.json dependencies based on environment variables?

How could I add a script to my package.json file that would allow me to dynamically use a local file instead of a package version based on an environment variable?
"dependencies": {
"dynamic-dependency": "$(process.env.NODE_ENV !== 'dev' ? '^1.0.7' : 'file:../local-path-to-package')"
}
You can't do this in package.json, which is non-executable JSON file. The JSON variant used in package.json doesn't even support comments :). The purpose of package.json is to specify which dependencies are installed into node_modules, and that's it. With those dependencies installed, they can be used by Node at runtime, which locates them using the module resolution algorithm:
If the module identifier passed to require() is not a core module, and does not begin with '/', '../', or './', then Node.js starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location. Node.js will not append node_modules to a path already ending in node_modules.
So you can't use NPM/package.json for this. But, I see that you tagged your question with React, so if you are using Webpack, you can solve this issue in your Webpack config. This can be done with resolve.alias:
const path = require('path');
module.exports = {
//...
resolve: {
alias: {
'dynamic-dependency': process.env.NODE_ENV !== 'dev' ? 'dynamic-dependency' : path.resolve(__dirname, '../local-path-to-package'),
},
},
};
I have not used other JS bundlers, but I would have to think Parcel/Rollup etc support this kind of configuration as well.

how to solve the error that fs module is not found when used react and next.js

Am using a react application without router settings. I want to build my sitemap.xml file. I tried some modules like sitemap.js, react-router-sitemap, sitemap-generator. But these module are throwing error as fs module is missing. I installed fs module via npm install --save. But it is still showing the error.
I found in some forums to add the below code in webpack.config file.
node: {
fs: "empty"
}
Am not sure where this file is. I couldn't find them nside the sitemap related modules.
Please help me to resolve this. Am new to react.
Here is my folder structure.
create next.config.js and put below code. It works fine for me.
next.config.js
module.exports = {
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Note: we provide webpack above so you should not `require` it
// Perform customizations to webpack config
// Important: return the modified config
// Example using webpack option
//config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//))
config.node = {fs:"empty"}
return config
},
webpackDevMiddleware: config => {
// Perform customizations to webpack dev middleware config
// Important: return the modified config
return config
},
}

Express, Pug and Webpack

I have a Node js server app which uses Express and Pug. I would like to bundle it to single script which can be deployed by pm2. There seem to be several problems with this.
In runtime I get Cannot find module "." and during compilation few messages like
WARNING in ./node_modules/express/lib/view.js 80:29-41 Critical
dependency: the request of a dependency is an expression
appear which come from dynamic imports like require(mod).__express. I assume Webpack can't statically resolve those and does not know which dependency to include.
How can this be solved ?
How do I make Pug compile and be part of the output js ?
It is because webpack rebundle node_modules (already bundled) dependencies and in the case of pug, it doesn't work.
You need to use webpack-node-externals within the webpack externals option in order to specifically ask not to re-bundle depedencies.
Install webpack-node-externals: npm i -D webpack-node-externals
Integrate it your webpack config file:
Example
// ...
const nodeExternals = require('webpack-node-externals')
module.exports = {
target: 'node',
entry: {
// ...
},
module: {
// ...
},
externals: [nodeExternals()],
output: {
// ...
},
}

Module not found : 'child process'

I'm developing a ReactJS app with Babel and Webpack. I am using the create-react-app facebook script so it handles the Webpack´s configuration. My problem is that I created a js file and add:
var childProcess = require('child_process');
But when I want to compile the new version i get the following error :
Module not found: 'child_process'.
I don't know what to do with this . I have read that adding custom configurations to the webpack.config.js may be the solution but i am using create react app so I don't have the Webpack configuration. I tried running npm run eject and create my own webpack.config.js but it doesn't work.
I hope somebody could help me.
You need to configure the correct target inside the webpack configuration: https://webpack.github.io/docs/configuration.html#target
module.exports = {
entry: './path/to/my/entry/file.js',
...
target: 'node',// we can use node.js modules after adding this configuration
};

Resources