Resolve the module loaded by plugin in Webpack config - node.js

The following example will work only if some-module module is Node module, and won't work for modules loaded by Webpack plugin.
How can Webpack's own logic (enhanced-resolve) be used to resolve module paths in config?
In my case it was bower-webpack-plugin, but I guess this should work in the same way with any ResolverPlugin
var BowerWebpackPlugin = require("bower-webpack-plugin");
module.exports = {
...
module: {
plugins: [new BowerWebpackPlugin()],
loaders: [
{
// this won't work
test: require.resolve("some-bower-module")
loader: "imports?this=>window"
}
]
};

require.resolve inside webpack.config.js is resolved by Node and not Webpack's resolver. You can use require("path").resolve("path/to/bower/module") to get the full path to your Bower module.

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

Webpack bundle imports with an #

I am trying to bundle a Node Express server built with TypeScript using Webpack.
Compiling/Transpiling into one JavaScript file server.js works well, but the file does not seem to have all necessary imports included. If the file is in dist/server.js and there are still Node modules in node_modules/..., then starting the server using node dist/server.js works well. But if I copy the server.js to any other location without also copying the Node modules, and then start it, it does not find classes imported with an #.
Possible error:
mysystem:Desktop myuser$ node server.js
internal/modules/cjs/loader.js:582
throw err;
^
Error: Cannot find module '#overnightjs/core'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)
at Function.Module._load (internal/modules/cjs/loader.js:506:25)
at Module.require (internal/modules/cjs/loader.js:636:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object.<anonymous> (/Users/myuser/Desktop/server.js:1:1422)
at a (/Users/myuser/Desktop/server.js:1:172)
at Object.<anonymous> (/Users/myuser/Desktop/server.js:1:6473)
at a (/Users/myuser/Desktop/server.js:1:172)
at Object.<anonymous> (/Users/myuser/Desktop/server.js:1:6233)
at a (/Users/myuser/Desktop/server.js:1:172)
I think that I might have something missing in my Webpack configuration file, which is:
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: "./src/start.ts",
output: {
filename: "server.js",
path: path.resolve(__dirname, "dist")
},
node: {
// Need this when working with express, otherwise the build fails
__dirname: false, // if you don't put this is, __dirname
__filename: false, // and __filename return blank or /
fs: 'empty',
},
resolve: {
alias: {},
// Add '.ts', and '.tsx' as resolvable exteensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
externals: [nodeExternals()], // Need this to avoid error when working with Express
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['dist']
})
]
};
The versions I use:
Node (v10.13.0)
yarn (1.7.0)
Express (4.17.1)
TypeScript (3.7.4)
Webpack (4.41.4)
Webpack-CLI (3.3.10)
How can I also add imports starting with an # into the bundle in Webpack?
It is make sense, Your externals config tells webpack not to bundle node_modules into the bundle but require them at run time.
This means that if you are not copying node_modules to the new location, it will try to require it, and will fail.
Usually it is best practice not to bundle node_modules whenever you are creating a node bundle.
You have 2 choices:
Remove externals config - will increase bundle size cause it will contain all the node_modules that your app is using.
Installing a fresh node_modules on you new location, if this location is a production env, you can use npm install --production which will install only the dependencies without devDependencies.
Don't bundle modules when transpiling TypeScript. Standard practice is two download modules wherever you've deployed you server. Make sure to use the production flag if you're all done developing. npm i --production

NodeJs : Require is not defined

I'm using NodeJs and ReactJs, with webpack config.
When I build my app, I have an error on navigator console :
Require is not defined
module.exports = require("jquery");
So I tried to import RequireJs, like this :
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
}),
requirejs (['jquery'])
But I have the same error.
Is there any way to solve the problem?
You're trying to use a CommonJS module from within your browser. This will not work.
ref
Try setting webpack target to web.
module.exports = {
target: 'node',
//externals: [nodeExternals()],
[...]
};

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: {
// ...
},
}

How to build a ES6 express app with webpack 2 and babel?

Given the following Webpack 2 configuration, I want to write a express app using ES6. My .babelrc has only the es2015 preset:
const path = require('path');
module.exports = {
target: 'node',
entry: path.resolve(__dirname, 'src', 'server.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'server.bundle.js',
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
};
Running webpack and starting the server work fine, but when accessing the URL through the browser I get the following error:
Error: Cannot find module "."
at webpackMissingModule (/Users/Me/project/dist/server.bundle.js:18208:74)
I don't know whether it's due to the . in a require('./some/other/file') call (not all files are ES6, so these one use require() instead of import); or maybe some configuration I'm missing.
And also, given that stack trace I can't really map it to the original source file.
Thanks in advance
Update 1
I just realize I'm trying to use webpack to transpile ES6 code because I'm trying to replicate another build task (the one in mern.io), but I could do the same just with babel. Maybe there's no reason for using webpack on the serverside.
You need to install and add in webpack.config.js ExternalsPlugin:
plugins: [
new ExternalsPlugin({
type: 'commonjs',
include: path.join(__dirname, './node_modules/'),
}),
],
It helped me, I hope you too, because I spent a lot of time for solutions this problem)
Maybe the reason is that you are using target: "node" on webpack config. So that means it's creating your package for nodejs environment. Can you test after changing it to target: "web" for client transpile?
https://webpack.js.org/concepts/targets/

Resources