Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vector icon not shown in react native for web #1425

Closed
2 tasks
aartigehlot opened this issue Mar 30, 2022 · 9 comments
Closed
2 tasks

vector icon not shown in react native for web #1425

aartigehlot opened this issue Mar 30, 2022 · 9 comments

Comments

@aartigehlot
Copy link

Environment

Description

Describe your issue in detail. Include screenshots if needed.

Demo

You can use https://snack.expo.io/ to create a demo that can help users to better understand your problem.

@hsavit1
Copy link

hsavit1 commented Apr 27, 2022

there are not enough steps or details here to warrant an issue. this should be closed

@gciluffo
Copy link

gciluffo commented May 13, 2022

I am running into the same issue where the icon is not displaying in RNW with the newest version of react-native-vector-icons:
Screen Shot 2022-05-13 at 12 40 07 PM

I have no idea if its related to what @aartigehlot is seeing. Also im not sure if this is an issue related to this library and RNW or webpack config issue.

Here is the repo with the issue reproduced: https://github.com/gciluffo/react-native-web
Here is the commit with changes attempting to get icons working in web: gciluffo/react-native-web@80d608a

webpack.js.config:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const appDirectory = path.resolve(__dirname, '../');

const compileNodeModules = [
  'react-navigation',
  '@react-navigation',
  'react-native-uncompiled',
  'react-native-web',
  '@mobily/stacks',
  'react-native-vector-icons',
].map(moduleName => path.resolve(appDirectory, `node_modules/${moduleName}`));

const babelLoaderConfiguration = {
  test: /\.m?[t|j]sx?$/,
  include: [
    path.resolve(__dirname, 'index.web.js'),
    path.resolve(appDirectory, 'src'),
    ...compileNodeModules,
  ],
  use: {
    loader: 'babel-loader',
    options: {
      presets: ['module:metro-react-native-babel-preset'],
      plugins: [['react-native-web']],
    },
  },
};

const svgLoaderConfiguration = {
  test: /\.svg$/,
  loader: '@svgr/webpack',
};
const imageLoaderConfiguration = {
  test: /\.(gif|svg|jpg|png)$/,
  loader: 'file-loader',
};
const ttfLoaderConfig = {
  test: /\.ttf$/,
  loader: 'url-loader', // or directly file-loader
  include: [
    path.resolve(appDirectory, 'node_modules/react-native-vector-icons'),
  ],
};

module.exports = {
  entry: {
    // load any web API polyfills
    // path.resolve(appDirectory, 'polyfills-web.js'),
    // your web-specific entry file
    app: path.join(__dirname, 'index.web.js'),
  },
  // configures where the build ends up
  output: {
    path: path.resolve(appDirectory, 'dist'),
    publicPath: '/',
    filename: 'rnw.bundle.js',
  },
  devServer: {
    historyApiFallback: true,
  },
  resolve: {
    // If you're working on a multi-platform React Native app, web-specific
    // module implementations should be written in files using the extension
    // `.web.js`.
    extensions: ['.web.tsx', '.web.ts', '.tsx', '.ts', '.web.js', '.js'],
    alias: {
      'react-native$': 'react-native-web',
    },
  },
  module: {
    rules: [
      babelLoaderConfiguration,
      imageLoaderConfiguration,
      svgLoaderConfiguration,
      ttfLoaderConfig,
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DefinePlugin({
      // See: <https://github.com/necolas/react-native-web/issues/349>
      __DEV__: JSON.stringify(true),
    }),
  ],
};

App.tsx:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React, {useEffect} from 'react';

import {NoteList, NoteDetail} from './screens';
import {StacksProvider} from '@mobily/stacks';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {Platform, Text} from 'react-native';

const Stack = createNativeStackNavigator();

const linking = {
  prefixes: ['http://localhost:8080'],
  config: {
    initialRouteName: 'NoteList' as 'NoteList' | 'NoteDetail' | undefined,
    screens: {
      NoteList: 'notes',
      NoteDetail: 'note-detail/:id',
    },
  },
};

function App() {
  useEffect(() => {
    if (Platform.OS === 'web') {
      const iconFontStyles = `@font-face {
  src: url(${require('react-native-vector-icons/Fonts/FontAwesome.ttf')}) format(truetype);
  font-family: "FontAwesome";
}`;

      // Create stylesheet
      const style = document.createElement('style');
      style.appendChild(document.createTextNode(iconFontStyles));

      // Inject stylesheet
      document.head.appendChild(style);
    }
  }, []);

  return (
    <StacksProvider spacing={4}>
      <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
        <Stack.Navigator>
          <Stack.Screen name="NoteList" component={NoteList} />
          <Stack.Screen name="NoteDetail" component={NoteDetail} />
        </Stack.Navigator>
      </NavigationContainer>
    </StacksProvider>
  );
}

export default App;

When inspecting the DOM I can see that the font-family is included:
Screen Shot 2022-05-13 at 12 39 17 PM

@Uzef1997
Copy link

Uzef1997 commented Jun 8, 2022

Hi, @gciluffo did you find any solution? I am also running into the same issue please let me know if there is any solution with this

@gciluffo
Copy link

gciluffo commented Jun 8, 2022

@Uzef1997 No. We decided to just use react-native-svg and react-native-svg-transformer for our icons which supports both native and web.

@JoshBot-Debug
Copy link

To use react-native-vector-icons with react-native-web

webpack.js.config:

I have commented "ADD THIS LINE HERE" where you need to add a line

const path = require('path');

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const appDirectory = path.resolve(__dirname);
const {presets} = require(`${appDirectory}/babel.config.js`);

const compileNodeModules = [
  // Add every react-native package that needs compiling
  // 'react-native-gesture-handler',
  'react-native-vector-icons', // ADD THIS LINE HERE
].map((moduleName) => path.resolve(appDirectory, `node_modules/${moduleName}`));

const babelLoaderConfiguration = {
  test: /\.js$|tsx?$/,
  // Add every directory that needs to be compiled by Babel during the build.
  include: [
    path.resolve(__dirname, 'index.web.js'), // Entry to your application
    path.resolve(__dirname, 'App.tsx'), // Change this to your main App file
    path.resolve(__dirname, 'src'),
    ...compileNodeModules,
  ],
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      presets,
      plugins: ['react-native-web'],
    },
  },
};

