Skip to content
This repository has been archived by the owner on Oct 1, 2020. It is now read-only.

How do you properly pre-compile for release? #61

Closed
ezekg opened this issue Jan 26, 2016 · 44 comments
Closed

How do you properly pre-compile for release? #61

ezekg opened this issue Jan 26, 2016 · 44 comments

Comments

@ezekg
Copy link
Contributor

ezekg commented Jan 26, 2016

The current documentation is confusing,

How can I precompile my code for release-time?

electron-compile comes with a command-line application to pre-create a cache for you.

Usage: electron-compile --appDir [root-app-dir] paths...

Options:
  -a, --appdir  The top-level application directory (i.e. where your
                package.json is)
  -v, --verbose  Print verbose information
  -h, --help     Show help

Run electron-compile on all of your application assets, even if they aren't strictly code (i.e. your static assets like PNGs). electron-compile will recursively walk the given directories.

electron-compile --appDir /path/to/my/app ./src ./static

What is --appDir? Is that where the compiled files will go? It seems like that flag does nothing.

Does pre-compiling require you to have your main.js and package.json inside of the ./src directory? I don't get how this while pre-compile thing is supposed to work. As it is now, I get this error when I boot the app with electron . after pre-compiling with electron-compile --appDir . ./src ./resources:

image

If I remove the .cache directory, then the app runs correctly again. What's the correct way to package an app for release with this library?

This is my current folder structure,
image

@anaisbetts
Copy link
Contributor

What is --appDir? Is that where the compiled files will go? It seems like that flag does nothing.

--appDir is the directory where your package.json is located. It's used as the base for the relative paths we'll save in the cache.

Does pre-compiling require you to have your main.js and package.json inside of the ./src directory? I don't get how this while pre-compile thing is supposed to work.

Basically, if you run electron-compile, it's going to create a folder in your source called .cache. You should put that in Electron.app/Contents/Resources/app (or .\resources\app on Windows, etc etc - the same folder as your package.json)

@ezekg
Copy link
Contributor Author

ezekg commented Jan 27, 2016

That's what I figured, I just wasn't sure if the documentation was out of date or not. Where is the main.js file supposed to be? I have it in the same directory as package.json, but am getting the above error (about it not being pre-compiled?) when attempting to boot up the app after pre-compiling.

Thanks for the help, btw. This whole project is great.

@ezekg ezekg changed the title How do you recompile for release? How do you properly pre-compile for release? Jan 27, 2016
@anaisbetts
Copy link
Contributor

set DEBUG and it will give you more of a hint - also, try providing an absolute path to your main.js, I think the relative require stuff is having problems in some scenarios

@ezekg
Copy link
Contributor Author

ezekg commented Jan 27, 2016

Yeah, I've tried that. Compiling with electron-compile --appDir $(pwd) ./src and then booting with DEBUG=*,-babel electron $(pwd)/main.js results in,

image

I don't understand the error message, because main.js shouldn't even be pre-compiled, right?

@giuge
Copy link

giuge commented Jan 27, 2016

I'm having some troubles as well.

Here's my directory structure, there you can see the entry file for the app as well:
screen shot 2016-01-27 at 11 46 12

When I run:

electron-compile --appdir ./ ./app

The .cache directory gets created but its content doesn't make sense to me:

screen shot 2016-01-27 at 11 48 38

Packaging the app using the cache contents produces an unusable app:

electron-packager .cache Test --platform=darwin --arch=x64 --version=0.0.1

@anaisbetts
Copy link
Contributor

Packaging the app using the cache contents produces an unusable app:

So right now, you still need to include your original files along with the app and the .cache folder (this will be fixed in the next version).

@anaisbetts
Copy link
Contributor

I don't understand the error message, because main.js shouldn't even be pre-compiled, right?

So, in production mode, all of the files are precompiled, and electron-compile just intercepts the request for the file. Annoyingly though, because node.js's module system will attempt to stat the original file and we can't stop them, you still have to have the original files too (though actually if you want, you can zero the contents!)

@anaisbetts
Copy link
Contributor

The .cache directory gets created but its content doesn't make sense to me:

The folders are essentially a hash of the compiler name + version, and the files are GZipped files which are your app's contents (you can see them by gzcat ./path/to/that/file)

@anaisbetts
Copy link
Contributor

