Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit 529b2bf

Browse files
Fatmesis0k0
Fatme
authored andcommitted
feat: add hook for preview command (#649)
`tns preview` command works without platform argument, so {N} CLI needs to start iOS webpack process when QR code is scanned with iOS device and android webpack process when QR code is scanned with Android device. Actually we need to have two separate webpack processes simultaneously. In order to do that we need to persist webpack process per platform. When `tns preview --bundle` command is executed and QR code is scanned for example with Android device, {N} CLI starts a webpack process in watch mode for Android platform. If the webpack process for Android is already started, {N} CLI doesn't do anything. In order to archive the above things, a new hook is introduced - "before-preview-sync". This hook is used only from `tns preview` command. ## PR Checklist - [x] The PR title follows our guidelines: https://github.com/NativeScript/NativeScript/blob/master/CONTRIBUTING.md#commit-messages. - [ ] There is an issue for the bug/feature this PR is for. To avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it. - [ ] You have signed the [CLA]. - [ ] All existing tests are passing: https://github.com/NativeScript/nativescript-dev-webpack/blob/master/CONTRIBUTING.md#testing-locally-by-running-e2e-tests - [ ] Tests for the changes are included. ## What is the current behavior? When `tns run --bundle` command is executed, the following error message is shown: "Bundling doesn't work with multiple platforms. Please specify platform to the run command." ## What is the new behavior? When `tns run --bundle` command is executed and for example the user has connected both iOS and Android devices, two webpack processes are started (one for Android and one for iOS). When the user makes some change in code, the changes are applied both on iOS and Android devices. NOTE: When a platform specific file is changed - for example `myfile.ios.js` only iOS webpack is started and the changes are applied only on iOS devices. When for example some iOS device is disconnected, we check if there are more connected iOS devices. If no more iOS devices are connected, we stopped the webpack process for iOS platform. We did it by adding an event handler for "liveSyncStopped" event. Implements: #457 Rel: NativeScript/nativescript-cli#3853 BREAKING CHANGES: The breaking changes are only for commands for which no platform argument is provided.
1 parent 54c83ec commit 529b2bf

9 files changed

+113
-42
lines changed

Diff for: lib/after-watch.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
const compiler = require('./compiler');
1+
const { stopWebpackCompiler } = require('./compiler');
2+
23
module.exports = function($logger) {
3-
const webpackProcess = compiler.getWebpackProcess();
4-
if (webpackProcess) {
5-
$logger.info("Stopping webpack watch");
6-
webpackProcess.kill("SIGINT");
7-
}
4+
$logger.info("Stopping webpack watch");
5+
stopWebpackCompiler();
86
}

Diff for: lib/before-cleanApp.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
const { cleanSnapshotArtefacts } = require("../snapshot/android/project-snapshot-generator");
22
const { isAndroid } = require("../projectHelpers");
3-
const { getWebpackProcess } = require("./compiler");
3+
const { getWebpackProcesses } = require("./compiler");
44

55
module.exports = function (hookArgs) {
66
return (args, originalMethod) => {
7-
const webpackProcess = getWebpackProcess();
8-
const promise = webpackProcess ? Promise.resolve() : originalMethod(...args);
7+
const platform = hookArgs.platformInfo.platform;
8+
const webpackProcesses = getWebpackProcesses();
9+
const promise = webpackProcesses[platform] ? Promise.resolve() : originalMethod(...args);
910
return promise.then(() => {
10-
if (isAndroid(hookArgs.platformInfo.platform)) {
11+
if (isAndroid(platform)) {
1112
cleanSnapshotArtefacts(hookArgs.platformInfo.projectData.projectDir);
1213
}
1314
});

Diff for: lib/before-preview-sync.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { runWebpackCompiler } = require("./compiler");
2+
3+
module.exports = function($logger, $liveSyncService, hookArgs) {
4+
const { config } = hookArgs;
5+
const bundle = config && config.appFilesUpdaterOptions && config.appFilesUpdaterOptions.bundle;
6+
if (bundle) {
7+
const env = config.env || {};
8+
const platform = config.platform;
9+
const release = config && config.appFilesUpdaterOptions && config.appFilesUpdaterOptions.release;
10+
const compilerConfig = {
11+
env,
12+
platform,
13+
bundle,
14+
release,
15+
watch: true
16+
};
17+
18+
return runWebpackCompiler(compilerConfig, hookArgs.projectData, $logger, $liveSyncService, hookArgs);
19+
}
20+
}
21+

Diff for: lib/before-watch.js

+30-20
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
1-
const { runWebpackCompiler } = require("./compiler");
1+
const { getWebpackProcesses, runWebpackCompiler, stopWebpackCompiler } = require("./compiler");
22

3-
module.exports = function ($logger, $liveSyncService, $options, hookArgs) {
4-
if (hookArgs.config) {
5-
const appFilesUpdaterOptions = hookArgs.config.appFilesUpdaterOptions;
6-
if (appFilesUpdaterOptions.bundle) {
7-
const platforms = hookArgs.config.platforms;
8-
return Promise.all(platforms.map(platform => {
9-
const env = hookArgs.config.env || {};
10-
env.hmr = !!$options.hmr;
11-
const config = {
12-
env,
13-
platform,
14-
bundle: appFilesUpdaterOptions.bundle,
15-
release: appFilesUpdaterOptions.release,
16-
watch: true
17-
};
3+
module.exports = function ($logger, $liveSyncService, $options, $devicesService, hookArgs) {
4+
if (hookArgs.config) {
5+
const appFilesUpdaterOptions = hookArgs.config.appFilesUpdaterOptions;
6+
if (appFilesUpdaterOptions.bundle) {
7+
$liveSyncService.on("liveSyncStopped", data => {
8+
const webpackProcesses = getWebpackProcesses();
9+
Object.keys(webpackProcesses).forEach(platform => {
10+
const devices = $devicesService.getDevicesForPlatform(platform);
11+
if (!devices || !devices.length) {
12+
stopWebpackCompiler(platform);
13+
}
14+
});
15+
});
1816

19-
return runWebpackCompiler(config, hookArgs.projectData, $logger, $liveSyncService, hookArgs);
20-
}));
21-
}
22-
}
17+
const platforms = hookArgs.config.platforms;
18+
return Promise.all(platforms.map(platform => {
19+
const env = hookArgs.config.env || {};
20+
env.hmr = !!$options.hmr;
21+
const config = {
22+
env,
23+
platform,
24+
bundle: appFilesUpdaterOptions.bundle,
25+
release: appFilesUpdaterOptions.release,
26+
watch: true
27+
};
28+
29+
return runWebpackCompiler(config, hookArgs.projectData, $logger, $liveSyncService, hookArgs);
30+
}));
31+
}
32+
}
2333
}

Diff for: lib/compiler.js

+33-9
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ const { buildEnvData, debuggingEnabled } = require("./utils");
99

1010
let hasBeenInvoked = false;
1111

12-
let webpackProcess = null;
12+
let webpackProcesses = {};
1313
let hasLoggedSnapshotWarningMessage = false;
1414

15-
exports.getWebpackProcess = function getWebpackProcess() {
16-
return webpackProcess;
15+
exports.getWebpackProcesses = function getWebpackProcess() {
16+
return webpackProcesses;
1717
}
1818

1919
exports.runWebpackCompiler = function runWebpackCompiler(config, $projectData, $logger, $liveSyncService, hookArgs) {
2020
if (config.bundle) {
2121
return new Promise(function (resolveBase, rejectBase) {
22-
if (webpackProcess) {
22+
if (webpackProcesses[config.platform]) {
2323
return resolveBase();
2424
}
2525

@@ -43,6 +43,11 @@ exports.runWebpackCompiler = function runWebpackCompiler(config, $projectData, $
4343
env["sourceMap"] = true;
4444
}
4545

46+
// Currently externals param is passed only from before-preview-sync hook. This hook is triggered only when `tns preview --bundle` command is executed
47+
if (hookArgs && hookArgs.externals) {
48+
env.externals = hookArgs.externals;
49+
}
50+
4651
const envData = buildEnvData($projectData, platform, env);
4752
const envParams = buildEnvCommandLineParams(config, envData, $logger);
4853

@@ -77,22 +82,27 @@ exports.runWebpackCompiler = function runWebpackCompiler(config, $projectData, $
7782

7883
if (hookArgs.filesToSync && hookArgs.startSyncFilesTimeout) {
7984
hookArgs.filesToSync.push(...message.emittedFiles);
80-
hookArgs.startSyncFilesTimeout();
85+
hookArgs.startSyncFilesTimeout(platform);
86+
}
87+
88+
if (hookArgs.filesToSyncMap && hookArgs.startSyncFilesTimeout) {
89+
hookArgs.filesToSyncMap[platform] = message.emittedFiles;
90+
hookArgs.startSyncFilesTimeout(platform);
8191
}
8292
}
8393
}
8494

8595
if (config.watch) {
8696
childProcess.on("message", resolveOnWebpackCompilationComplete);
87-
if (webpackProcess) {
97+
if (webpackProcesses[platform]) {
8898
throw new Error("Webpack process already spawned.");
8999
}
90-
webpackProcess = childProcess;
100+
webpackProcesses[platform] = childProcess;
91101
}
92102

93103
childProcess.on("close", code => {
94-
if (webpackProcess == childProcess) {
95-
webpackProcess = null;
104+
if (webpackProcesses[platform] === childProcess) {
105+
delete webpackProcesses[platform];
96106
}
97107
if (code === 0) {
98108
resolve();
@@ -106,6 +116,14 @@ exports.runWebpackCompiler = function runWebpackCompiler(config, $projectData, $
106116
}
107117
}
108118

119+
exports.stopWebpackCompiler = function stopWebpackCompiler(platform) {
120+
if (platform) {
121+
stopWebpackForPlatform(platform);
122+
} else {
123+
Object.keys(webpackProcesses).forEach(platform => stopWebpackForPlatform(platform));
124+
}
125+
}
126+
109127
function buildEnvCommandLineParams(config, envData, $logger) {
110128
const envFlagNames = Object.keys(envData);
111129
const snapshotEnvIndex = envFlagNames.indexOf("snapshot");
@@ -136,3 +154,9 @@ function logSnapshotWarningMessage($logger) {
136154
}
137155
}
138156

157+
function stopWebpackForPlatform(platform) {
158+
const webpackProcess = webpackProcesses[platform];
159+
webpackProcess.kill("SIGINT");
160+
delete webpackProcesses[platform];
161+
}
162+

Diff for: package.json

+5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
"type": "after-prepare",
4545
"script": "lib/after-prepare.js",
4646
"inject": true
47+
},
48+
{
49+
"type": "before-preview-sync",
50+
"script": "lib/before-preview-sync",
51+
"inject": true
4752
}
4853
]
4954
},

Diff for: templates/webpack.angular.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ module.exports = env => {
4242
uglify, // --env.uglify
4343
report, // --env.report
4444
sourceMap, // --env.sourceMap
45-
hmr, // --env.hmr
45+
hmr, // --env.hmr,
4646
} = env;
47+
const externals = (env.externals || []).map((e) => { // --env.externals
48+
return new RegExp(e + ".*");
49+
});
4750

4851
const appFullPath = resolve(projectRoot, appPath);
4952
const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
@@ -63,6 +66,7 @@ module.exports = env => {
6366
const config = {
6467
mode: uglify ? "production" : "development",
6568
context: appFullPath,
69+
externals,
6670
watchOptions: {
6771
ignored: [
6872
appResourcesFullPath,

Diff for: templates/webpack.javascript.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ module.exports = env => {
4040
uglify, // --env.uglify
4141
report, // --env.report
4242
sourceMap, // --env.sourceMap
43-
hmr, // --env.hmr
43+
hmr, // --env.hmr,
4444
} = env;
45+
const externals = (env.externals || []).map((e) => { // --env.externals
46+
return new RegExp(e + ".*");
47+
});
4548

4649
const appFullPath = resolve(projectRoot, appPath);
4750
const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
@@ -52,6 +55,7 @@ module.exports = env => {
5255
const config = {
5356
mode: uglify ? "production" : "development",
5457
context: appFullPath,
58+
externals,
5559
watchOptions: {
5660
ignored: [
5761
appResourcesFullPath,

Diff for: templates/webpack.typescript.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ module.exports = env => {
4040
uglify, // --env.uglify
4141
report, // --env.report
4242
sourceMap, // --env.sourceMap
43-
hmr, // --env.hmr
43+
hmr, // --env.hmr,
4444
} = env;
45+
const externals = (env.externals || []).map((e) => { // --env.externals
46+
return new RegExp(e + ".*");
47+
});
4548

4649
const appFullPath = resolve(projectRoot, appPath);
4750
const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
@@ -52,6 +55,7 @@ module.exports = env => {
5255
const config = {
5356
mode: uglify ? "production" : "development",
5457
context: appFullPath,
58+
externals,
5559
watchOptions: {
5660
ignored: [
5761
appResourcesFullPath,

0 commit comments

Comments
 (0)