const svgLoaderConfiguration = {
  test: /\.svg$/,
  use: [
    {
      loader: '@svgr/webpack',
    },
  ],
};

// ADD THIS LINE HERE (ttfLoaderConfiguration)
const ttfLoaderConfiguration = {
  test: /\.ttf$/,
  loader: 'url-loader', // or directly file-loader
  include: [
    path.resolve(appDirectory, 'node_modules/react-native-vector-icons'),
  ],
};

const imageLoaderConfiguration = {
  test: /\.(gif|jpe?g|png)$/,
  use: {
    loader: 'url-loader',
    options: {
      name: '[name].[ext]',
    },
  },
};

module.exports = {
  entry: {
    app: path.join(__dirname, 'index.web.js'),
  },
  output: {
    path: path.resolve(appDirectory, 'dist'),
    publicPath: '/',
    filename: 'rnw_blogpost.bundle.js',
  },
  resolve: {
    extensions: ['.web.tsx', '.web.ts', '.tsx', '.ts', '.web.js', '.js'],
    alias: {
      'react-native$': 'react-native-web',
    },
  },
  module: {
    rules: [
      babelLoaderConfiguration,
      imageLoaderConfiguration,
      svgLoaderConfiguration,
      ttfLoaderConfiguration, // ADD THIS LINE HERE
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DefinePlugin({
      // See: https://github.com/necolas/react-native-web/issues/349
      __DEV__: JSON.stringify(true),
    }),
  ],
};

index.web.js:

import {AppRegistry} from 'react-native';
import {name as appName} from './app.json';
import App from './App';

// ADD THESE LINES BELOW
// This is done for Ionicons, just follow the pattern to add others like materialicons, etc

import Ionicons from 'react-native-vector-icons/Fonts/Ionicons.ttf';

const IoniconsStyles = `@font-face {
  src: url(${Ionicons});
  font-family: Ionicons;
}`;

const style = document.createElement('style');
style.type = 'text/css';

if (style.styleSheet) {
  style.styleSheet.cssText = IoniconsStyles;
} else {
  style.appendChild(document.createTextNode(IoniconsStyles));
}

document.head.appendChild(style);

if (module.hot) {
  module.hot.accept();
}
AppRegistry.registerComponent(appName, () => App);
AppRegistry.runApplication(appName, {
  initialProps: {},
  rootTag: document.getElementById('app-root'),
});

After that, just restart webpack and you're done

@johnf johnf closed this as completed Aug 5, 2023
@junaid7898
Copy link

junaid7898 commented Jan 29, 2024

After applying above mentioned solution i got this error when i do npm run web
**Module not found: Error: Can't resolve 'react-native-vector-icons/Fonts/Ionicons.ttf'
Can anybody help me on this?

@JoshBot-Debug
Copy link

After applying above mentioned solution i got this error when i do npm run web **Module not found: Error: Can't resolve 'react-native-vector-icons/Fonts/Ionicons.ttf' Can anybody help me on this?

Make sure react-native-vector-icons is installed, if it is installed then try deleting node_modules, package-lock.json, and then run

npm install

@junaid7898
Copy link

junaid7898 commented Jan 30, 2024

After applying above mentioned solution i got this error when i do npm run web **Module not found: Error: Can't resolve 'react-native-vector-icons/Fonts/Ionicons.ttf' Can anybody help me on this?

Make sure react-native-vector-icons is installed, if it is installed then try deleting node_modules, package-lock.json, and then run

npm install

Thank you for helping I tried this solution vector icons were already installed and i deleted node modules and package-lock file but got error the same error but this time I am putting here all the info related to error so that i might get some help.

**ERROR in ./index.web.js 1:266-321
Module not found: Error: Can't resolve 'react-native-vector-icons/Fonts/Ionicons.ttf' in
resolve 'react-native-vector-icons/Fonts/Ionicons.ttf' in '/Users/Project'
Parsed request is a module
using description file: /Project/package.json (relative path: .)
aliased with mapping 'react-native-vector-icons': 'react-native-vector-icons/dist' to 'react-native-vector-icons/dist/Fonts/Ionicons.ttf'
Parsed request is a module
using description file: /Users/Project/package.json (relative path: .)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
looking for modules in /Users/Project/node_modules
existing directory /Users/Project/node_modules/react-native-vector-icons
using description file: /Users/Project/node_modules/react-native-vector-icons/package.json (relative path: .)
using description file: /Users/Project/node_modules/react-native-vector-icons/package.json (relative path: ./dist/Fonts/Ionicons.ttf)
no extension
Field 'browser' doesn't contain a valid alias configuration
/Users/Project/node_modules/react-native-vector-icons/dist/Fonts/Ionicons.ttf doesn't exist
.web.tsx
Field 'browser' doesn't contain a valid alias configuration
/Project/node_modules/react-native-vector-icons/dist/Fonts/Ionicons.ttf.web.tsx doesn't exist
.web.ts

Here is my webpack.config.js

 const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const appDirectory = path.resolve(__dirname);
const {presets, plugins} = require(`${appDirectory}/babel.config.js`);
const compileNodeModules = [
  // Add every react-native package that needs compiling
  // 'react-native-gesture-handler',
  'react-native-google-places-autocomplete',
  'react-native-vector-icons',
].map(moduleName => path.resolve(appDirectory, `node_modules/${moduleName}`));

const babelLoaderConfiguration = {
  test: /\.(js|jsx|ts|tsx)$/, // Updated to include .jsx
  // Add every directory that needs to be compiled by Babel during the build.
  include: [
    path.resolve(__dirname, 'index.web.js'), // Entry to your application
    path.resolve(__dirname, 'App.js'), // Updated to .jsx
    path.resolve(__dirname, 'src'),
    path.resolve(__dirname, 'component'),
    ...compileNodeModules,
  ],
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      presets,
      plugins,
    },
  },
};

