I need help here. I am bundling a custom library (named for the example LibraryJS and it uses lodash as dependency.
In the webpack configuration I setup lodash as an external dependency like so:
{
externals: {
"lodash"
}
}
It works great. But then when I want to use this library inside another project, I got the following error: "libraryjs.js:77 Uncaught ReferenceError: lodash is not defined"
which is the following line:
/***/ }),
/* 1 */
/***/ (function(module, exports) {
=> module.exports = lodash;
/***/ }),
The fact is, I am using lodash as well in my project, so it should be working. What am I doing wrong?
By the way, I am using gulp + browserify to bundle my project and gulp + gulp-webpack to bundle the library.
Edit: I found a way to fix the error, but I really don't want to stick with this fix because it's really... ugly... See bellow:
const lodash = require('lodash')
window.lodash = lodash; // <= The fix, ugh
Thank you for the help!
I had a similar situation trying to build a library - this is the solution I found.
Goal: Build a library that depends on Lodash without including Lodash in that library bundle. The consumer of the library is responsible for making Lodash available to our library.
I used the Authoring Libraries section of the documentation to put together this solution.
Specifically these two sections:
There is an example project showing this configuration as well: https://github.com/webpack/webpack/tree/master/examples/externals
// "my-lib" package.json
{
"name": "my-lib",
"version": "0.5.0",
"main": "my-lib.js",
"peerDependencies": {
"lodash": "^4.17.5"
},
"devDependencies": {
"webpack": "^4.5.0",
"webpack-cli": "^2.0.14"
}
}
Here's our example library that imports lodash and uses it. Note that whilst we depend on lodash, it won't be included in our bundle.
// lib-entry.js
import _ from "lodash";
export default function doubleUp(listOfNum){
// Do something using lodash
let result = _.flatMap(listOfNum, (i) => [i, i]);
return result;
}
Here's our webpack.config.js
that bundles our library, but excludes lodash from the bundle:
// "my-lib" webpack.config.js
module.exports = {
entry: {
'my-lib': './lib-entry.ts',
},
output: {
filename: '[name].js',
// [1]
libraryTarget: 'umd',
/*
[2]
NOTE: until this issue is fixed: https://github.com/webpack/webpack/issues/6525
we need to define `globalObject` in Webpack 4 to correctly build a universal library
(i.e. node and browser compatible).
*/
globalObject: 'this',
},
externals: {
// [3]
'lodash': {
commonjs: 'lodash',
commonjs2: 'lodash',
amd: 'lodash',
root: '_',
},
},
resolve: {
extensions: ['.js'],
},
};
[1] This tells Webpack to bundle our library for different environments (so it will work when loaded via: browser scripts, Node CommonJS, AMD, and downstream Webpack projects). NOTE: This is needed otherwise the externals
config in [3] will output an incorrect undefined
module in your bundle.
[2] Workaround for a Webpack 4 bug (if you're in the future then check if this is still relevant and needed). Also described here: https://stackoverflow.com/a/49119917/81723
[3] From the documentation: "set the externals
option to define dependencies that should be resolved in the target environment". We're telling Webpack to exclude lodash from the library bundle and that consumers of our library are responsible for providing it.
Define an application that depends on our my-lib
library:
// "my-app" package.json
{
"name": "my-app",
"version": "1.0.0",
"dependencies": {
"lodash": "^4.17.5",
"my-lib": "^0.5.0"
},
"devDependencies": {
"webpack": "^4.5.0",
"webpack-cli": "^2.0.14"
}
}
Our application imports lodash into its environment (because our library needs it) and then use our library:
// app-entry.js
import _ from "lodash";
import doubleUp from "my-lib";
let result = doubleUp([1, 2, 3]);
console.log(result); // [1, 1, 2, 2, 3, 3]
Here's the webpack.config.js
for our application:
// "my-app" webpack.config.js
const path = require('path');
module.exports = {
entry: {
'my-app': './app-entry.ts',
},
output: {
filename: '[name].js',
},
resolve: {
extensions: ['.js'],
alias: {
/*
[1]
Resolve all `lodash` requests to the same location otherwise
we end up with two versions loaded into the bundle, one
for `my-lib` and one for `my-app`.
*/
lodash: path.resolve('./node_modules/lodash/index.js'),
}
},
};
[1] This alias
config means anytime Webpack encounters require('lodash')
or import ... from "lodash";
it will resolve it to this one module on disk. I found I had to do this to avoid getting multiple versions of lodash loaded into my bundle. Webpack was including one version for my-app
and one for my-lib
, but this fixes it so that both get the same version.
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