Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit ff6da06

Browse files
Add IPC notifications for CLI watch
1 parent d6975ce commit ff6da06

File tree

12 files changed

+159
-85
lines changed

12 files changed

+159
-85
lines changed

‎.gitignore‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
node_modules
23
*.tgz
34
package-lock.json
@@ -10,5 +11,9 @@ plugins/PlatformFSPlugin.d.ts
1011
plugins/PlatformFSPlugin.js
1112
plugins/PlatformFSPlugin.js.map
1213

14+
plugins/WatchStateLoggerPlugin.d.ts
15+
plugins/WatchStateLoggerPlugin.js
16+
plugins/WatchStateLoggerPlugin.js.map
17+
1318
hooks
14-
.DS_Store
19+
.DS_Store

‎demo/AngularApp/app/item/items.component.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,5 @@ export class ItemsComponent implements OnInit {
1818

1919
ngOnInit(): void {
2020
this.items = this.itemService.getItems();
21-
// console.log("ngOnInit!");
2221
}
2322
}

‎lib/after-watch.js‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
var compiler = require('./compiler');
2+
module.exports = function($logger) {
3+
var webpackProcess = compiler.getWebpackProcess();
4+
if (webpackProcess) {
5+
$logger.info("Stopping webpack watch");
6+
webpack.kill("SIGINT");
7+
}
8+
}

‎lib/before-prepareJS.js‎

Lines changed: 5 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,4 @@
1-
const utils = require("./utils");
2-
const { spawn } = require("child_process");
3-
const { join, resolve: pathResolve } = require("path");
4-
const { existsSync } = require("fs");
5-
let hasBeenInvoked = false;
6-
7-
function escapeWithQuotes(arg) {
8-
return `"${arg}"`;
9-
}
10-
11-
function spawnChildProcess(projectDir, command, ...args) {
12-
return new Promise((resolve, reject) => {
13-
const escapedArgs = args.map(escapeWithQuotes)
14-
15-
const childProcess = spawn(command, escapedArgs, {
16-
stdio: "inherit",
17-
pwd: projectDir,
18-
shell: true,
19-
});
20-
21-
childProcess.on("close", code => {
22-
if (code === 0) {
23-
resolve();
24-
} else {
25-
reject({
26-
code,
27-
message: `child process exited with code ${code}`,
28-
});
29-
}
30-
});
31-
});
32-
}
33-
34-
function throwError(error) {
35-
console.error(error.message);
36-
process.exit(error.code || 1);
37-
}
38-
39-
function prepareJSWebpack(config, $mobileHelper, $projectData, originalArgs, originalMethod) {
40-
if (config.bundle) {
41-
return new Promise(function (resolve, reject) {
42-
console.log(`Running webpack for ${config.platform}...`);
43-
const envFlagNames = Object.keys(config.env).concat([config.platform.toLowerCase()]);
44-
45-
const snapshotEnvIndex = envFlagNames.indexOf("snapshot");
46-
if (snapshotEnvIndex !== -1 && !utils.shouldSnapshot($mobileHelper, config.platform, config.bundle)) {
47-
envFlagNames.splice(snapshotEnvIndex, 1);
48-
}
49-
50-
// Adding `npm i source-map-support --save-dev` in an app will make source maps work
51-
// and stack traces will point to .ts if .ts files and proper source maps exist.
52-
let sourceMapSupportArgs = [];
53-
let appSourceMapSupportInstallPath = pathResolve($projectData.projectDir, "node_modules", "source-map-support", "register.js");
54-
let devDepSourceMapSupportInstallPath = pathResolve(__dirname, "..", "node_modules", "source-map-support", "register.js");
55-
if (existsSync(appSourceMapSupportInstallPath)) {
56-
sourceMapSupportArgs = ["--require", appSourceMapSupportInstallPath];
57-
} else if (existsSync(devDepSourceMapSupportInstallPath)) {
58-
sourceMapSupportArgs = ["--require", devDepSourceMapSupportInstallPath];
59-
}
60-
61-
const args = [
62-
$projectData.projectDir,
63-
"node",
64-
"--preserve-symlinks",
65-
...sourceMapSupportArgs,
66-
join($projectData.projectDir, "node_modules", "webpack", "bin", "webpack.js"),
67-
"--config=webpack.config.js",
68-
"--progress",
69-
...envFlagNames.map(item => `--env.${item}`),
70-
].filter(a => !!a);
71-
72-
// TODO: require webpack instead of spawning
73-
spawnChildProcess(...args)
74-
.then(resolve)
75-
.catch(throwError);
76-
});
77-
}
78-
}
1+
const { runWebpackCompiler } = require("./compiler");
792