I think in general, this thread is indicating that my user documentation sucks when it comes to production mode, I'll definitely try to beef up this. In general the idea though is:

  1. Package your app the Regular way (using electron-packager, whatever)
  2. Run electron-compile on your source code, it'll generate a .cache folder.
  3. Move that into your packaged app, under the resources/app folder. (i.e. on OS X, MyApp.app/Contents/Resources/app/.cache)

@ezekg
Copy link
Contributor Author

ezekg commented Jan 28, 2016

So does electron-compile intercept the request for every file, and then uses a cached file if it's available within a relative .cache/ directory? If so, how do you determine relative? The application's root? I'm still kind of confused on how it finds the cached files vs. compiling it in place. I think the documentation could definitely be improved on the whole release process.

@jronallo
Copy link

I'm to the point where I'm trying to package my app and running into issues. The compiled app isn't finding module resources/app/index.js which is actually created in index.coffee. I used electron-packager to package my app, created a .cache folder with electron-compile, and copied .cache to dist/app-linux-x64/resources/app/.cache. What might I be missing?

@ezekg
Copy link
Contributor Author

ezekg commented Jan 31, 2016

I had tried that as well. I ended up moving to a Grunt workflow and moving away from this library until it's a little more mature. I couldn't waste any more time trying to get this nice-to-have library to work correctly. I'll definitely keep my eyes on any updates and pick it back up in the future. 👍

@anaisbetts
Copy link
Contributor

So does electron-compile intercept the request for every file, and then uses a cached file if it's available within a relative .cache/ directory? If so, how do you determine relative? The application's root?

You got it

The compiled app isn't finding module resources/app/index.js which is actually created in index.coffee

Not sure I follow what this means, electron-compile never creates an explicit JS file

@jronallo
Copy link

When I try to run my built app I just get an error that resources/app/index.js can't be found. There is no index.js file there, because I'm using index.coffee instead. I've moved the compiled .cache over but it still is looking for index.js and can't find it.

@anaisbetts
Copy link
Contributor

When I try to run my built app I just get an error that resources/app/index.js can't be found.

Stupid question, you aren't trying to require 'index.js' are you?

@jronallo
Copy link

jronallo commented Feb 4, 2016

No, I don't think I was. I've since moved on to using other tools to compile things, so won't be able to help troubleshoot this problem more.

@reverentgeek
Copy link

I'm working on a workshop and want to use electron-compile to help others get started with electron, but I'm running into an issue getting this to work. I have a very simple test app:

test-electron-compile/
  |-- node_modules/
  |-- src/
    |-- app/
       index.html
    |-- components/
      Home.js
    |-- styles/
      main.less
    app.js
    index.js
  package.json

Here are the exact steps I've run through, based on what I read earlier in this thread:

