diff --git a/.idea/dictionaries/develar.xml b/.idea/dictionaries/develar.xml index 47a113cc671..2d9292eed22 100644 --- a/.idea/dictionaries/develar.xml +++ b/.idea/dictionaries/develar.xml @@ -3,6 +3,7 @@ actperepo addincludedir + addons adminrequired allusersnotpossible amazonaws diff --git a/README.md b/README.md index a8206673a25..eeef43c008f 100755 --- a/README.md +++ b/README.md @@ -56,8 +56,7 @@ For an app that will be shipped to production, you should sign your application. ``` Then you can run `npm run dist` (to package in a distributable format (e.g. dmg, windows installer, deb package)) or `npm run pack` (only generates the package directory without really packaging it. This is useful for testing purposes). - If you use the [two-package.json project structure](#two-packagejson-structure), you'll only have your `devDependencies` in your development `package.json` and your `dependencies` in your app `package.json`. To ensure your dependencies are always updated based on both files, simply add `"postinstall": "install-app-deps"` to your development `package.json`. This will basically automatically trigger an `npm install` within your app directory so you don't have to do this work everytime you install/update your dependencies. - + To ensure your native dependencies are always matched electron version, simply add `"postinstall": "install-app-deps"` to your `package.json`. [Do not use Yarn.](https://github.com/yarnpkg/yarn/issues/1749) 5. If you have native addons of your own that are part of the application (not as a dependency), add `"nodeGypRebuild": true` to the `build` section of your development `package.json`. :bulb: Don't [use](https://github.com/electron-userland/electron-builder/issues/683#issuecomment-241214075) [npm](http://electron.atom.io/docs/tutorial/using-native-node-modules/#using-npm) (neither `.npmrc`) for configuring electron headers. Use [node-gyp-rebuild](https://github.com/electron-userland/electron-builder/issues/683#issuecomment-241488783) bin instead. diff --git a/docs/Two package.json Structure.md b/docs/Two package.json Structure.md index fdfb7e0767a..d8ab02e6e5f 100644 --- a/docs/Two package.json Structure.md +++ b/docs/Two package.json Structure.md @@ -13,4 +13,6 @@ Why? 1. Native npm modules (those written in C, not JavaScript) need to be compiled and here we have two different compilation targets for them. Those used within the application need to be compiled against the electron runtime and all `devDependencies` need to be compiled against your local node.js environment. Thanks to the two `package.json` structure, this is trivial (see [#39](https://github.com/electron-userland/electron-builder/issues/39)). 2. No need to specify which [files](https://github.com/electron-userland/electron-builder/wiki/Options#BuildMetadata-files) to include in the app (because development files reside outside the `app` directory). -Please see [Loading App Dependencies Manually](https://github.com/electron-userland/electron-builder/wiki/Loading-App-Dependencies-Manually) and [#379](https://github.com/electron-userland/electron-builder/issues/379#issuecomment-218503881). \ No newline at end of file +Please see [Loading App Dependencies Manually](https://github.com/electron-userland/electron-builder/wiki/Loading-App-Dependencies-Manually) and [#379](https://github.com/electron-userland/electron-builder/issues/379#issuecomment-218503881). + +If you use the two-package.json project structure, you'll only have your `devDependencies` in your development `package.json` and your `dependencies` in your app `package.json`. To ensure your dependencies are always updated based on both files, simply add `"postinstall": "install-app-deps"` to your development `package.json`. This will basically automatically trigger an `npm install` within your app directory so you don't have to do this work every time you install/update your dependencies. \ No newline at end of file diff --git a/src/install-app-deps.ts b/src/install-app-deps.ts index 5aa4ab5a059..3ec778c5d25 100644 --- a/src/install-app-deps.ts +++ b/src/install-app-deps.ts @@ -7,7 +7,7 @@ import BluebirdPromise from "bluebird-lst-c" import { DevMetadata } from "./metadata" import yargs from "yargs" import { readPackageJson } from "./util/readPackageJson" -import { installDependencies, computeExtraArgs } from "./yarn" +import { installOrRebuild } from "./yarn" const args: any = yargs .option("arch", { @@ -24,11 +24,8 @@ async function main() { getElectronVersion(devMetadata, devPackageFile) ]) - if (results[0] === projectDir) { - throw new Error("install-app-deps is only useful for two package.json structure") - } - - await installDependencies(results[0], results[1], args.arch, computeExtraArgs(devMetadata.build)) + // if two package.json — force full install (user wants to install/update app deps in addition to dev) + await installOrRebuild(devMetadata.build, results[0], results[1], args.arch, results[0] !== projectDir) } main() diff --git a/src/packager.ts b/src/packager.ts index a0d8d9d3f25..0a8751546a2 100644 --- a/src/packager.ts +++ b/src/packager.ts @@ -1,5 +1,5 @@ import * as path from "path" -import { computeDefaultAppDirectory, getElectronVersion, use, exec, isEmptyOrSpaces, exists } from "./util/util" +import { computeDefaultAppDirectory, getElectronVersion, use, exec, isEmptyOrSpaces } from "./util/util" import { all, executeFinally } from "./util/promise" import { EventEmitter } from "events" import BluebirdPromise from "bluebird-lst-c" @@ -17,7 +17,7 @@ import { createTargets } from "./targets/targetFactory" import { readPackageJson } from "./util/readPackageJson" import { TmpDir } from "./util/tmp" import { BuildOptions } from "./builder" -import { getGypEnv, installDependencies, rebuild, computeExtraArgs } from "./yarn" +import { getGypEnv, installOrRebuild } from "./yarn" function addHandler(emitter: EventEmitter, event: string, handler: Function) { emitter.on(event, handler) @@ -229,29 +229,24 @@ export class Packager implements BuildInfo { } private async installAppDependencies(platform: Platform, arch: Arch): Promise { - if (this.devMetadata.build.nodeGypRebuild === true) { + const options = this.devMetadata.build + if (options.nodeGypRebuild === true) { log(`Executing node-gyp rebuild for arch ${Arch[arch]}`) await exec(process.platform === "win32" ? "node-gyp.cmd" : "node-gyp", ["rebuild"], { env: getGypEnv(this.electronVersion, Arch[arch]), }) } - if (this.devMetadata.build.npmRebuild === false) { + if (options.npmRebuild === false) { log("Skip app dependencies rebuild because npmRebuild is set to false") return } - if (this.devMetadata.build.npmSkipBuildFromSource !== true && platform.nodeName !== process.platform) { + if (options.npmSkipBuildFromSource !== true && platform.nodeName !== process.platform) { log("Skip app dependencies rebuild because platform is different") } else { - const args = computeExtraArgs(this.devMetadata.build) - if (await exists(path.join(this.appDir, "node_modules"))) { - await rebuild(this.appDir, this.electronVersion, Arch[arch], args) - } - else if (this.isTwoPackageJsonProjectLayoutUsed) { - await installDependencies(this.appDir, this.electronVersion, Arch[arch], args) - } + await installOrRebuild(options, this.appDir, this.electronVersion, Arch[arch]) } } } diff --git a/src/yarn.ts b/src/yarn.ts index db9c698c033..650e4000fdc 100644 --- a/src/yarn.ts +++ b/src/yarn.ts @@ -1,12 +1,18 @@ import BluebirdPromise from "bluebird-lst-c" import * as path from "path" -import { task, log } from "./util/log" +import { log } from "./util/log" import { homedir } from "os" import { spawn, exists, asArray } from "./util/util" import { BuildMetadata } from "./metadata" -export function installDependencies(appDir: string, electronVersion: string, arch: string = process.arch, additionalArgs: Array): Promise { - return task(`Installing app dependencies for arch ${arch} to ${appDir}`, spawnNpmProduction(appDir, getGypEnv(electronVersion, arch), additionalArgs)) +export async function installOrRebuild(options: BuildMetadata, appDir: string, electronVersion: string, arch: string, forceInstall: boolean = false) { + const args = computeExtraArgs(options) + if (forceInstall || !(await exists(path.join(appDir, "node_modules")))) { + await installDependencies(appDir, electronVersion, arch, args) + } + else { + await rebuild(appDir, electronVersion, arch, args) + } } export function getGypEnv(electronVersion: string, arch: string): any { @@ -21,7 +27,7 @@ export function getGypEnv(electronVersion: string, arch: string): any { }) } -export function computeExtraArgs(options: BuildMetadata) { +function computeExtraArgs(options: BuildMetadata) { const args = asArray(options.npmArgs) if (options.npmSkipBuildFromSource !== true) { args.push("--build-from-source") @@ -29,7 +35,8 @@ export function computeExtraArgs(options: BuildMetadata) { return args } -function spawnNpmProduction(appDir: string, env: any, additionalArgs: Array): Promise { +export function installDependencies(appDir: string, electronVersion: string, arch: string = process.arch, additionalArgs: Array): Promise { + log(`Installing app dependencies for arch ${arch} to ${appDir}`) let npmExecPath = process.env.npm_execpath || process.env.NPM_CLI_JS const npmExecArgs = ["install", "--production"] @@ -55,10 +62,9 @@ function spawnNpmProduction(appDir: string, env: any, additionalArgs: Array