803
module.exports = function ($mobileHelper, $projectData, hookArgs) {
814
const env = hookArgs.config.env || {};
@@ -84,8 +7,10 @@ module.exports = function ($mobileHelper, $projectData, hookArgs) {
847
const config = {
858
env,
869
platform,
87-
bundle: appFilesUpdaterOptions.bundle
10+
bundle: appFilesUpdaterOptions.bundle,
11+
watch: false
8812
};
8913

90-
return config.bundle && prepareJSWebpack.bind(prepareJSWebpack, config, $mobileHelper, $projectData);
14+
const result = config.bundle && runWebpackCompiler.bind(runWebpackCompiler, config, $mobileHelper, $projectData);
15+
return result;
9116
}

‎lib/compiler.js‎

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
const utils = require("./utils");
2+
const { spawn } = require("child_process");
3+
const { join, resolve: pathResolve } = require("path");
4+
const { existsSync } = require("fs");
5+
const readline = require("readline");
6+
7+
let hasBeenInvoked = false;
8+
9+
let webpackProcess = null;
10+
11+
function throwError(error) {
12+
console.error(error.message);
13+
process.exit(error.code || 1);
14+
}
15+
16+
exports.getWebpackProcess = function getWebpackProcess() {
17+
return webpackProcess;
18+
}
19+
20+
exports.runWebpackCompiler = function runWebpackCompiler(config, $mobileHelper, $projectData, originalArgs, originalMethod) {
21+
if (config.bundle) {
22+
return new Promise(function (resolveBase, rejectBase) {
23+
let isResolved = false;
24+
function resolve() {
25+
if (isResolved) return;
26+
if (childProcess) {
27+
childProcess.removeListener("message", resolveOnWebpackCompilationComplete);
28+
}
29+
resolveBase();
30+
}
31+
function reject() {
32+
if (isResolved) return;
33+
if (childProcess) {
34+
childProcess.removeListener("message", resolveOnWebpackCompilationComplete);
35+
}
36+
rejectBase();
37+
}
38+
39+
// TODO: Read from CLI options...
40+
const { watch } = true;
41+
42+
console.log(`Running webpack for ${config.platform}...`);
43+
const envFlagNames = Object.keys(config.env).concat([config.platform.toLowerCase()]);
44+
45+
const snapshotEnvIndex = envFlagNames.indexOf("snapshot");
46+
if (snapshotEnvIndex !== -1 && !utils.shouldSnapshot($mobileHelper, config.platform, config.bundle)) {
47+
envFlagNames.splice(snapshotEnvIndex, 1);
48+
}
49+
50+
// Adding `npm i source-map-support --save-dev` in an app will make source maps work
51+
// and stack traces will point to .ts if .ts files and proper source maps exist.
52+
let sourceMapSupportArgs = [];
53+
let appSourceMapSupportInstallPath = pathResolve($projectData.projectDir, "node_modules", "source-map-support", "register.js");
54+
let devDepSourceMapSupportInstallPath = pathResolve(__dirname, "..", "node_modules", "source-map-support", "register.js");
55+
if (existsSync(appSourceMapSupportInstallPath)) {
56+
sourceMapSupportArgs = ["--require", appSourceMapSupportInstallPath];
57+
} else if (existsSync(devDepSourceMapSupportInstallPath)) {
58+
sourceMapSupportArgs = ["--require", devDepSourceMapSupportInstallPath];
59+
}
60+
61+
const args = [
62+
"--preserve-symlinks",
63+
...sourceMapSupportArgs,
64+
join($projectData.projectDir, "node_modules", "webpack", "bin", "webpack.js"),
65+
"--config=webpack.config.js",
66+
"--progress",
67+
... (config.watch ? ["--watch"] : []),
68+
...envFlagNames.map(item => `--env.${item}`),
69+
].filter(a => !!a);
70+
71+
const childProcess = spawn("node", args, {
72+
// IPC calls so we don't mess with the stdin/out/err.
73+
// These will notify us for the webpack compilation states.
74+
// Enables `childProcess.on("message", msg => ...)` kind of communication.
75+
stdio: ["inherit", "inherit", "inherit", "ipc"],
76+
pwd: $projectData.projectDir,
77+
shell: true,
78+
});
79+
80+
function resolveOnWebpackCompilationComplete(message) {
81+
if (message === "Webpack compilation complete. Watching for file changes.") {
82+
console.log("Initial webpack build done!");
83+
resolve();
84+
}
85+
}
86+
87+
if (config.watch) {
88+
childProcess.on("message", resolveOnWebpackCompilationComplete);
89+
if (webpackProcess) {
90+
throw new Error("Webpack process already spawned.");
91+
}
92+
webpackProcess = childProcess;
93+
}
94+
95+
childProcess.on("close", code => {
96+
if (webpackProcess == childProcess) {
97+
webpackProcess = null;
98+
}
99+
if (code === 0) {
100+
resolve();
101+
} else {
102+
reject({
103+
code,
104+
message: `child process exited with code ${code}`,
105+
});
106+
}
107+
});
108+
});
109+
}
110+
}

‎lib/utils.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ function shouldSnapshot($mobileHelper, platform, bundle) {
66
return bundle && platformSupportsSnapshot && osSupportsSnapshot;
77
}
88

9-
module.exports.shouldSnapshot = shouldSnapshot;
9+
module.exports.shouldSnapshot = shouldSnapshot;

‎plugins/WatchStateLoggerPlugin.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
/**
3+
* This little plugin will report the webpack state through the console.
4+
* So the {N} CLI can get some idea when compilation completes.
5+
*/
6+
export class WatchStateLoggerPlugin {
7+
apply(compiler) {
8+
compiler.plugin("watch-run", function(compiler, callback) {
9+
console.log("File change detected. Starting incremental webpack compilation...");
10+
process.send("File change detected. Starting incremental webpack compilation...", error => null);
11+
callback();
12+
});
13+
compiler.plugin("after-emit", function(compilation, callback) {
14+
callback();
15+
console.log("Webpack compilation complete. Watching for file changes.");
16+
process.send("Webpack compilation complete. Watching for file changes.", error => null);
17+
});
18+
}
19+
}

‎plugins/index.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ module.exports = Object.assign({},
33
require("./NativeScriptJsonpPlugin"),
44
require("./NativeScriptSnapshotPlugin"),
55
require("./PlatformSuffixPlugin"),
6-
require("./PlatformFSPlugin")
6+
require("./PlatformFSPlugin"),
7+
require("./WatchStateLoggerPlugin")
78
);

‎templates/webpack.angular.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ module.exports = env => {
105105
},
106106
}, ngToolsWebpackOptions)
107107
),
108+
// Does IPC communication with the {N} CLI to notify events when running in watch mode.
109+
new nsWebpack.WatchStateLoggerPlugin(),
108110
],
109111
};
110112
if (report) {

‎templates/webpack.javascript.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ module.exports = env => {
9191
new nsWebpack.PlatformFSPlugin({
9292
platform, platforms, ignore: ["App_Resources"]
9393
}),
94+
// Does IPC communication with the {N} CLI to notify events when running in watch mode.
95+
new nsWebpack.WatchStateLoggerPlugin(),
9496
],
9597
};
9698
if (report) {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /