react-native-vector-icons
react-native-vector-icons copied to clipboard
vector icon not shown in react native for web
- [ ] Review the documentation: https://github.com/oblador/react-native-vector-icons
- [ ] Search for existing issues (including closed ones): https://github.com/oblador/react-native-vector-icons/issues
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.
there are not enough steps or details here to warrant an issue. this should be closed
I am running into the same issue where the icon is not displaying in RNW with the newest version of react-native-vector-icons:
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: https://github.com/gciluffo/react-native-web/commit/80d608a68c79bd368b9bc363fb528c8f9ee296b7
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:
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
@Uzef1997 No. We decided to just use react-native-svg
and react-native-svg-transformer
for our icons which supports both native and web.
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
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?
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
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),
}),
],
};
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';