-
-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chnged: tns run
command to watch for changes by default
#2374
Conversation
8a98e65
to
f788f7e
Compare
6c3e780
to
b423d3b
Compare
@@ -3,11 +3,9 @@ import * as helpers from "../../common/helpers"; | |||
import * as path from "path"; | |||
import * as semver from "semver"; | |||
import * as fiberBootstrap from "../../common/fiber-bootstrap"; | |||
|
|||
let gaze = require("gaze"); | |||
let choki = require("chokidar"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to replace gaze with chokidar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also it's not added to package.json, so it will not be installed on any machine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there is a reason. I observed that gaze is quite slow and unstable when watching for a large number of files, while chokidar handles this scenario fast and reliable. Chokidar is the preferred watching tool used in webpack.
I added the corresponding entry in package.json
this.$processService.attachToProcessExitSignals(this, () => gazeWatcher.close()); | ||
this.$processService.attachToProcessExitSignals(this, () => { | ||
watcher.unwatch(pattern); | ||
process.exit(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need process.exit
call here? The attachToProcessExitSignals
means that it's already in process of exiting current process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not able to stop the process without calling process.exit. Maybe there is something specific in chokidar preventing the process from exiting. I didn't observed any side effects while testing this code. Watching for changes in all files is important in order to support predictable livesync. So I am open for suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just found a way to stop the watcher without process.exit. Changed the code.
chrome: { type: OptionType.Boolean } | ||
chrome: { type: OptionType.Boolean }, | ||
clean: { type: OptionType.Boolean }, | ||
watch: { type: OptionType.Boolean, default: true }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need of comma (,
) at the end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, yes. Someone could argue that this way it is easier to add new entries, however different languages, different styles.. removed the comma.
let localToDevicePaths:Mobile.ILocalToDevicePathData[] = null; | ||
let isFullSync = false; | ||
if (this.$options.clean || this.$projectChangesService.currentChanges.changesRequireBuild) { | ||
this.$platformService.buildPlatform(this.liveSyncData.platform, { buildForDevice: !device.isEmulator }).wait(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case you have two (or more) devices attached, you'll build your project for each of them, while in fact even a single build may be enough.
However this can be handled in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct! Changed the logic to build only when necessary. 👍
excludedDirs.push(constants.TNS_MODULES_FOLDER_NAME); | ||
} | ||
|
||
this.$projectFilesManager.processPlatformSpecificFiles(directoryPath, platform, excludedDirs); | ||
|
||
if (changeInfo.configChanged || changeInfo.modulesChanged) { | ||
if (!changesInfo || (changesInfo.configChanged || changesInfo.modulesChanged)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need of additional (
, just:
if (!changesInfo || changesInfo.configChanged || changesInfo.modulesChanged) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct! 👍
return path.join(deviceRootPath, buildInfoFileName); | ||
} | ||
|
||
private getDeviceBuildInfo(device: Mobile.IDevice): IBuildInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method has async operation, so it should return IFuture<IBuildInfo>
instead of IBuildInfo. When there's async code in the body, you should wrap it in a future:
return (() => {
....
}).future<IBuildInfo>()();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the method to use IFuture. 👍
|
||
public shouldInstall(device: Mobile.IDevice): boolean { | ||
if(this.$options.release) { | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the logic to always install the app in case --release
is specified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Humm, just wanted to ensure that everything is ok in release. In case if there are some artefacts from debug. It shouldn't be necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the code.
if (processFunc) { | ||
this._newFiles ++; | ||
let filePathRelative = path.relative(this.$projectData.projectDir, filePath); | ||
let that = this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you do not need that
variable here, you can pass this
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the variable. 👍
I've tested the current implementation for Android and there's some strange behavior. It looks like no matter of the change I made, a package.json is always transferred to the device. This causes double restart of the application during livesync. You can check this video where the issue is visible. |
Based on the code and related issues in the descriptions, I assume the current PR should allow adding new dependencies in package.json during
Should this work? |
818d805
to
1c81407
Compare
Regarding the scond rebuild on android, yes I confirm the issue. Like I pointed, it is caused by the android snapshot plugin. It modifies last modified times for different files explicitly every time it is executed (regardless if this is debug or release). I am not sure why it does this. It breaks the livesync watching logic. My personal opinion is that it should be corrected in android snapshot plugin. It should be able to work without changing file times explicitly. You shouldn't see this glitch if you remove the hooks related with android snapshot plugin from your project. |
No, currently adding dependencies while watching for changes will not work. This is caused by the fact that livesync syncs/rebuilds on every change. When adding a new dependency you are adding a lot of files at the same time. This will lead to unpredictable behaviour. In some cases it will cause endless sync/rebuild on every file change, in other cases it will break. I was not able to find an easy solution for this scenario. We should state this explicitly in our documentation. |
1c81407
to
81d4ca4
Compare
NOTE: Verify that this PR does not broke the case below: |
40d525c
to
c8d5a1a
Compare
Implemented pt redictable livesync Implement run command to use livesync project changes info as a service
c8d5a1a
to
b35259a
Compare
Changes the run command behavior to watch for changes by executing livesync.
Changes the livesync behavior to watch for changes in all files. The project-changes-service detects whether the change requires a full build or files can be livesynced.
The livesync state is preserved between calls, so no extra files will be transferred on second run.
Fixes: #1366, #2276, #2277, #2303, #2315, #2330, #2341, and most parts of #2153
The new prepare, build, deploy, run, debug and livesync commands behavior is described here: https://github.com/NativeScript/nativescript-cli/wiki/Workflow-commands-spec
It is based on the one described in this issue:
#475
Currently there are two issues not related with livesync:
DO NOT MERGE BEFORE telerik/mobile-cli-lib#863 is merged in mobile-cli-lib