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

Commit

Permalink
feat(livesync): enable webpack with watch (#433)
Browse files Browse the repository at this point in the history
* feat(livesync): enable webpack with watch

Plug into NativeScript CLI's LiveSync pipeline in order to enable incremental webpacking with watch.
Includes:
* Instruct CLI to watch `App_Resources` directory only
* Launch `webpack` with `--watch` on before-watch hook
* Do not launch multiple `webpack` processes

* refactor(livesync): extract app as constant

* chore(livesync): make code synchronous

* fix: do not rebuild every time

* fix: emit absolute paths
  • Loading branch information
Mitko-Kerezov authored Feb 22, 2018
1 parent cfc0a57 commit 847a56f
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 13 deletions.
3 changes: 1 addition & 2 deletions lib/before-prepareJS.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ module.exports = function ($mobileHelper, $projectData, hookArgs) {
const config = {
env,
platform,
bundle: appFilesUpdaterOptions.bundle,
watch: false // TODO: Read from CLI options...
bundle: appFilesUpdaterOptions.bundle
};
const result = config.bundle && runWebpackCompiler.bind(runWebpackCompiler, config, $mobileHelper, $projectData, hookArgs);
return result;
Expand Down
21 changes: 21 additions & 0 deletions lib/before-watch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { runWebpackCompiler } = require("./compiler");

module.exports = function ($mobileHelper, $projectData, hookArgs) {
if (hookArgs.config) {
const appFilesUpdaterOptions = hookArgs.config.appFilesUpdaterOptions;
if (appFilesUpdaterOptions.bundle) {
const platforms = hookArgs.config.platforms;
return Promise.all(platforms.map(platform => {
const env = hookArgs.config.env || {};
const config = {
env,
platform,
bundle: appFilesUpdaterOptions.bundle,
watch: true
};

return runWebpackCompiler(config, $mobileHelper, $projectData, hookArgs);
}));
}
}
}
16 changes: 16 additions & 0 deletions lib/before-watchPatterns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const { AppDirectoryLocation } = require("./constants");

module.exports = function (hookArgs) {
if (hookArgs.liveSyncData && hookArgs.liveSyncData.bundle) {
return (args, originalMethod) => {
return originalMethod().then(originalPatterns => {
const appDirectoryLocationIndex = originalPatterns.indexOf(AppDirectoryLocation);
if (appDirectoryLocationIndex !== -1) {
originalPatterns.splice(appDirectoryLocationIndex, 1);
}

return originalPatterns;
});
};
}
}
26 changes: 17 additions & 9 deletions lib/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { join, resolve: pathResolve } = require("path");
const { existsSync } = require("fs");
const readline = require("readline");
const { messages } = require("../plugins/WatchStateLoggerPlugin");
const { AppDirectoryLocation } = require("./constants");

let hasBeenInvoked = false;

Expand All @@ -16,25 +17,19 @@ exports.getWebpackProcess = function getWebpackProcess() {
exports.runWebpackCompiler = function runWebpackCompiler(config, $mobileHelper, $projectData, hookArgs, originalArgs, originalMethod) {
if (config.bundle) {
return new Promise(function (resolveBase, rejectBase) {
if (hookArgs && hookArgs.config && hookArgs.config.changesInfo) {
hookArgs.config.changesInfo.nativeChanged = true;
if (webpackProcess) {
return resolveBase();
}

let isResolved = false;
function resolve() {
if (isResolved) return;
isResolved = true;
if (childProcess) {
childProcess.removeListener("message", resolveOnWebpackCompilationComplete);
}
resolveBase();
}
function reject(error) {
if (isResolved) return;
isResolved = true;
if (childProcess) {
childProcess.removeListener("message", resolveOnWebpackCompilationComplete);
}
rejectBase(error);
}

Expand Down Expand Up @@ -75,11 +70,24 @@ exports.runWebpackCompiler = function runWebpackCompiler(config, $mobileHelper,
cwd: $projectData.projectDir
});

let isFirstWebpackWatchCompilation = true;
function resolveOnWebpackCompilationComplete(message) {
if (message === messages.compilationComplete) {
console.log("Initial webpack build done!");
console.log("Webpack build done!");
resolve();
}

if (message.emittedFiles) {
if (isFirstWebpackWatchCompilation) {
isFirstWebpackWatchCompilation = false;
return;
}

if (hookArgs.filesToSync && hookArgs.startSyncFilesTimeout) {
hookArgs.filesToSync.push(...message.emittedFiles.map(emittedFile => join($projectData.projectDir, AppDirectoryLocation, emittedFile)));
hookArgs.startSyncFilesTimeout();
}
}
}

if (config.watch) {
Expand Down
3 changes: 3 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
AppDirectoryLocation: "app"
};
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@
"script": "lib/before-cleanApp.js",
"inject": true
},
{
"type": "before-watch",
"script": "lib/before-watch.js",
"inject": true
},
{
"type": "before-watchPatterns",
"script": "lib/before-watchPatterns.js",
"inject": true
},
{
"type": "after-prepare",
"script": "lib/after-prepare.js",
Expand Down
11 changes: 9 additions & 2 deletions plugins/WatchStateLoggerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,29 @@ export class WatchStateLoggerPlugin {
isRunningWatching: boolean;
apply(compiler) {
const plugin = this;
compiler.plugin("watch-run", function(compiler, callback) {
compiler.plugin("watch-run", function (compiler, callback) {
plugin.isRunningWatching = true;
if (plugin.isRunningWatching) {
console.log(messages.changeDetected);
}
process.send && process.send(messages.changeDetected, error => null);
callback();
});
compiler.plugin("after-emit", function(compilation, callback) {
compiler.plugin("after-emit", function (compilation, callback) {
callback();
if (plugin.isRunningWatching) {
console.log(messages.startWatching);
} else {
console.log(messages.compilationComplete);
}

const emittedFiles = Object
.keys(compilation.assets)
.filter(assetKey => compilation.assets[assetKey].emitted);

process.send && process.send(messages.compilationComplete, error => null);
// Send emitted files so they can be LiveSynced if need be
process.send && process.send({ emittedFiles }, error => null);
});
}
}
3 changes: 3 additions & 0 deletions templates/webpack.angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ module.exports = env => {

const config = {
context: resolve("./app"),
watchOptions: {
ignored: resolve("./app/App_Resources")
},
target: nativescriptTarget,
entry: {
bundle: aot ? "./main.aot.ts" : "./main.ts",
Expand Down
3 changes: 3 additions & 0 deletions templates/webpack.javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ module.exports = env => {

const config = {
context: resolve("./app"),
watchOptions: {
ignored: resolve("./app/App_Resources")
},
target: nativescriptTarget,
entry: {
bundle: `./${nsWebpack.getEntryModule()}`,
Expand Down
3 changes: 3 additions & 0 deletions templates/webpack.typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ module.exports = env => {

const config = {
context: resolve("./app"),
watchOptions: {
ignored: resolve("./app/App_Resources")
},
target: nativescriptTarget,
entry: {
bundle: `./${nsWebpack.getEntryModule()}`,
Expand Down

0 comments on commit 847a56f

Please sign in to comment.