2

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

Jesse Reza Khorasanee
  • 3,140
  • 4
  • 36
  • 53

3 Answers3

1

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

Harkal
  • 1,770
  • 12
  • 28
1

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.

User 28
  • 4,863
  • 1
  • 20
  • 35
  • Thanks for the help @User 28! I just tried the above and switching to absolute urls and both unfortunately didn't work. I'm getting suspicious it's the async `process.client ? ...` import that is causing issues and will try testing this next. – Jesse Reza Khorasanee Oct 13 '20 at 23:37
  • For the first solution make sure your file size does not exceed the limit. Then after you run build you won't see `img` directory. And you have to run build on the component not your app. It's the same thing when you use other npm packages. – User 28 Oct 14 '20 at 04:11
  • 1
    For the second solution, `../assets` and `@assets` are not the absolute path. If you use vue-cli you have to put that asset file to public directory and then use as `/icon.svg` then build, the webpack will do nothing with this absolute path. Copy that public to your app which is `static` directory in nuxt. – User 28 Oct 14 '20 at 04:15
  • @JesseRezaKhorasanee – User 28 Oct 14 '20 at 04:16
0

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

Jesse Reza Khorasanee
  • 3,140
  • 4
  • 36
  • 53