My question is very close to others which' answers I believe still require another WebPack-step which I want to avoid. But here is the story first:
I have a Node module (let's call it libfoo
) which provides some functionality and requires some third party modules,
and a small script main.js
which provides the main entry point and requires libfoo
:
main.js:
const foo = require('foo');
function main() {
foo.bar();
}
main();
I now want to turn libfoo
and main.js
into browser executable deliverables using WebPack. And I want libfoo
(which is quite large) to reside statically on the target systems while main.js
is very small and changes quickly (just imagine a test scenario where libfoo
is a module I want to test and main.js
contains changing code snippets)
I managed to create two packages - let's call them foo.browser.js
and main.browser.js
- which contain all the needed functionality, but I can't manage to make main.browser.js
correctly import foo.browser.js
.
I'm not very into WebPack yet - and up to now I couldn't figure out what's happening. My current approach looks like this: I build foo.browser.js
by running the following command:
webpack --output-filename foo.browser.js foo.js
And I have a webpack.config.js
for main.js
which looks like this:
module.exports = {
externals: {'foo': 'foo'}, // don't know what I'm doing here - added `commonjs` and `root` randomly
}
I turn main.js
into main.browser.js
with a very similar command: webpack --output-filename main.browser.js main.js
Now I try to use those both files in file called foo.html
containing these lines:
<script src="dist/foo.browser.js"></script>
<script src="dist/main.browser.js"></script>
But when I now open foo.html
in a browser I get
external "foo":1 Uncaught ReferenceError: foo is not defined
at Object.foo (external "foo":1)
at __webpack_require__ (bootstrap:19)
at Object../main.js (main.js:3)
at __webpack_require__ (bootstrap:19)
at bootstrap:83
at bootstrap:83
I fiddled around a little but (only randomly I'm afraid) but with no luck.
There is one constraint in my scenario which might be a difference to the other (working) examples I found: I need foo.browser.js
and main.browser.js
to be "final" i.E. they must run on the target system without any further postprocessing (like running WebPack again to turn them into a single bundle).
You can do it with this type of configuration:
module.exports = [{
resolve: {
modules: ["."],
},
entry: {
"foo": "foo.js",
},
output: {
path: `${__dirname}/build`,
filename: "[name].js",
sourceMapFilename: "[name].js.map",
library: "foo",
// libraryTarget: "umd",
}
},{
resolve: {
modules: ["."],
},
entry: {
"main": "main.js",
},
externals: {
"foo": "foo",
},
output: {
path: `${__dirname}/build`,
filename: "[name].js",
sourceMapFilename: "[name].js.map",
}
}];
This will produce two bundles in the build/
subdirectory. The key to get main
to use foo
is:
The "foo": "foo"
entry in externals
for creating the main
bundle. Whenever main
requests foo
it looks for it externally in a "module" named foo
. I've put "module" into quotes because when you have bundles in the UMD format and you load them with script
, there's no module system. Instead of looking for an actual module, the code will look for a global variable named foo
.
The foo
bundle exports itself into the global space as the variable foo
, which allows it to be used by main
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With