ModusCreateOrg / ionic-vue

Vuejs integration for Ionic versions 4 and 5
MIT License
271 stars 26 forks source link

Ionicons not working #120

Closed EdwardMillen closed 4 years ago

EdwardMillen commented 4 years ago

Hi, I've just started a new project using the latest versions of everything (@ionic/core@5.1.1 and @modus/ionic-vue@1.3.8) but I can't get Ionicons to show at all.

For example with <ion-icon name="add"></ion-icon> when running the dev server, the browser seems to be trying to load the icon from /svg/add.svg, but that HTTP request is actually returning the same HTML code as the root page (and any other URL that doesn't exist). If I run a build, the icon files don't seem to show up anywhere in the output folder at all.

What am I missing?

Thanks

michaeltintiuc commented 4 years ago

HI @EdwardMillen I can confirm this is also happening with my setup, something must've change, looking into it. Thanks for reporting!

michaeltintiuc commented 4 years ago

Hey @EdwardMillen turns out the usage of icons changed, I've checked some of the internal components as well as the React version of Ionic, you've got several options, it's up to you to decide which one is better for your use case

1. Add all required icons globally

// main.js
import { addIcons } from 'ionicons'
import { add } from 'ionicons/icons'
addIcons({ add })

// your component
<ion-icon name="add"></ion-icon>

2. Set icon to imported value

<template>
  <ion-icon :icon="icons.add"></ion-icon>
</template>

<script>
import { add } from 'ionicons/icons'

export default {
  data() {
    return { icons: { add } };
  }
}
</script>

3. Add icons on a need-to-need basis

<template>
  <ion-icon name="add"></ion-icon>
</template>

<script>
import { addIcons } from 'ionicons'
import { add } from 'ionicons/icons'
addIcons({ add })

export default {
  ...
}
</script>

I'll make sure to add this to README

EdwardMillen commented 4 years ago

Thanks a lot, at least now I have options :D

When I was initially trying to troubleshoot this, I tried some similar looking code I found elsewhere, but it didn't work (and for some reason the call to addIcons was much more complex). Your version (the global one) seems to work fine though :)

EdwardMillen commented 4 years ago

Just as a follow up to this, it turns out methods 1 and 3 don't work with any of the icons with dashes in the name (like cart-outline, cart-sharp etc). Method 2 still works though.

After digging around in the source code, I've found that adding them like this fixes it:

import { addIcons } from 'ionicons'
import { add, cartOutline } from 'ionicons/icons'
addIcons({ add, "cart-outline": cartOutline })
edtownend commented 4 years ago

OK, this got weirder yet for me. I'm using @vue/cli-service@4.4.1 and @ionic-vue@0.0.9.

None of the solutions worked for me because the svgs always got output to /img/, while the app was looking for them in /svg/. Couldn't figure out what was causing it so I ended up altering the webpack config via vue.config.js like this:

module.exports = {
  chainWebpack: (config) => {
    config.module
      .rule('svg')
      .use('file-loader')
      .loader('file-loader')
      .tap((options) => {
        options.outputPath = 'svg';
        options.name = '[name].[ext]?[contenthash]';
        return options;
      });
  },
};

Interestingly after that, all of the icons end up in /svg without me having to do any of the import stuff?

EdwardMillen commented 4 years ago

I'm not sure if things are different in @ionic/vue (and also it might depend what version of @ionic/core you are using?), but mine (using this project, which is @modus/ionic-vue) didn't/doesn't seem to output svgs anywhere at all. It does seem like it looks for unknown icons in /svg/ by default, but I think that is meant to be as a fallback for the case of adding your own custom icons, not the built in ones.

In my project now, with the correct import statements etc above, they actually get defined as data:image/svg+xml etc... URLs (or something, not sure what the correct terminology is for that). So there are still no actual icon files involved anywhere, the actual SVG code is imported into JavaScript variables I think, and then used directly from there.

(I didn't try changing anything in Webpack at all, as I don't understand it yet)

michaeltintiuc commented 4 years ago

@edtownend switching to latest ionic-vue and ionic/core should fix this for you. ionicons used to rely on this webpack config awhile back, they have switched to imports in order to not import all the icons and leverage tree-shaking.

edtownend commented 4 years ago

@michaeltintiuc Thanks, I only had @ionic/vue installed and not @ionic/core. That seemed to do the trick - though I had to also install the older ^4.6.3 version of ionicons because I got the error Interface 'HTMLIonIconElement' cannot simultaneously extend types 'IonIcon' and 'IonIcon'. with the bundled 5.x ionicons

grgur commented 4 years ago

Thanks for sharing this know-how with the community @edtownend 🙌

509dave16 commented 4 years ago

And if for some reason you wanted to add all of the icons and use their kebab case name, you could do something like the following:

import { addIcons } from 'ionicons'
import * as allIcons from 'ionicons/icons'
import _ from 'lodash'
addIcons(_.mapKeys(allIcons, (value, key) => _.kebabCase(key))