build.js
4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env node
var fs = require("fs");
var path = require('path');
var child_process = require('child_process');
var Promise = require("bluebird");
var exec = function (cmd, args) {
return new Promise(function(resolve, reject) {
// Execute command
var child = child_process.exec(cmd, {cwd: process.cwd(), env: process.env});
// Pass stdout and stderr
child.stdout.on('data', function(data) { process.stdout.write(data.toString()); });
child.stderr.on('data', function(data) { process.stderr.write(data.toString()); });
// Handle result
child.on('exit', function (code) {
if (code) reject(code);
else resolve();
});
child.on('error', reject);
});
}
var CWD = process.cwd();
var POSTINSTALL_BUILD_CWD = process.env.POSTINSTALL_BUILD_CWD;
// If we didn't have this check, then we'd be stuck in an infinite `postinstall`
// loop, since we run `npm install --only=dev` below, triggering another
// `postinstall`. We can't use `--ignore-scripts` because that ignores scripts
// on all the modules that get installed, too, which would break stuff. So
// instead, we set an environment variable, `POSTINSTALL_BUILD_CWD`, that keeps
// track of what we're installing. It's more than just a yes/no flag because
// the dev dependencies we're installing might use `postinstall-build` too, and
// we don't want the flag to prevent them from running.
if (POSTINSTALL_BUILD_CWD !== CWD) {
var BUILD_ARTIFACT = process.argv[2];
var BUILD_COMMAND = process.argv[3];
fs.stat(BUILD_ARTIFACT, function(err, stats) {
if (err || !(stats.isFile() || stats.isDirectory())) {
// This script will run again after we run `npm install` below. Set an
// environment variable to tell it to skip the check. Really we just want
// the execSync's `env` to be modified, but it's easier just modify and
// pass along the entire `process.env`.
process.env.POSTINSTALL_BUILD_CWD = CWD;
// We already have prod dependencies, that's what triggered `postinstall`
// in the first place. So only install dev.
// Fetch package.json
var pkgJson = require(path.join(CWD, "package.json"));
var devDeps = pkgJson.devDependencies;
var opts = { env: process.env, stdio: 'inherit' };
var installArgs = [];
// Map all key (dependency) value (semver) pairs to
// "dependency@semver dependency@semver ..." string that can be used
// for `npm install` command
for (var dep of pkgJson.buildDependencies) {
var semver = devDeps[dep];
// Values listed under `buildDependencies` contain the dependency names
// that are required for `lib` building.
if (!semver) {
continue;
}
// Check if the dependency is already installed
try {
require(dep);
} catch (err) {
// Format installable dependencies
installArgs.push(dep + '@' + semver);
}
}
Promise.try(function() {
if (installArgs.length) {
console.log('Installing dependencies');
return exec("npm install " + installArgs.join(' '), opts);
}
}).then(function(stdout, stderr) {
console.log('✓')
// Don't need the flag anymore as `postinstall` was already run.
// Change it back so the environment is minimally changed for the
// remaining commands.
process.env.POSTINSTALL_BUILD_CWD = POSTINSTALL_BUILD_CWD;
console.log('Building compiled files (' + BUILD_COMMAND + ')');
return exec(BUILD_COMMAND, opts);
})
.catch(function(err) {
console.error(err);
process.exit(1);
})
.then(function(stdout, stderr) {
if (process.env.NODE_ENV === 'production') {
console.log('✓');
console.log('Pruning dev dependencies for production build');
return exec("npm prune --production", opts);
} else {
console.log('Skipping npm prune');
}
})
.then(function() {
console.log('✓')
})
.catch(function(err) {
console.error(err)
process.exit(1);
})
}
});
}