Rollup image import with only file copy and preserve import

Viewed 610

I spend a lot of time and try a few plugin with rollup to preserve normal image import.

When I was compiling with tsc i had no issue with compiling as my image import was compiled from:

import myImage from '../../images/my-image.jpg'

to

const myImage = tslib_1.__importDefault(require( '../../images/my-image.jpg'));

But now with rollup the only proper way I found to import image was with @rollup/plugin-image but it increased the bundle size by 30% due to base64 conversion.

I tried @rollup/plugin-url but this plugin create a my-image.js file that export the path of my image. This is not working when importing the component from an other application as webpack (for example) doesn't understand that this path have to be imported.

I also tried rollup-plugin-rebase, It's really what I am looking for but had a problem with preserveModule so the import was bundled like this

import myImage from '../Title/my-image.jpg' (Title is the last folder on the same subfolder)

I also tried rollup-plugin-smart-assets but also had path problems with path.

The last solution I was thinking is to ignore image parsing in rollup and only copy the images folder with the copy plugin. But I don't know how to ignore those file parsing in rollup.

Thank you, don't hesitate to ask me if it's not clear or if you need more precision.

1 Answers

I had the same problem and couldn't find an existing plugin that did exactly what I wanted.

I ended up writing this small plugin to let me ignore image imports by marking them as external in the resolveId hook. That leaves them as for example import whatever from "assets/whatever.png" in the library, so the consuming application's bundler can handle this image how it wants to.

function externalAsset({ include, copyTargets, assetTargetDir }) {
  const isMatchSingle = function (include, module) {
    return new RegExp(include, "g").test(module);
  };

  const isMatch = function (include, module) {
    if (include === undefined) return true;
    return Array.isArray(include) ? include.some((i) => isMatchSingle(i, module)) : isMatchSingle(include, module);
  };

  return {
    name: "rollup-plugin-external-asset",
    resolveId(source) {
      if (!isMatch(include, source)) return null;
      copyTargets && copyTargets.push({ src: source, dest: assetTargetDir });
      return { id: source, external: true };
    },
  };
}

Which I then use from the rollup plugins config like this in my case to target imports of .png image files specifically:

import copy from "rollup-plugin-copy";

const copyTargets = [];

...

plugins: [
    externalAsset({
        include: [".png$"],
        copyTargets: copyTargets,
        assetTargetDir: "dist/assets",
    }),
    copy({ targets: copyTargets, verbose: true }),
]

I then feed those image paths to the rollup-plugin-copy plugin which copies the ignored image files into the distribution.

Related