const svgLoaderConfiguration = {
  test: /\.svg$/,
  use: [
    {
      loader: '@svgr/webpack',
    },
  ],
};

const imageLoaderConfiguration = {
  test: /\.(gif|jpe?g|png|svg)$/,
  use: {
    loader: 'url-loader',
    options: {
      name: '[name].[ext]',
    },
  },
};

const ttfLoaderConfiguration = {
  test: /\.ttf$/,
  loader: 'url-loader', // or directly file-loader
  include: [
    path.resolve(appDirectory, 'node_modules/react-native-vector-icons'),
  ],
};

const tsLoaderConfiguration = {
  test: /\.(ts)x?$/,
  exclude: /node_modules|\.d\.ts$/, // this line as well
  use: {
    loader: 'ts-loader',
    options: {
      compilerOptions: {
        noEmit: false, // this option will solve the issue
      },
    },
  },
};

module.exports = {
  entry: {
    app: path.join(__dirname, 'index.web.js'),
  },
  output: {
    path: path.resolve(appDirectory, 'dist'),
    publicPath: '/',
    filename: 'rnw.bundle.js',
  },
  resolve: {
    extensions: [
      '.web.tsx',
      '.web.ts',
      '.tsx',
      '.ts',
      '.web.js',
      '.js',
      '.jsx',
      '.web.jsx',
    ],
    alias: {
      'react-native$': 'react-native-web',
      'react-native-vector-icons': 'react-native-vector-icons/dist',
      'react-native-maps': '@preflower/react-native-web-maps',
    },
  },
  module: {
    rules: [
      babelLoaderConfiguration,
      imageLoaderConfiguration,
      svgLoaderConfiguration,
      tsLoaderConfiguration,
      ttfLoaderConfiguration,
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DefinePlugin({
      __DEV__: JSON.stringify(true),
    }),
  ],
};

@JoshBot-Debug
Copy link

JoshBot-Debug commented Jan 31, 2024

It's probably because of this

alias: {
      'react-native$': 'react-native-web',
      'react-native-vector-icons': 'react-native-vector-icons/dist', // I think this line here is the problem
      'react-native-maps': '@preflower/react-native-web-maps',
    },

Because you added an alias for react-native-vector-icons, when you import react-native-vector-icons, it'll use the alias react-native-vector-icons/dist

// This is where Ionicons.ttf exists
import Ionicons from 'react-native-vector-icons/Fonts/Ionicons.ttf';

// Because of the alias, this is where it tries to load it from. Ionicons.ttf does not exist at this path
import Ionicons from 'react-native-vector-icons/dist/Fonts/Ionicons.ttf';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants