expo-electron-adapter
expo-electron-adapter copied to clipboard
[Electron] Requiring a file from assets folder doesn't work properly
Description
Hello there! I've found this issue while trying to implement a cross platform application with react-native-web used inside electron. I've followed all setup configuration and everything works smoothly except require of local asset. I'm using some audio and images in my project (with expo AV) and I've placed them inside assets folder and I'm using following code to import them:
await Audio.Sound.createAsync(require("../../../assets/audio/island_exercise_1_1.mp3"))
This works perfectly in react-native-web (running yarn web command), but when I use electron it fails because it seems that requiring an asset conflict with module resolution. On electron if I use
await Audio.Sound.createAsync(require("../../../assets/audio/island_exercise_1_1.mp3").default)
it works, but it's horrible because with RN I can't use dynamic require on mobile, so wrapping the logic in a utility method seems tricky.
I've same problem with source props for Image :(
Expected Behavior
Import with require of an asset works the same way as mobile and web
Environment
Expo CLI 3.24.0 environment info: System: OS: macOS 10.15.2 Shell: 3.2.57 - /bin/bash Binaries: Node: 14.8.0 - /var/folders/zd/nkvx5_tx0f976dl5h43x45jw0000gn/T/yarn--1599129033543-0.8979876647817548/node Yarn: 1.22.4 - /var/folders/zd/nkvx5_tx0f976dl5h43x45jw0000gn/T/yarn--1599129033543-0.8979876647817548/yarn npm: 4.2.0 - ~/.npm-packages/bin/npm Watchman: 4.7.0 - /usr/local/bin/watchman IDEs: Android Studio: 3.5 AI-191.8026.42.35.5791312 Xcode: 11.6/11E708 - /usr/bin/xcodebuild npmPackages: @expo/webpack-config: ^0.12.23 => 0.12.23 expo: ~38.0.8 => 38.0.9 react: ~16.11.0 => 16.11.0 react-dom: ~16.11.0 => 16.11.0 react-native: https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz => 0.62.2 react-native-web: ~0.11.7 => 0.11.7 npmGlobalPackages: expo-cli: 3.24.0
Electron versions
electron: ^6.0.12 @expo/electron-adapter: ^0.0.15
@FRizzonelli I am having this problem as well. Thanks for the tip on using .default
!
@wrsulliv You're welcome. Hope to find someone who can help us with a better solution tho :)
@FRizzonelli Not sure if this helps, but I'm using this utility function:
unpackAsset.ts
export const unpackAsset = (asset: any) => {
return asset;
}
unpackAsset.electron.ts
export const unpackAsset = (asset: any) => {
return asset.default;
}
I invoke throughout the codebase as:
unpackAsset(require('./path/to/image.png'))
Tested this with iOS, Web, and Electron
@wrsulliv Doing the same, but I'd like to have a working require directly from the platform :)
Hi @EvanBacon, I saw that you moved the issue in the proper package. Do you have any insight to handle it better?
I have this simple solution
export const unpackAsset = (asset: any) => { if(typeof asset === 'object'){ return asset.default; } return asset; }
I'm trying to use a custom threejs loader called OBJLoader and MTLLoader from:
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
However, I'm getting this error as well, and I can't seem to load these files any way.
The message I'm getting is:
ERROR in ./src/assets/models/portal.mtl 1:0
Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> # Blender MTL File: 'None'
| # Material Count: 6
|
@ ./src/screens/HomeScreen.js 162:58-96
@ ./App.js
@ ./node_modules/expo/AppEntry.js
@ multi css-hot-loader/hotModuleReplacement ./node_modules/expo/AppEntry.js
ERROR in ./src/assets/models/portal.obj 1:0
Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> # Blender v2.93.1 OBJ File: ''
| # www.blender.org
| mtllib logo.mtl
@ ./src/screens/HomeScreen.js 157:58-96
@ ./App.js
@ ./node_modules/expo/AppEntry.js
@ multi css-hot-loader/hotModuleReplacement ./node_modules/expo/AppEntry.js
Child HtmlWebpackCompiler:
1 asset
Entrypoint HtmlWebpackPlugin_0 = __child-HtmlWebpackPlugin_0
[./node_modules/html-loader/dist/cjs.js?minimize=false!./dist/.renderer-index-template.html] 3.58 KiB {HtmlWebpackPlugin_0} [built]
Is this an issue where webpack can not load these types of files and therefore fails compiling? (MTL and OBJ)? Or is it that the libraries I'm importing this from simply don't support expo electron?
If anyone could point me in the right direction that would be pretty nice.
I also haven't been able to get this to work on web yet... But it's a different issue there...
This is my homepage example:
import React from 'react';
import { View, StyleSheet } from 'react-native';
import ExpoTHREE, { THREE } from 'expo-three';
import { GraphicsView } from 'expo-graphics'
import { Asset } from 'expo-asset';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
export default class HomeScreen extends React.Component {
componentDidMount() {
THREE.suppressExpoWarnings();
}
componentWillUnmount() {
this.mounted = false;
}
onGLContextCreated = async({gl}) => {
this.renderer = new ExpoTHREE.Renderer({gl});
this.renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
this.renderer.setClearColor(0xffffff);
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, gl.drawingBufferWidth / gl.drawingBufferHeight, 0.1, 1000);
this.camera.position.z = 5;
this.ambientLight = new THREE.AmbientLight(0xFFFFFF, 0.5);
this.scene.add(this.ambientLight);
this.spotlight = new THREE.SpotLight( 0xffffff );
this.spotlight.position.set( -60, 150, 100 );
this.spotlight.intensity = 6;
this.spotlight.distance = 1600;
this.spotlight.angle = 0.624;
this.spotlight.exponent = 19.3;
this.spotlight.decay = 7.7;
this.scene.add(this.spotlight);
this.objFile = Asset.fromModule(require('../assets/models/portal.obj').default);
await this.objFile.downloadAsync();
this.mtlFile = Asset.fromModule(require('../assets/models/portal.mtl').default);
await this.mtlFile.downloadAsync();
this.mtlLoader = new MTLLoader();
this.mtlLoader.load(this.mtlFile.localUri, (mtl) => {
mtl.preload();
this.portalLoader = new OBJLoader();
this.portalLoader.setMaterials(mtl);
this.portalLoader.load(this.objFile.localUri, (obj) => {
this.portal = obj
this.portal.rotation.x = 0.2;
this.spotlight.target = this.portal;
this.scene.add(this.portal);
this.mounted = true;
},
(xhr) => {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
(error) => {
console.log(error);
})
},
(xhr) => {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
(error) => {
console.log(error);
});
}
onRender = delta => {
if (this.mounted == true) {
this.portal.rotation.y += 0.01;
this.renderer.render(this.scene, this.camera);
}
}
render() {
return (
<View style={{...styles.view}}>
<GraphicsView style={{ ...styles.container }} onContextCreate={this.onGLContextCreated} onRender={this.onRender} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
alignItems: 'stretch',
flex:1
},
view: {
backgroundColor: '#ffffff',
flex: 1
}
});
And it only seems to work for mobile so far...