expo / expo-electron-adapter

This package wraps `electron-webpack` and adds support for Expo web and other universal React packages.
MIT License
29 stars 11 forks source link

[electron] Can't run built application #8

Open lukasluecke opened 4 years ago

lukasluecke commented 4 years ago

Description

Following the Building your project part of the Electron guide results in a non-working application output.

(Using the workaround to get it to run at all in https://github.com/expo/expo-cli/issues/1385#issuecomment-569069639)

Expected Behavior

Starting the generated application should show the same result as running expo-electron start.

Observed Behavior

The only thing that happens is an alert with the following error message:

Uncaught Exception:
/Volumes/Work/wwd/sensopro-expo/sensopro/dist/mac/sensopro.app/Contents/Resources/app.asar/node_modules/expo/AppEntry.js:2
import registerRootComponent from 'expo/build/launch/registerRootComponent';
       ^^^^^^^^^^^^^^^^^^^^^

SyntaxError: Unexpected identifier
    at Module._compile (internal/modules/cjs/loader.js:722:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)
    at Module.load (internal/modules/cjs/loader.js:645:32)
    at Function.Module._load (internal/modules/cjs/loader.js:560:12)
    at Object.<anonymous> (/Volumes/Work/wwd/sensopro-expo/sensopro/dist/mac/sensopro.app/Contents/Resources/electron.asar/browser/init.js:181:12)
    at Module._compile (internal/modules/cjs/loader.js:786:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)
    at Module.load (internal/modules/cjs/loader.js:645:32)
    at Function.Module._load (internal/modules/cjs/loader.js:560:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:850:10)

Environment

  Expo CLI 3.11.3 environment info:
    System:
      OS: macOS 10.15.2
      Shell: 5.7.1 - /usr/local/bin/zsh
    Binaries:
      Node: 10.15.0 - ~/.nvm/versions/node/v10.15.0/bin/node
      Yarn: 1.21.1 - /usr/local/bin/yarn
      npm: 6.4.1 - ~/.nvm/versions/node/v10.15.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    IDEs:
      Xcode: 11.3/11C29 - /usr/bin/xcodebuild
    npmPackages:
      @types/react: ~16.9.0 => 16.9.17
      @types/react-native: ~0.60.23 => 0.60.26
      expo: ~36.0.0 => 36.0.2
      react: ~16.9.0 => 16.9.0
      react-native: https://github.com/expo/react-native/archive/sdk-36.0.0.tar.gz => 0.61.4
    npmGlobalPackages:
      expo-cli: 3.11.3

Reproducible Demo

WIP

lukasluecke commented 4 years ago

The problem seems to be that the referenced files have .web.js extensions, and can't get resolved inside the built application. Not sure what the best solution for that would be 🤔

mohammedmulazada commented 4 years ago

I have the same issue, did you find anything new?

mohammedmulazada commented 4 years ago

My guess is that it is unable to find the files in the node_modukes/expo/build directory.

varmab commented 4 years ago

Same issue here. Any ideas on how to solve this?

lukasluecke commented 4 years ago

I have added the following configuration in package.json to get a running application. I'm not sure if that's the intended way to solve this, but it works for now. (Probably missing some paths like assets here, but that might depend on your application structure)

"build": {
  "extraMetadata": {
    "main": "main.js"
  },
  "files": [
    {
      "from": "dist/main/",
      "to": "./",
      "filter": ["**/*"]
    },
    {
      "from": "dist/renderer",
      "to": "./",
      "filter": ["**/*"]
    },
    "package.json",
    "**/node_modules/**/*"
  ]
}
mohammedmulazada commented 4 years ago

@lukasluecke how did you even figure this out? This fixes my issue completely atm.

lukasluecke commented 4 years ago

@moniac Yeah it wasn't that intuitive at first, because all the guides (the one linked in the issue at the top, and also the guide for building by electron-webpack) made it seem like it would just work out of the box.

The first hint that that didn't work as expected was the error message itself, because it referenced AppEntry.js directly, which uses ES6 imports - and should therefore be transpiled by electron-webpack.

I then used the asar package to unpack the app.asar out of the built application contents, and found only the "unprocessed" source files inside. The reason for that is that the dist folder (which is where electron-webpack outputs its transpiled results) is also used by electron-builder to put the final output, and is therefore excluded / ignored automatically while building, meaning no resources get copied from there by default.

After adding the file copy rules, the content of app.asar looked much better, but trying to start the app resulted in the same error. The reason for that was that it was still using AppEntry.js (from node_modules/expo) as the main entrypoint, so we have to override that in the build settings as well.

With the config I posted it overrides the index.html file that's usually auto-generated by electron-builder with the one from dist/renderer, which then correctly references and loads renderer.js, copies main.js from dist/main and uses that as the main entrypoint, which then opens a window loading the index.html we copied earlier.

nandorojo commented 4 years ago

Update

Ah, I fixed it by running yarn electron-webpack first, then editing my package.json as @lukasluecke recommended. I have another issue now, but it doesn't apply to this thread.


I had the same issue. I tried @lukasluecke's solution. It did get rid of the error. However, I have this new one now:

Uncaught Exception:
Error: [HMR] Env ELECTRON_HMR_SOCKET_PATH is not set
    at eval (webpack-internal:///./node_modules/electron-webpack/out/electron-main-hmr/main-hmr.js:8:9)
    at Object../node_modules/electron-webpack/out/electron-main-hmr/main-hmr.js (/Volumes/copy-magic 0.0.3/copy-magic.app/Contents/Resources/app.asar/main.js:806:1)
    at __webpack_require__ (/Volumes/copy-magic 0.0.3/copy-magic.app/Contents/Resources/app.asar/main.js:703:30)
    at fn (/Volumes/copy-magic 0.0.3/copy-magic.app/Contents/Resources/app.asar/main.js:78:20)
    at Object.0 (/Volumes/copy-magic 0.0.3/copy-magic.app/Contents/Resources/app.asar/main.js:817:1)
    at __webpack_require__ (/Volumes/copy-magic 0.0.3/copy-magic.app/Contents/Resources/app.asar/main.js:703:30)
    at /Volumes/copy-magic 0.0.3/copy-magic.app/Contents/Resources/app.asar/main.js:770:37
    at Object.<anonymous> (/Volumes/copy-magic 0.0.3/copy-magic.app/Contents/Resources/app.asar/main.js:773:10)
    at Module._compile (internal/modules/cjs/loader.js:786:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)
Screenshot 2020-05-22 21 26 26

Reproducible example

https://github.com/nandorojo/copy-magic

To reproduce, run yarn && yarn dist, then open the .dmg file in dist/

agungsb commented 3 years ago

I have added the following configuration in package.json to get a running application. I'm not sure if that's the intended way to solve this, but it works for now. (Probably missing some paths like assets here, but that might depend on your application structure)

"build": {
  "extraMetadata": {
    "main": "main.js"
  },
  "files": [
    {
      "from": "dist/main/",
      "to": "./",
      "filter": ["**/*"]
    },
    {
      "from": "dist/renderer",
      "to": "./",
      "filter": ["**/*"]
    },
    "package.json",
    "**/node_modules/**/*"
  ]
}

For me, aside of doing above, I also set /electron/webpack.config.js:

const { withExpoWebpack } = require('@expo/electron-adapter');

module.exports = (config) => {
  config.resolve.extensions.push('.web.js', '.web.ts', '.web.tsx');
  return withExpoWebpack(config);
};
JulianSolros commented 3 years ago

So after doing the above, I get

Uncaught ReferenceError: require is not defined at index.html:63
Uncaught ReferenceError: module is not defined at renderer.js:2
JulianSolros commented 3 years ago

Ah, check this out: https://github.com/electron/electron/issues/27964 It seems in the electron/main/index.js, you have to add contextIsolation: false to the BrowserWindow. It's a security thing, so worth reading further, especially if your app connects to the internet.

If you're using typescript, make sure you have "target": "ES5" in your tsconfig.

So, to summarize all the steps required for an empty repo to work:

  1. Follow the instructions in the docs (https://docs.expo.io/guides/using-electron/)
  2. Move electron to dev environment (yarn remove electron && yarn add -D electron)
  3. Add babel-loader (yarn add -D babel-loader)
  4. Add @lukasluecke 's build property to package.json
  5. Add name and version to package.json (why aren't these automatically included?)
  6. Add contextIsolation: false to the BrowserWindow in electron/main/index.js
  7. Make sure to set your target in tsconfig.json to "target": "ES5" (if using typescript)
  8. Ready to bundle!

Phew, that's kind of a lot!