Name: webpack-alternate-require-loader
Owner: Formidable
Description: Webpack alternate require loader
Created: 2016-11-21 22:20:01.0
Updated: 2017-02-20 04:17:08.0
Pushed: 2017-04-06 10:49:53.0
Homepage: null
Size: 11
Language: JavaScript
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
This loader allows webpack to approximate arcane Node.js require
semantics for
advanced use cases when a normal require
doesn't suffice
The Problem
Let's say you have a project like:
index.js
outside-of-resolution-path/node_modules/foo
if you try:
rc/index.js
AD: Fails
foo = require("foo");
This will fail, because src/outside-of-resolution-path/node_modules
is not in
the resolution path, which is:
node_modules
_modules
The Module Pattern
One solution to this problem is called the “module pattern“, which adds
an extra file to start Node.js module resolution from a different directory.
Basically, say we add a simple file in a directory outside of the current
Node.js require
resolution path:
rc/outside-of-resolution-path/require.js
e-export the `require` to start resolution from `src/outside-of-resolution-path/node_modules`
le.exports = require;
And switched our importing code to:
rc/index.js
OOD: Module pattern (re-exported `require`) works!
foo = require("./outside-of-resolution-path/require")("foo");
this works because the Node.js resolution path starts from the re-exported
require
:
outside-of-resolution-path/node_modules
node_modules
_modules
Webpack
The above pattern works just fine for Node.js. Unfortunately, this non-standard
require
usage fails in Webpack.
Enter this loader, which allows a bridge for webpack builds to also use the module pattern / other non-standard requires.
The loader is available via npm:
m install --save webpack-alternate-require-loader
The plugin takes a configuration object of a re-exported module path to search for in code and then a resolved path to that same code on disk like:
ODE_TO_MATCH": require.resolve("REEXPORTED_CODE_PATH")
/outside-of-resolution-path/require": require.resolve("./outside-of-resolution-path/require")
It will then effectively transform something like:
foo = require("CODE_TO_MATCH")("foo");
foo = require("./outside-of-resolution-path/require")("foo");
to:
foo = require("/RESOLVED/PATH/TO/foo");
This effectively simulates what Node.js would do at execution time to the code.
A basic configuration:
le.exports = {
dule: {
loaders: [
{
test: /\.js$/,
loader: "webpack-alternate-require-loader",
query: JSON.stringify({
"./outside-of-resolution-path/require": require.resolve("./outside-of-resolution-path/require")
})
}
]
Additional examples are provided in:
demo/webpack.config.js
. If you have a clone of this
repository with devDependencies
, you can run:
m run build-demo-wp
and see the results in the demo
directory.
Do I have to use exactly the module / require pattern above?
Yes. Although Node.js can figure out:
altRequire = require("./outside-of-resolution-path/require");
foo = altRequire("foo");
This plugin currently cannot because it is naive and uses regexes. You must follow the form:
foo = require("./outside-of-resolution-path/require")("foo");
Fortunately, if you are using
babel-plugin-replace-require
,
you can easily produce require
expressions that work with this plugin.
Why can't I just prepend the non-standard node_modules
path in code?
See the module pattern discussion page. Basically, with top-level
dependencies you can. But with nested dependencies and modern npm
/ yarn
the real depended on code can be located anywhere in the tree. And you need
the node_modules
search path to be different than normal.
You're using regexes? Yuck!
Indeed. But that's basically how webpack / some loaders roll. We stick to an easy pattern and avoid the cost of a full babel install + parsing. But, we may be open to real code parsing in the future.
Contributions welcome! Make sure to pass $ npm run check
.