15

I am trying to include some fonts with a component library that I will distribute as an UMD bundle generated with Webpack and installed as an NPM module; the components make use of those fonts. The problem is that URLs pointing to the fonts in the generated bundle are incorrect and result in 404s when the application that uses the library is run.

For example, resolve-url-loader will output a URL of "/myfont.woff". But of course, that file is not actually available at that URL in the application unless the application that uses it does some configuration to copy that file and serve it at the expected path.

Is there a way to automatically make these fonts available (i.e., font-face: 'My Font' will work) when an application imports a component from my library, minimizing amount of configuration needed in the application that uses it?

For large files, I don't want to use url-loader and Base 64-encode them and I can't use a CDN.

xli
  • 1,298
  • 1
  • 9
  • 30

2 Answers2

10

I think the easiest way is to provide a .css file where your assets are being used through relative url(...) statements. Then, having something like

...
{
  test: /\.css$/,
  use: ['style-loader', 'css-loader'],
},
{
  test: /\.(eot|svg|ttf|woff|woff2|png|jpg)$/,
  use: ['file-loader'],
},
...

in their webpack.config.js and your .css file imported in their code, they will be able to use the assets by automatic transferring them to their output public directory (URLs should be also automatically adjusted in the result CSS bundle).

You might take a look, for instance, to Onsen UI library, that offers to embed their assets and styles through these files:

import 'onsenui/css/onsenui.css';
import 'onsenui/css/onsen-css-components.css';

Here is an example of how they use fonts through relative URLs there:

@font-face {
  font-family: 'Material-Design-Iconic-Font';
  src: url('../fonts/Material-Design-Iconic-Font.woff2') format('woff2'), url('../fonts/Material-Design-Iconic-Font.woff') format('woff'), url('../fonts/Material-Design-Iconic-Font.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
}
Dmitry Druganov
  • 2,088
  • 3
  • 23
  • 32
  • 1
    This works, but if the user imports the CSS file from JS, `css-loader` will still try to resolve the `.woff` file, so they will need to add `file-loader` to their Webpack config for that file. – xli Nov 10 '17 at 19:55
  • 2
    They could also set url resolution to false for `css-loader`, or import the CSS with just a `` tag in the HTML. But then they would need to add something to copy the needed files from `node_modules/my_library` to where they will be served, maybe with `CopyWebpackPlugin`. I wonder if there's any way to further reduce the configuration steps needed for the user. – xli Nov 10 '17 at 19:57
2

You need some loaders to do that task . to fix large file size issue i use file loaders.

      { test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?name=assests/fonts/[name].[ext]' },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader?mimetype=application/font-woff&name=assests/fonts/[name].[ext]' },
      { test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?mimetype=application/octet-stream&name=assests/fonts/[name].[ext]' },
      { test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml&name=assests/fonts/[name].[ext]' },
      { test: /\.(jpe?g|png|gif|ico)$/i, loader: 'file-loader?name=assests/images/[name].[ext]' },

finally use import statements to import the css files of the fonts

import from ./assets/fonts/abc.css

but make sure you have webpack css loaders setup

hannad rehman
  • 4,133
  • 3
  • 33
  • 55