> electron-packager . test-electron-compile --platform=darwin --arch=x64 --version=0.37.2
> electron-compile ./src
> mkdir ./test-electron-compile-darwin-x64/test-electron-compile.app/Contents/Resources/app/.cache
> cp -R .cache/** ./test-electron-compile-darwin-x64/test-electron-compile.app/Contents/Resources/app/.cache

When I run the app, I get the following error:

Uncaught Exception:
SyntaxError: Unexpected token import
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:404:25)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Object.<anonymous> (/Users/david/Projects/testing/test-electron-compile/test-electron-compile-darwin-x64/test-electron-compile.app/Contents/Resources/atom.asar/browser/init.js:158:8)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)

So, it doesn't look like it's picking up on the compiled cache. Am I doing something wrong?

@anaisbetts
Copy link
Contributor

@reverentgeek Hm, what happens if you run electron-compile ./src -a .

@reverentgeek
Copy link

@paulcbetts Here's a screen shot of what I'm seeing after running electron-compile ./src -a .. I've also got the .app expanded so you can see the .cache is there.

image

@anaisbetts
Copy link
Contributor

@reverentgeek Ok, I think I know the problem. If you package the app via electron-packager, you basically don't have the trampoline that electron-prebuilt-compile sets up at https://github.com/paulcbetts/electron-prebuilt-compile/blob/master/src/es6-init.js.

Basically, what it comes down to is I didn't think through how electron-prebuilt-compile would work with packaging :( Lemme work on this tonight, I want to get a solution that's as easy to work with as electron-prebuilt-compile is. Thanks for your patience and for reporting this great detailed info

@reverentgeek
Copy link

Ok, awesome. I love what I see with electron-compile so far. It _greatly_ simplifies building electron apps with these common dependencies, without having to go through all kinds of hoops with babel, webpack, etc. If I can put together an end-to-end solution, this is definitely the path I'm going to encourage people to take.

BTW, this exercise is specifically for a workshop I'm doing at JSConf UY next month, but have several talks on electron I'll be giving throughout this year.

@anaisbetts
Copy link
Contributor

Alright, I didn't quite finish, but #79 sketches out the plan - basically there will soon be a electron-packager-compile command that comes with electron-compile which will take all of the same parameters as electron-packager but will do all of the trampoline work.

@anaisbetts
Copy link
Contributor

Ok! This is now much better, here's how it works:

npm install --save-dev electron-packager
./node-modules/.bin/electron-packager-compile   ## Use the same args as electron-packager

@reverentgeek
Copy link

I've tried lots of variations, but yet to get this to work for me. My current attempt is to have a 2-package.json project structure that looks like the following screen shot:

image

The script I have in my root package.json looks like:

    "package": "electron-packager-compile ./app test-electron-compile --platform=darwin --arch=x64 --version=0.37.7 --overwrite",

After the compile finishes, and I try to launch my application, I get an error "Asked for [path]/main.js but it was not precompiled!"

image

Oh, and half the time when I run the packager, I get the following error. Running it again seems to work.

> [email protected] package /Users/david/Projects/leankit/electron-starter-kit
> electron-packager-compile ./app test-electron-compile --platform=darwin --arch=x64 --version=0.37.7 --overwrite

The strict-ssl parameter is deprecated, use download.strictSSL instead
Packaging app for platform darwin x64 using electron v0.37.7
EEXIST: file already exists, link '/var/folders/2_/2lj6qr6d07318_k0q81y6ggw0000gn/T/electron-packager/darwin-x64/test-electron-compile-darwin-x64' -> '/Users/david/Projects/leankit/electron-starter-kit/test-electron-compile-darwin-x64'

Failed with exit code: 1

npm ERR! Darwin 15.4.0
npm ERR! argv "/Users/david/.nvm/versions/node/v5.10.0/bin/node" "/Users/david/.nvm/versions/node/v5.10.0/bin/npm" "run" "package"
npm ERR! node v5.10.0
npm ERR! npm  v3.8.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] package: `electron-packager-compile ./app test-electron-compile --platform=darwin --arch=x64 --version=0.37.7 --overwrite`
npm ERR! Exit status 255
npm ERR!
npm ERR! Failed at the [email protected] package script 'electron-packager-compile ./app test-electron-compile --platform=darwin --arch=x64 --version=0.37.7 --overwrite'.
npm ERR! Make sure you have the latest version of node.js and npm installed.

@anaisbetts
Copy link
Contributor

@reverentgeek Can you share this project?

@reverentgeek
Copy link

@paulcbetts Here is my electron-starter-kit, to someday be a foundation for Electron apps at my company.

@anaisbetts
Copy link
Contributor

Hah! You found an interesting bug - if you call your source folder app, we will get very confused :)

@reverentgeek
Copy link

Thanks for your help! Do I need to file an issue for the .svg rendering bug? If so, where?

@anaisbetts
Copy link
Contributor

Here is fine

@Haumed
Copy link

Haumed commented Aug 31, 2016

Hey, so I believe I got the pre-compile working! The app works and as @paulcbetts mentioned I tried zeroing out the contents of main.js in the resources/appdirectory (of production) and also extracted resources/app.asar, zeroed out the contents of main.js and packed it again. The app still loads so this seems like proof that it's intercepting nicely.

My concern now is, I obviously don't want to manually zero every .js file every time I package. For size, obfuscation and general cleanliness reasons I'd like a script that recursively does this to every .js file in a directory. I can handle getting inside the asar myself, but I'm not familiar enough with scripting to elegantly do the zeroing. Would somebody [ hint: @paulcbetts :) ] like to offer a solution? I'm on Windows 7 x64.

Also, is this a common enough need to add an option for it to electron-compile? If so I can open a new issue.

@anaisbetts
Copy link
Contributor

@Haumed You could add it as an option to packager-cli, you'd probably do the zeroing here: https://github.com/electron/electron-compile/blob/master/src/packager-cli.js#L140

@Haumed
Copy link

Haumed commented Aug 31, 2016

Ok cool. I'm actually still using regular electron-packager, but if I do get the code figured out I'll make sure to come back and add it.

@manikantag
Copy link

As @paulcbetts commented on #61 (comment),

paulcbetts commented on Feb 1

So does electron-compile intercept the request for every file, and then uses a cached file if it's available within a relative .cache/ directory? If so, how do you determine relative? The application's root?

You got it

electron-compile will check if the requested file is present in the .cache or not.

What if that file is not present in the .cache? Will it serve the original file?

I m getting similar issue. I've below project structure.
image

And es6-init.js (main file):

require('electron-compile').init(require('path').join(__dirname), './main');

And, I m pre-compiling using below command:

electron-compile --appDir . ./assets ./services ./lib

I m getting below error when I launch my app (Windows 8.1 64bit)

image

I think I knew why is the error coming as I m pre-compiling main.js and all other files which are in root. But if I mention root also in the *paths... arg, it is pre-compiling all the .js files in node_modules dir too and it is taking a lot of time. And there is no 'ignore' dir option.

So, when file is not present in .cache dir, won't the original file served? Can we've ignore option? Or can we already do that? Thanks.

@MarshallOfSound
Copy link
Member

@manikantag electron-packager-compile compiles all files inside a directory in the root of your project but excludes node_modules

See https://github.com/electron/electron-compile/blob/master/src/packager-cli.js#L73

Move your main.js and preload.js and such out of the root of your app and into any sub-folder and it will work 👍

@manikantag
Copy link

@MarshallOfSound I m not using electron-packager-compile as I m using electron-builder, and both are not compatible (#99), yet!

I've moved the main.js & preload.js to main dir. Now the structure is:

image

I've tried with below command, but still is pre-compiling node_modules

app> node_modules\.bin\electron-compile.cmd .

How to do the same with just electron-compile?

@manikantag
Copy link

manikantag commented Dec 7, 2016

And if I don't compile everything and instead only js files, then what will happen? In other words, what if a file is not present in .cache dir? Will it serve the original file?

When I m compiling all the files, CSS files are not coming with proper MIME. Strange thing is few CSS files are coming fine. Ex: bootswatch-paper.min.css.

Resource interpreted as Stylesheet but transferred with MIME type text/plain: "file:///C:/Users/kh1015/AppData/Local/E-App/app-0.0.1/resources/app.asar/assets/css/app.css".
index.html:10 Resource interpreted as Stylesheet but transferred with MIME type text/plain: "file:///C:/Users/kh1015/AppData/Local/E-App/app-0.0.1/resources/app.asar/assets/css/angular-motion.css".
index.html:13 Resource interpreted as Stylesheet but transferred with MIME type text/plain: "file:///C:/Users/kh1015/AppData/Local/E-App/app-0.0.1/resources/app.asar/assets/css/style.css".

When I inspect the contents in devtools, it is showing blank. But when I unpack using asar, files are extracted correctly. How to check .cache contents?

image

@manikantag
Copy link

I've verified that the contents in .cache are also present. I've got the file name from compiler-info.json in .cache dir. What could be the issue?

@manikantag
Copy link

@MarshallOfSound any inputs here? Thanks.

@manikantag
Copy link

Any help is much appreciated? I doubt this is a bug.

@MarshallOfSound
Copy link
Member

@manikantag I don't have time to look into this atm but a quick fix would be to either use or steal the code from electron-forge which has implemented packaging for electron-compile 👍

@manikantag
Copy link

Similar issue is seen with electron-forge too. electron/forge#53

I feel this is an issue with electron-compile itself.

@anaisbetts
Copy link
Contributor

@manikantag I think you're right - I think we're somehow not getting text/css as the MIME type for the CSS file (you can even see it in the console screenshot).

@ghost
Copy link

ghost commented Apr 27, 2017

@paulcbetts

So, in production mode, all of the files are precompiled, and electron-compile just intercepts the request for the file. Annoyingly though, because node.js's module system will attempt to stat the original file and we can't stop them, you still have to have the original files too (though actually if you want, you can zero the contents!)

So just to be clear, at the moment there doesn't seem to be a way to remove the original source files (although they can be zeroed) in a production app?

@anaisbetts
Copy link
Contributor

@callodacity Correct - because the node module system will realpath these files before electron-compile has a chance to do anything with them. You could probably hack Module._resolveModule to support this, but stomping into node.js's module system seems super invasive to do in a library

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

No branches or pull requests

8 participants