Webpack has been very useful to us in writing isomorphic Javascript, and swapping out npm
packages for browser globals when bundling.
So, if I want to use the node-fetch
npm
package on Node.js but exclude it when bundling and just use the native browser fetch
global, I can just mention it in my webpack.config.js
:
{ externals: { 'node-fetch': 'fetch', 'urlutils': 'URL', 'webcrypto': 'crypto', // etc } }
And then my CommonJS requires const fetch = require('node-fetch')
will be transpiled to const fetch = window.fetch
(or whatever it does).
So far so good. Here's my question: This is easy enough when requiring entire modules, but what about when I need to require a submodule / individual property of an exported module?
For example, say I want to use the WhatWG URL standard, isomorphically. I could use the urlutils
npm
module, which module.exports
the whole URL class, so my requires look like:
const URL = require('urlutils')
And then I can list urlutils
in my externals
section, no prob. But the moment I want to use a more recent (and more supported) npm
package, say, whatwg-url
, I don't know how to Webpack it, since my requires look like:
const { URL } = require('whatwg-url') // or, if you don't like destructuring assignment const URL = require('whatwg-url').URL
How do I tell Webpack to replace occurrences of require('whatwg-url').URL
with the browser global URL
?
1 Answers
Answers 1
At first I would like to highlight that I am not a webpack expert. I think there is a better way of bundling during the build time. Anyway, here is my idea:
webpack.config.js
module.exports = { target: "web", entry: "./entry.js", output: { path: __dirname, filename: "bundle.js" } };
entry.js
var URL = require("./content.js"); document.write('Check console'); console.log('URL function from content.js', URL);
content.js
let config = require('./webpack.config.js'); let urlutils = require('urlutils'); let whatwgUrl = require('whatwg-url'); console.log('urlutils:', urlutils); console.log('whatwgUrl', whatwgUrl); module.exports = { URL: undefined }; if (config.target === 'web') { module.exports.URL = urlutils; } else { module.exports.URL = whatwgUrl.URL; }
index.html
<html> <head> <meta charset="utf-8"> </head> <body> <script type="text/javascript" src="bundle.js" charset="utf-8"></script> </body> </html>
As I said in the comment, it's going to bundle two libs for the Web bundle - waste of space.
Now, for NodeJS, you change the target
from web
to node
and it should take the other library. https://webpack.github.io/docs/configuration.html#target
I've found a module for 'isomorphic' apps: https://github.com/halt-hammerzeit/universal-webpack
I think you could try to use two, separate middle content.js
files as a parameters for the module. One containing urlutis
and the second whatwg-url
. Then it would dynamically recognize what it compiles your files for and use the proper module.
Hope it helps.
0 comments:
Post a Comment