I have an expression require which should get resolved in runtime but I can’t get my head around the webpack config for this simple example:
import something from 'module'; import pkg from './package.json'; let a; if (pkg.main) { a = require(pkg.main); }
The resulting build should contain the module
but also require ./package.json
and pkg.main
in runtime as commonjs modules — in other words, exclude them from the build.
My webpack.config.js
so far:
var webpack = require('webpack'); module.exports = { entry: './src/main.js', output: { filename: '[name].js', path: './build' }, target: 'node-webkit', plugins: [ new webpack.ExternalsPlugin('commonjs', './package.json') ], module: { noParse: /.min.js/, exprContextRegExp: /$^/, exprContextCritical: false, loaders: [ { test: /.js$/, loader: 'babel', exclude: /node_modules/ } ] } };
What happens now is the require for pkg.main
results in webpackMissingModule
exception and if I remove exprContextRegExp
, the require will use context.
Thanks for any help
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
For anyone wondering: you can solve it with this plugin:
function() { this.parser.plugin('call require', function(expr) { if (expr.arguments.length !== 1) { return; } const param = this.evaluateExpression(expr.arguments[0]); if (!param.isString() && !param.isConditional()) { return true; } }); }
Anything that cannot be resolved by webpack will be left as is.
Method 2
UPDATE: With NPM package
Install it: yarn add webpack-ignore-dynamic-require
Enable it
// webpack.config.js
const IgnoreDynamicRequire = require('webpack-ignore-dynamic-require');
module.exports = {
// ...
plugins: [
new IgnoreDynamicRequire()
]
}
Original answer: self made
In order to bundle a server application, I needed it, because it uses require
for loading local JSON files.
Based on self answer from Patrik Holčák, I was able to create a plugin for Webpack 4. It may work on Webpack 5.
class IgnoreDynamicRequire {
apply(compiler) {
compiler.hooks.normalModuleFactory.tap('IgnoreDynamicRequire', factory => {
factory.hooks.parser.for('javascript/auto').tap('IgnoreDynamicRequire', (parser, options) => {
parser.hooks.call.for('require').tap('IgnoreDynamicRequire', expression => {
// This is a SyncBailHook, so returning anything stops the parser, and nothing allows to continue
if (expression.arguments.length !== 1 || expression.arguments[0].type === 'Literal') {
return
}
const arg = parser.evaluateExpression(expression.arguments[0])
if (!arg.isString() && !arg.isConditional()) {
return true;
}
});
});
});
}
}
This is much more complicated than the previous answer, but we need to access the parser
object. After that, simply include it in your plugins
array:
plugins: [
new IgnoreDynamicRequire()
]
And all require
calls that does not resolve to a string are left as-is.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0