Include assets from webpack bundled npm package

ghz 6months ago ⋅ 86 views

I've been banging my head over this for a while, and am wondering if it's even possible to begin with. Thanks for any help with this!

The npm package

I've got an npm package which is basically a library of React components. This library has embedded stylesheets, which references assets like fonts and images from the CSS. These are then all bundled using webpack into my-package.js.

The config for this looks like:

var path = require('path');

module.exports = {
  module: {
    loaders: [
      {
        test: /\.js$/,
        loaders: ['babel-loader'],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        loader: "style-loader!css-loader"
      },
      {
        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
        loader: 'file-loader'
      },
      {
        test: /\.styl$/,
        loader: 'style-loader!css-loader!stylus-loader'
      }
    ]
  },
  entry: [
    './lib/components/index.js',
    './lib/index.styl'
  ],
  output: {
    path: path.join(__dirname, 'build/'),
    filename: 'my-package.js'
  }
}

With ./lib/components/index.js looking like:

import '../index.styl';
import MyComponent from './my-component.js';

export {
  MyComponent
}

So far, so good.

The application

Now in another code base I've got the main application, which install this npm package.

My application root requires this package...

import MyPackage from 'my-package';

And is then itself webpack bundled and loaded onto the browser. All the scripts and style blocks are bundled correctly, however the styles which reference the assets are using the relative url from the npm package itself, therefore giving me 404s from the application.

console errs

Is there any way to tell webpack to resolve these images from node_modules/my-package/build/[webpack-generated-name].jpg ?

My application's webpack config looks like this:

var path = require('path'),
    webpack = require('webpack');

module.exports = {
  devtool: '#eval-source-map',
  entry: [
    'my-package',
    'webpack/hot/only-dev-server',
    './app/index.js',
  ],
  output: {
    path: path.join(__dirname, 'build/static'),
    filename: 'bundled.js',
    publicPath: '/',
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  resolve: {
    extensions: ['', '.js']
  },
  resolveLoader: {
    'fallback': path.join(__dirname, 'node_modules')
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loaders: ['react-hot', 'babel'],
        exclude: /node_modules/,
        include: __dirname
      },
      {
        test: /\.css?$/,
        loader: "style-loader!css-loader",
        include: __dirname
      },
      {
        test: /\.(jpg|jpeg|ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        loader: 'file-loader'
      },
      {
        test: /\.styl$/,
        loader: 'style-loader!css-loader!stylus-loader'
      }
    ]
  }
};

Answers

To resolve the issue where your npm package's stylesheets reference assets (like fonts and images) using relative paths that lead to 404 errors when used in another application, you need to configure Webpack in your application's webpack configuration to correctly resolve these paths from the npm package's build directory.

Here’s a step-by-step approach to achieve this:

1. Update file-loader Configuration in Your Application's Webpack Config

In your application's webpack configuration, modify the file-loader configuration to handle files from your npm package:

module: {
  loaders: [
    // Other loaders...
    {
      test: /\.(jpg|jpeg|png|gif|svg|woff|woff2|ttf|eot)$/,
      loader: 'file-loader',
      options: {
        outputPath: 'static/', // Specify the output path where files will be placed
        publicPath: '/build/static/' // Specify the public URL of the output directory
      }
    },
    // Other loaders...
  ]
}
  • outputPath: Specifies the directory within your application's build output where files processed by file-loader will be placed. Adjust this path as per your application’s structure.
  • publicPath: Specifies the public URL prefix for the files. This is crucial as it ensures that URLs in your CSS files are correctly resolved relative to the application’s build output.

2. Ensure Correct Import Paths in Your Application

When importing your npm package's components and styles into your application, make sure the paths are correct. Typically, you should import your package like this:

import MyPackage from 'my-package';

Webpack will resolve this to node_modules/my-package/build/my-package.js automatically.

3. Verify CSS URLs in Your npm Package

Ensure that URLs in the CSS files of your npm package are relative to the build directory where they end up after bundling. For example, if your CSS references an image like this:

.someClass {
  background-image: url('images/some-image.jpg');
}

After bundling, this should resolve to something like /build/static/images/some-image.jpg relative to your application's root.

4. Rebuild Your Application

After making these changes, rebuild your application using Webpack to ensure that the assets from your npm package are correctly resolved and copied to the output directory specified in outputPath.

Summary

By configuring file-loader in your application's Webpack configuration with the outputPath and publicPath options, you ensure that assets referenced in your npm package’s stylesheets are correctly resolved and served from the correct path within your application’s build output. This approach should resolve the 404 errors you were encountering due to incorrect asset paths. Adjust the paths (outputPath and publicPath) according to your specific project structure and deployment environment.