How to send a npm package's static assets to a nuxt application?

1.7k views Asked by At

I'm trying to send assets from an npm package to a nuxt application. Has anyone had success doing this?

I have an vue component as an npm package with stucture:

-src/
 -assets/
  -noun-filter.svg

This vector image is loaded in the vue component's template in this npm package like so:

<img class="filter-icon" :src="require('../assets/noun-filter.svg')"/>

The above works fine for use when testing this package on it's own.

However when I import the npm package in a nuxt app like so:

<script>
export default {
  name: "NuxtMainPage",
  components: {
    NpmImportedComponent: process.client
      ? () => import("@myname/mynpmpackage").then(m => m.Content)
      : null
  },
//...
}
</script>

When I run the app I get a 404 for the svg.

Nuxt looks for the file in http://localhost:3000/_nuxt/img/noun-filter.b16c5666.svg where it does not exist.

Is there something I'm missing here? Why does nuxt change the path of the assets? Why is it not just looking in the node modules like we would expect?

How does one send static assets via an npm package to nuxt?

What I've tried

  • Tried using url-loader in my app. Url's were still getting redirected in nuxt
  • Import items with import @myname/mypackage/src/assets/noun-filter.svg in the nuxt app
  • Switch the relative urls in npm package from ../assets to @assets
  • Move the assets folder to the root of the npm package and add it to included files in package.json

All of the above had the same result with nuxt looking for the image at: http://localhost:3000/_nuxt/img/noun-filter.b16c5666.svg

3

There are 3 answers

4
User 28 On BEST ANSWER

I think there is no easy solution here.

First solution, use url-loader to inline your asset file as a base-64 data url. See Asset URL Handling.

vue.config.js

...
  chainWebpack: config => {
    config.module
      .rule('images')
        .use('url-loader')
          .loader('url-loader')
          .tap(options => Object.assign(options, { limit: 10240 })) // default is 4096
  }
...

From Relative Path Imports

Second solution, copy your asset file to static directory and use absolute url instead.

Related post.

6
Harkal On

make your assets in a standalone directory static and in your tsconfig.json of your package include the static directory to the rootDirs field like the following example

{
    ...
    "compilerOptions": {
        ...
        "rootDirs": [
            "src",
            "static",
            ...
        ]
        ...
    }
    ...
}

and republish your package and the static files ll also be available

0
Jesse Reza Khorasanee On

For those who find this and none of the other answers work, use vue-svg-inline-loader.

in your component template

<img svg-inline src="'@/../assets/noun-filter.svg'"/>

in vue.config.js

//...
      config.module
        .rule('vue')
        .use("vue-svg-inline-loader")
        .loader("vue-svg-inline-loader") 
//...   

Pretty painless and works well for me. It has the downside that your svg's end up bundled with your package but url-loaders will do the same