How to ship assets (images, fonts) in a NPM package/library bundled by Webpack?

See original GitHub issue

Note: 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:closed
  • Created 5 years ago
  • Reactions:74
  • Comments:38 (11 by maintainers)

github_iconTop GitHub Comments

33reactions
ooflorentcommented, Dec 20, 2018

tl;dr

  • Solution 1: use url-loader so your consumers never know about the assets
  • Solution 2: you don’t care how your consumer includes your assets, that’s their problem

Let’s recap the use-case: we want to distribute some assets along with our library. Here are some restrictions for our solution:

  • it must not require the library consumer to use webpack
  • it must be easy for the library consumer to include the assets

The problem

Using file-loader ties 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-loader all matching assets will be included as URLs inside the final JS bundle. A simple configuration could be:

{
  test: /\.(jpg|png|svg)$/,
  loader: "url-loader",
  options: {
    limit: Infinity // everything
  }
}

Solution 2: externalize assets

Instead of bundling the assets inside the library, they are distributed as separate files of your package. For example:

my-module
├── dist
│   └── bundle.js
├── styles.css
└── package.json

Here, styles.css is 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 use my-module? Perfect! They must require("my-module") and load my-module/styles.css whatever is there preferred solution.

Personally I would use css-loader:

import "my-module/styles.css"
import MyModule from "my-module"

This is not the library business to handle this.


Can you please re-open the issue […]?

No I won’t because your use-case is very localized and would be better handled on StackOverflow.

32reactions
rikbrowningcommented, Dec 19, 2018

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?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Include assets from webpack bundled npm package
This library has embedded stylesheets, which references assets like fonts and images from the CSS. These are then all bundled using webpack into ......
Read more >
Package exports - webpack
The exports field in the package.json of a package allows to declare which module should be used when using module requests like import...
Read more >
A Guide to Managing Webpack Dependencies - Toptal
A Guide to Managing Webpack Dependencies. The Webpack module bundler processes JavaScript code and all static assets, such as stylesheets, images, and fonts....
Read more >
how to ship assets images fonts in a npm package library bundled ...
how to ship assets images fonts in a npm package library bundled by webpack 技术、学习、经验文章掘金开发者社区搜索结果。掘金是一个帮助开发者成长的社区,how ...
Read more >
Customizing image bundling in webpack - Media Jams
Developers can customize image bundling using Webpack, which provides asset modules for using files (containing the fonts and icons).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found