How to ship assets (images, fonts) in a NPM package/library bundled by Webpack?
See original GitHub issueNote: I haven’t created a question on StackOverflow, because in fact they already exist, two, and both don’t have a good conclusion/solution for the problem, just a workaround, which is insufficient.
Those are the SO’s questions:
https://stackoverflow.com/questions/37171767/how-to-load-assets-correctly-from-webpack-generated-npm-package https://stackoverflow.com/questions/36559850/include-assets-from-webpack-bundled-npm-package
I have the exact same problem as the 1) question. I want to be able to ship assets in an NPM package bundled by Webpack, but not necessarily I have control over the Webpack from the app who will use that library, i.e I can’t just use the solution proposed on the 2) question.
The package is already well configured with output.library, output.libraryTarget set. The functionality of it works perfectly, the problem is only with their assets. I can see that they were outputted to the dist file inside of node_modules/myLibrary as expected using file-loader, but they aren’t served correctly when the library require them, because they are in the node_modules of the library, not in the folder of the main app for instance.
The generated code of the library seems like (the part regarding the assets):
/***/ "./src/assets/icons/add-tap-pixel.svg":
/*!********************************************!*\
!*** ./src/assets/icons/add-tap-pixel.svg ***!
\********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("module.exports = __webpack_require__.p + \"88112c78dd50d85634e6a85d3454bd9d.svg\";\n\n//# sourceURL=webpack://connections-component/./src/assets/icons/add-tap-pixel.svg?");
And when the library uses it, it tries to load the asset using the publicPath configuration as expected in the code via the __webpack_require__.p - the problem is just that the assets aren’t there at all. They’re in the node_modules/myLibrary/dist. And no, as I said, I can’t just add a rule on the main app that uses the library to copy those files, because this library is supposed to be used in some other places which I not necessarily will have control over it build process.
I have knowledge that one solution would be to use url-loader for all assets, thus making them available directly via the JS code, but this is not what I’d like to do, as I want to have caching individually on each asset file.
Does anyone have a better solution for this? Thanks!
Issue Analytics
- State:
- Created 5 years ago
- Reactions:74
- Comments:38 (11 by maintainers)
Top Related StackOverflow Question
tl;dr
url-loaderso your consumers never know about the assetsLet’s recap the use-case: we want to distribute some assets along with our library. Here are some restrictions for our solution:
The problem
Using
file-loaderties the library code to a public path which is hard to configure. Moreover, I would require the library consumer to use webpack or its runtime.Solution 1: don’t ship the assets, embed them
By using
url-loaderall matching assets will be included as URLs inside the final JS bundle. A simple configuration could be:Solution 2: externalize assets
Instead of bundling the assets inside the library, they are distributed as separate files of your package. For example:
Here,
styles.cssis not produced by webpack. It is not referenced from any file of your bundle. The library consumers must manage this file themselves! So they want to usemy-module? Perfect! They mustrequire("my-module")and loadmy-module/styles.csswhatever is there preferred solution.Personally I would use
css-loader:This is not the library business to handle this.
No I won’t because your use-case is very localized and would be better handled on StackOverflow.
I think the main issue is around defining the public path. If I create a library that has a component that uses an image it will construct a path based off the public path defined when the library is built. Ideally when consuming that library you want to update the public path to be whatever is now appropriate for that consumer. They can then include the image as necessary to get it output to the new public path. The issue is the library is not aware of this change and still looks at the old path. Anyone aware of a good way to handle this situation?