Rapid chrome extension development [duplicate] - javascript

I'd like for my chrome extension to reload every time I save a file in the extension folder, without having to explicitly click "reload" in chrome://extensions/. Is this possible?
Edit: I'm aware I can update the interval at which Chrome reloads extensions, which is a half-way solution, but I'd rather either making my editor (emacs or textmate) trigger on-save a reload or asking Chrome to monitor the directory for changes.

You can use "Extensions Reloader" for Chrome:
Reloads all unpacked extensions using the extension's toolbar button or by browsing to "http://reload.extensions"
If you've ever developed a Chrome extension, you might have wanted to
automate the process of reloading your unpacked extension without the
need of going through the extensions page.
"Extensions Reloader" allows you to reload all unpacked extensions
using 2 ways:
1 - The extension's toolbar button.
2 - Browsing to "http://reload.extensions".
The toolbar icon will reload unpacked extensions using a single click.
The "reload by browsing" is intended for automating the reload process
using "post build" scripts - just add a browse to
"http://reload.extensions" using Chrome to your script, and you'll
have a refreshed Chrome window.
Update: As of January 14, 2015, the extension is open-sourced and available on GitHub.

Update: I have added an options page, so that you don't have to manually find and edit the extension's ID any more. CRX and source code are at: https://github.com/Rob--W/Chrome-Extension-Reloader
Update 2: Added shortcut (see my repository on Github).
The original code, which includes the basic functionality is shown below.
Create an extension, and use the Browser Action method in conjunction with the chrome.extension.management API to reload your unpacked extension.
The code below adds a button to Chrome, which will reload an extension upon click.
manifest.json
{
"name": "Chrome Extension Reloader",
"version": "1.0",
"manifest_version": 2,
"background": {"scripts": ["bg.js"] },
"browser_action": {
"default_icon": "icon48.png",
"default_title": "Reload extension"
},
"permissions": ["management"]
}
bg.js
var id = "<extension_id here>";
function reloadExtension(id) {
chrome.management.setEnabled(id, false, function() {
chrome.management.setEnabled(id, true);
});
}
chrome.browserAction.onClicked.addListener(function(tab) {
reloadExtension(id);
});
icon48.png: Pick any nice 48x48 icon, for example:

I've made a simple embeddable script doing hot reload:
https://github.com/xpl/crx-hotreload
It watches for file changes in an extension's directory. When a change detected, it reloads the extension and refreshes the active tab (to re-trigger updated content scripts).
Works by checking timestamps of files
Supports nested directories
Automatically disables itself in the production configuration

in any function or event
chrome.runtime.reload();
will reload your extension (docs). You also need to change the manifest.json file, adding:
...
"permissions": [ "management" , ...]
...

I am using a shortcut to reload. I don't want to reload all the time when I save a file
So my approach is lightweight, and you can leave the reload function in
manifest.json
{
...
"background": {
"scripts": [
"src/bg/background.js"
],
"persistent": true
},
"commands": {
"Ctrl+M": {
"suggested_key": {
"default": "Ctrl+M",
"mac": "Command+M"
},
"description": "Ctrl+M."
}
},
...
}
src/bg/background.js
chrome.commands.onCommand.addListener((shortcut) => {
console.log('lets reload');
console.log(shortcut);
if(shortcut.includes("+M")) {
chrome.runtime.reload();
}
})
Now press Ctrl + M in the chrome browser to reload

Another solution would be to create custom livereload script (extension-reload.js):
// Reload client for Chrome Apps & Extensions.
// The reload client has a compatibility with livereload.
// WARNING: only supports reload command.
var LIVERELOAD_HOST = 'localhost:';
var LIVERELOAD_PORT = 35729;
var connection = new WebSocket('ws://' + LIVERELOAD_HOST + LIVERELOAD_PORT + '/livereload');
connection.onerror = function (error) {
console.log('reload connection got error:', error);
};
connection.onmessage = function (e) {
if (e.data) {
var data = JSON.parse(e.data);
if (data && data.command === 'reload') {
chrome.runtime.reload();
}
}
};
This script connects to the livereload server using websockets. Then, it will issue a chrome.runtime.reload() call upon reload message from livereload. The next step would be to add this script to run as background script in your manifest.json, and voila!
Note: this is not my solution. I'm just posting it. I found it in the generated code of Chrome Extension generator (Great tool!). I'm posting this here because it might help.

TL;DR
Create a WebSocket server that dispatches a message to a background script that can handle the update. If you are using webpack and don't plan to do it yourself, webpack-run-chrome-extension can help.
Answer
You can create a WebSocket server to communicate with the extension as a WebSocket client (via window object). The extension would then listen for file changes by attaching the WebSocket server to some listener mechanism (like webpack devServer).
Did the file change? Set the server to dispatch a message to the extension asking for updates (broadcasting the ws message to the client(s)). The extension then reloads, replies with "ok, reloaded" and keeps listening for new changes.
Plan
Set up a WebSocket server (to dispatch update requests)
Find a service that can tell you when did the files change (webpack/other bundler software)
When an update happens, dispatch a message to client requesting updates
Set up a WebSocket client (to receive update requests)
Reload the extension
How
For the WebSocket server, use ws. For file changes, use some listener/hook (like webpack's watchRun hook). For the client part, native WebSocket. The extension could then attach the WebSocket client on a background script for keeping sync persistent between the server (hosted by webpack) and the client (the script attached in the extension background).
Now, to make the extension reload itself, you can either call chrome.runtime.reload() in it each time the upload request message comes from the server, or even create a "reloader extension" that would do that for you, using chrome.management.setEnabled() (requires "permissions": [ "management" ] in manifest).
In the ideal scenario, tools like webpack-dev-server or any other web server software could offer support for chrome-extension URLs natively. Until that happens, having a server to proxy file changes to your extension seems to be the best option so far.
Available open-source alternative
If you are using webpack and don't want to create it all yourself, I made webpack-run-chrome-extension, which does what I planned above.

Chrome Extensions have a permission system that it wouldn't allow it (some people in SO had the same problem as you), so requesting them to "add this feature" is not going to work IMO. There's a mail from Chromium Extensions Google Groups with a proposed solution (theory) using chrome.extension.getViews(), but is not guaranteed to work either.
If it was possible to add to the manifest.json some Chrome internal pages like chrome://extensions/, it would be possible to create a plugin that would interact to the Reload anchor, and, using an external program like XRefresh (a Firefox Plugin - there's a Chrome version using Ruby and WebSocket), you would achieve just what you need:
XRefresh is a browser plugin which
will refresh current web page due to
file change in selected folders. This
makes it possible to do live page
editing with your favorite HTML/CSS
editor.
It's not possible to do it, but I think you can use this same concept in a different way.
You could try to find third-party solutions instead that, after seeing modifications in a file (I don't know emacs neither Textmate, but in Emacs it would be possible to bind an app call within a "save file" action), just clicks in an specific coordinate of an specific application: in this case it's the Reload anchor from your extension in development (you leave a Chrome windows opened just for this reload).
(Crazy as hell but it may work)

Here's a function that you can use to watch files for changes, and reload if changes are detected. It works by polling them via AJAX, and reloading via window.location.reload(). I suppose you shouldn't use this in a distribution package.
function reloadOnChange(url, checkIntervalMS) {
if (!window.__watchedFiles) {
window.__watchedFiles = {};
}
(function() {
var self = arguments.callee;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (__watchedFiles[url] &&
__watchedFiles[url] != xhr.responseText) {
window.location.reload();
} else {
__watchedFiles[url] = xhr.responseText
window.setTimeout(self, checkIntervalMS || 1000);
}
}
};
xhr.open("GET", url, true);
xhr.send();
})();
}
reloadOnChange(chrome.extension.getURL('/myscript.js'));

The great guys at mozilla just released a new https://github.com/mozilla/web-ext that you can use to launch web-ext run --target chromium

Maybe I'm a little late to the party, but I've solved it for me by creating https://chrome.google.com/webstore/detail/chrome-unpacked-extension/fddfkmklefkhanofhlohnkemejcbamln
It works by reloading chrome://extensions page, whenever file.change events are incoming via websockets.
A Gulp-based example of how to emit file.change event upon file changes in an extension folder can be found here: https://github.com/robin-drexler/chrome-extension-auto-reload-watcher
Why reloading the entire tab instead of just using the extensions management api to reload/re-enable extensions? Currently disabling and enabling extensions again causes any open inspection window (console log etc.) to close, which I found to be too annoying during active development.

There's an automatic reload plugin if you're developing using webpack:
https://github.com/rubenspgcavalcante/webpack-chrome-extension-reloader
const ChromeExtensionReloader = require('webpack-chrome-extension-reloader');
plugins: [
new ChromeExtensionReloader()
]
Also comes with a CLI tool if you don't want to modify webpack.config.js:
npx wcer
Note: an (empty) background script is required even if you don't need it because that's where it injects reload code.

Maybe a bit late answer but I think crxreload might work for you. It's my result of trying to have a reload-on-save workflow while developing.

Use npm init to create a package.json in directory root, then
npm install --save-dev gulp-open && npm install -g gulp
then create a gulpfile.js
which looks like:
/* File: gulpfile.js */
// grab our gulp packages
var gulp = require('gulp'),
open = require('gulp-open');
// create a default task and just log a message
gulp.task('default', ['watch']);
// configure which files to watch and what tasks to use on file changes
gulp.task('watch', function() {
gulp.watch('extensionData/userCode/**/*.js', ['uri']);
});
gulp.task('uri', function(){
gulp.src(__filename)
.pipe(open({uri: "http://reload.extensions"}));
});
This works for me developing with CrossRider, you might watch to change the path you watch the files at, also assuming you have npm and node installed.

Your content files such has html and manifest files are not changeable without installation of the extension, but I do believe that the JavaScript files are dynamically loaded until the extension has been packed.
I know this because of a current project im working on via the Chrome Extensions API, and seems to load every-time i refresh a page.

Disclaimer: I developed this extension myself.
Clerc - for Chrome Live Extension Reloading Client
Connect to a LiveReload compatible server to automatically reload your extension every time you save.
Bonus: with a little extra work on your part, you can also automatically reload the webpages that your extension alters.
Most webpage developers use a build system with some sort of watcher that automatically builds their files and restarts their server and reloads the website.
Developing extensions shouldn't need to be that different. Clerc brings this same automation to Chrome devs. Set up a build system with a LiveReload server, and Clerc will listen for reload events to refresh your extension.
The only big gotcha is changes to the manifest.json. Any tiny typos in the manifest will probably cause further reload attempts to fail, and you will be stuck uninstalling/reinstalling your extension to get your changes loading again.
Clerc forwards the complete reload message to your extension after it reloads, so you can optionally use the provided message to trigger further refresh steps.

Thanks to #GmonC and #Arik and some spare time, I managet to get this working. I have had to change two files to make this work.
(1) Install LiveReload and Chrome Extension for that application.
This will call some script on file change.
(2) Open <LiveReloadInstallDir>\Bundled\backend\res\livereload.js
(3) change line #509 to
this.window.location.href = "http://reload.extensions";
(4) Now install another extension Extensions Reloader which has useful link handler that reload all development extensions on navigating to "http://reload.extensions"
(5) Now change that extension's background.min.js in this way
if((d.installType=="development")&&(d.enabled==true)&&(d.name!="Extensions Reloader"))
replace with
if((d.installType=="development")&&(d.enabled==true)&&(d.name!="Extensions Reloader")&&(d.name!="LiveReload"))
Open LiveReload application, hide Extension Reloader button and activate LiveReload extension by clicking on button in toolbar, you will now reload page and extensions on each file change while using all other goodies from LiveReload (css reload, image reload etc.)
Only bad thing about this is that you will have to repeat procedure of changing scripts on every extension update. To avoid updates, add extension as unpacked.
When I'll have more time to mess around with this, I probably will create extension that eliminates need for both of these extensions.
Untill then, I'm working on my extension Projext Axeman

Just found a newish grunt based project that provides bootstrapping, scaffolding, some automated pre-processing faculty, as well as auto-reloading (no interaction needed).
Bootstrap Your Chrome Extension from Websecurify

I want to reload (update) my extensions overnight, this is what I use in background.js:
var d = new Date();
var n = d.getHours();
var untilnight = (n == 0) ? 24*3600000 : (24-n)*3600000;
// refresh after 24 hours if hour = 0 else
// refresh after 24-n hours (that will always be somewhere between 0 and 1 AM)
setTimeout(function() {
location.reload();
}, untilnight);
Regards,
Peter

I primarily develop in Firefox, where web-ext run automatically reloads the extension after files change. Then once it's ready, I do a final round of testing in Chrome to make sure there aren't any issues that didn't show up in Firefox.
If you want to develop primarily in Chrome, though, and don't want to install any 3rd party extensions, then another option is to create a test.html file in the extension's folder, and add a bunch of SSCCE's to it. That file then uses a normal <script> tag to inject the extension script.
You could use that for 95% of testing, and then manually reload the extension when you want to test it on live sites.
That doesn't identically reproduce the environment that an extension runs in, but it's good enough for many simple things.

MAC ONLY
Using Extensions Reloader:
Using Typescript
Add the watcher of your to your project: yarn add tsc-watch
Add command to scripts to package.json
...
"scripts": {
"dev": "tsc-watch --onSuccess \"open -a '/Applications/Google Chrome.app' 'http://reload.extensions'\""
},
...
Run script yarn dev
Using JavaScript
Add the watcher of your to your project: yarn add watch-cli
Add command to scripts to package.json
...
"scripts": {
"dev": "watch -p \"**/*.js\" -c \"open -a '/Applications/Google Chrome.app' 'http://reload.extensions'\""
},
...
Run script yarn dev
Bonus: Turn on 'reload current tab' in Extensions Reloader options, so it reloads after a change was made:

I've forked LiveJS to allow for live reloading of Packaged Apps. Just include the file in your app and every time you save a file the app will autoreload.

As mentioned in the docs: the following command line will reload an app
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --load-and-launch-app=[path to the app ]
so I just created a shell script and called that file from gulp. Super simple:
var exec = require('child_process').exec;
gulp.task('reload-chrome-build',function(cb){
console.log("reload");
var cmd="./reloadchrome.sh"
exec(cmd,function (err, stdout, stderr) {
console.log("done: "+stdout);
cb(err);
}
);});
run your necessary watch commands on scripts and call the reload task when you want to. Clean, simple.

This is where software such as AutoIt or alternatives shine. The key is writing a script which emulates your current testing phase. Get used to using at least one of them as many technologies do not come with clear workflow/testing paths.
Run("c:\Program Files (x86)\Google\Chrome\Application\chrome.exe")
WinWaitActive("New Tab - Google Chrome")
Send("^l")
Send("chrome://extensions{ENTER}")
WinWaitActive("Extensions - Google Chrome")
Send("{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}")
Send("{ENTER}")
WinWaitActive("Extensions - Google Chrome")
Send("{TAB}{TAB}")
Send("{ENTER}")
WinWaitActive("Developer Tools")
Send("^`")
Obviously you change the code to suit your testing/iterating needs. Make sure tab clicks are true to where the anchor tag is in the chrome://extensions site. You could also use relative to window mouse movements and other such macros.
I would add the script to Vim in a way similar to this:
map <leader>A :w<CR>:!{input autoit loader exe here} "{input script location here}"<CR>
This means that when I'm in Vim I press the button above ENTER (usually responsible for: | and \) known as the leader button and follow it with a capital 'A' and it saves and begins my testing phase script.
Please make sure to fill in the {input...} sections in the above Vim/hotkey script appropriately.
Many editors will allow you to do something similar with hotkeys.
Alternatives to AutoIt can be found here.
For Windows: AutoHotkey
For Linux: xdotool, xbindkeys
For Mac: Automator

If you have a Mac, ¡the easiest way is with Alfred App!
Just get Alfred App with Powerpack, then add the workflow provided in the link below and customise the hotkey you want (I like to use ⌘ + ⌥ + R). That's all.
Now, every time you use the hotkey, Google Chrome will reload, no matter which application you're at that moment.
If you want to use other browser, open the AppleScript inside Alfred Preferences Workflows and replace "Google Chrome" with "Firefox", "Safari", ...
I also will show here the content of the /usr/bin/osascript script used in the ReloadChrome.alfredworkflow file so you can see what it is doing.
tell application "Google Chrome"
activate
delay 0.5
tell application "System Events" to keystroke "r" using command down
delay 0.5
tell application "System Events" to keystroke tab using command down
end tell
The workflow file is ReloadChrome.alfredworkflow.

The author recommended the next version of that webpack plugin: https://github.com/rubenspgcavalcante/webpack-extension-reloader. It works very well for me.

Yes,you can do it indirectly! Here is my solution.
In manifest.json
{
"name": "",
"version": "1.0.0",
"description": "",
"content_scripts":[{
"run_at":"document_end",
"matches":["http://*/*"],
"js":["/scripts/inject.js"]
}]
}
In inject.js
(function() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = 'Your_Scripts';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
})();
Your injected script can inject other script from any location.
Another benefit from this technic is that you can just ignore the limitation of isolated world. see content script execution environment

BROWSER-SYNC
Using the amazing Browser-Sync
update browsers (any) when source code changes (HTML, CSS, images, etc.)
support Windows, MacOS and Linux
you could even watch your code updates (live) using your mobile devices
Instalation on MacOS (view their help to install on other OS)
Install NVM, so you can try any Node version
brew install nvm # install a Node version manager
nvm ls-remote # list available Node versions
nvm install v10.13.0 # install one of them
npm install -g browser-sync # install Browser-Sync
How to use browser-sync for static sites
Let's see two examples:
browser-sync start --server --files . --host YOUR_IP_HERE --port 9000
browser-sync start --server --files $(ack --type-add=web:ext:htm,html,xhtml,js,css --web -f | tr \\n \ ) --host $(ipconfig getifaddr en0) --port 9000
The --server option allow you to run a local server anywhere you are in your terminal and --files let you specify which files will be tracked for changes. I prefer to be more specific for the tracked files, so in the second example I use ack for listing specific file extensions (is important that those files do not have filenames with spaces) and also useipconfig to find my current IP on MacOS.
How to use browser-sync for dynamic sites
In case you are using PHP, Rails, etc., you already have a running server, but it doesn't refresh automatically when you make changes to your code. So you need to use the --proxy switch to let browser-sync know where is the host for that server.
browser-sync start --files $(ack --type-add=rails:ext:rb,erb,js,css,sass,scss,coffee --rails -f | tr \\n \ ) --proxy 192.168.33.12:3000 --host $(ipconfig getifaddr en0) --port 9000 --no-notify --no-open
In the above example, I already have a Rails app running on my browser on 192.168.33.12:3000. It really runs on a VM using a Vagrant box, but I could access the virtual machine using port 3000 on that host. I like --no-notify to stop browser-sync sending me a notification alert on the browser every time I change my code and --no-open to stop browser-sync behavior that immediately loads a browser tab when the server start.
IMPORTANT: Just in case you're using Rails, avoid using Turbolinks on development, otherwise you will not be able click on your links while using the --proxy option.
Hope it would be useful to someone. I've tried many tricks to refresh the browser (even an old post I've submitted on this StackOverflow question using AlfredApp time ago), but this is really the way to go; no more hacks, it just flows.
CREDIT: Start a local live reload web server with one command

It can't be done directly. Sorry.
If you would like to see it as a feature you can request it at http://crbug.com/new

Related

Is there a way, in Node or Gulp, to reload the browser with a specific URL?

Apologies in advance if this is not the right place to ask.
Due to the way my workplace/CMS is set up I do not have access to a local version of the site to develop on. Instead, we are devloping CSS and JS locally (compiling with Node and Gulp) and using a Chrome extension to use those local .css and .js files on the live site. Whilst this is not ideal, it is working.
I want to incorporate automatic browser refreshing into this. I've looked into Browser-Sync but as per their documentation:
Browsersync works by injecting an asynchronous script tag (<script async>...</script>) right after the tag
So that's not an option (assuming the file it injects into has to be local and writable).
I've also looked at Live Reload BP but that seems to work the same way.
Does anyone know of a way to have Node or Gulp reload the browser given a specific third-party URL?
What I want to achieve is something like:
gulp.task('watch', ['browserSync', 'sass'], function (){
gulp.watch('app/scss/**/*.scss', ['sass']);
});
gulp.task('browserSync', function() {
reload: 'https://somesite.com/test';
})
This can be done by simply spawning a browser process, for example on Windows:
gulp.task('browserSync', function(done) {
const { exec } = require('child_process');
exec('start Chrome https://somesite.com/test', done); // Use Chrome on Windows
});
For cross-os and cross-browser compatibility, there are third party utilities like open.
Install the dependency:
npm i -D open
Then use it in your task:
gulp.task('browserSync', async function() {
const open = require('open');
await open('https://somesite.com/test'); // Use default browser
});

Why might Chrome (inside Electron) suddenly redirect to chrome-error://chromewebdata?

My electron app is randomly redirecting to chrome-error://chromewebdata, and I've no idea why. There's no errors in the console, etc.
When the Electron app first starts, the window opens, and it redirects away from my application to that URL and I see an empty blank white screen. No user interaction is necessary, it just happens when the app starts.
If I open devtools, I can see that window.location.href contains chrome-error://chromewebdata instead of http://localhost:9080 (the Electron app runs using a localhost URL).
I tried deleting the local Electron/Chrome data folder at ~/Library/Application Support/my-app-name and starting over, but no luck.
What are reasons that Chrome (in Electron?) can decide to redirect to chrome-error://chromewebdata?
For some reason, your code is trying to navigate to an invalid (non-existing) URL, which then results in window.location.href being chrome-error://chromewebdata.
To reiterate: there is no direct redirection to chrome-error://chromewebdata, but instead to a URL that doesn't exist or is not reachable.
Check if your code causes this navigation (possibly a redirect). It is very useful to inspect the Network tab in DevTools, making sure that "Preserve log" is checked. This should give some indication about what exactly is happening.
This is happening for me in my Angular based Electron project. In my case, the problem is that Angular's Webpack server isn't ready to receive requests when I first launch the project. This is only at startup and simple reload can get around it - any live changes to the Angular code will refresh the page without any issue.
This isn't a problem in production as I switch to loading static files in my releases.
To make this a little less annoying, I added a delay to my electron startup:
"start": "concurrently -k \"ng serve\" \"npm run delay && nodemon\"",
"delay": "node -e \"setTimeout(() => true, 3000)\"",
Where:
concurrently runs Electron and Angular/Webpack at the same time for faster development.
nodemon watches my electron files and restarts the app when I save changes
delay just uses node to delay nodemon's first startup (works on all operating systems...)
And just for clarity, my nodemon.json:
{
"watch": ["nucleus"],
"ext": "*",
"exec": "tsc -p nucleus/tsconfig.json && electron ."
}
view-vhcl-cntr-ctgrs.tpl
i replace this file name like below.
view-vhclcntr-ctgrs.tpl
and it worked....
To me it was launchPath issue. As I had multiple electron apps in my workspace (NX).
So all I needed to do is to set correct url to launch electron.
It was 4200 by default so I updated it to 4202 b/c I already had 4200 & 4201.
let launchPath;
if (serve) {
require('electron-reload')(__dirname, {
electron: require(`${__dirname}/../../../node_modules/electron`),
});
launchPath = 'http://localhost:4202';
win.loadURL(launchPath);
} else {
launchPath = url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true,
});
win.loadURL(launchPath);
}
console.log('launched electron with:', launchPath);

Gulp with live-reload

I have a website that I've built with Node. I can successfully start and run the site by running node server.js from the command-line. I then access the site by visiting "http://localhost:3000" in my browser. I'm now trying to improve some of the build process surrounding the site. To do that, I'm relying on Gulp.
I want to automatically reload the webpage when a change is made to the HTML or CSS files. I stumbled upon the gulp-livereload plugin. I have installed it as described in the docs. However, when I visit "http://localhost:35729/" in the browser, I just see the following:
{
minilr: "Welcome",
version: "0.1.8"
}
My gulp task is configured like this:
gulp.task('launch', function() {
var toWatch = [
'src/**/*.html',
'src/**/*.css'
];
livereload.listen();
gulp.watch(toWatch, function() {
console.log('reloading...');
livereload();
})
}
I do not see my home page like I do when I visit "http://localhost:3000" after running node server.js. What am I missing?
Live reload is a protocol to send notifications to the browser to do a reload. But you need a browser plugin to listen and do the reload, although it is possible to forgo the plugin using a script tag.
The gulp-livereload plugin only concerns itself with the implementation of the livereload server, you still need to serve the files via a http server from gulp.
You can use a gulp module that does both gulp-connect.
However unless you are tied to livereload for some reason, I suggest using browserync. Browsersync is a nice alternative to livereload that aditionally adds
the capacity of syncing your view between browsers. Since it injects a script tag into your html and listens on a socket you don't need any plugins to make it work. It works even on Mobile devices.
A gulp task to use browsersync might look like this. Don't forget to add browsersync to your
package.json file
var browserSync = require('browser-sync').create();
gulp.task('serve', [] , function( cb ){
browserSync.init({
open: true ,
server: {
baseDir: "src"
}
});
gulp.watch([
'src/**/*' ,
] , ['serve:reload'] );
});
gulp.task('serve:reload' , [] , function(){
browserSync.reload();
});
Why are you visiting 'http://localhost:35729/' ? If this is port where livereload is listening then it won't show your site, because as you said your site is available from 'http://localhost:3000'.
I assume that you have correctly configure gulp. By it I mean that livereload is listening, and you watch changes in your files and in pipes you have '.pipe(livereload()'.
You have to install https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei
you have to run your app 'http://localhost:3000' in chrome browser.
you will have in browser plugin bar new icon (this is icon of this plugin)
you have to click this icon to run this plugin
finish
Now when you change something in files, gulp watcher will notice this, do some work, and inform chrome plugin that there are changes, This plugin will refresh your project page.

How can I make node-inspector restart when node is restarted?

I use node-inspector a lot. When I edit my code and restart, I get the inevitable
Detached from the target
Error when a new process starts. I always have to go find the tab node inspector is on and restart it.
I was wondering if I could avoid this. For example, send a message to node-inspector from node to tell the browsers tab running node-inspector to restart.
You don't have to restart the Node Inspector process itself when the debugged process was restarted. All you need to do is reload the browser tab with Node Inspector GUI.
I am afraid there is no easy way at the moment for automatically reloading the Node Inspector GUI page when your debugged process is restarted. It is probably possible to perform some kind of active polling in Node Inspector backend, but that's a feature that would have to be implemented by somebody.
Depending on what part of your application you are debugging, you might find useful the feature "Live Edit". It allows you to edit your code from Node Inspector, save the changes to the Node/V8 runtime and possibly back to disk too. That way you don't have to restart the debugged process after you made your changes.
This feature has been implemented in Node Inspector and released in v0.7.0. See issue #266 for more details.
This feature has been implemented in Node Inspector and released in v0.7.0. See issue #266 for more details.
Previous answer here's a workaround:
I wrote a simple js script to be executed by greasemonkey/tampermonkey.
The script looks for the message "Detached from the target" on tab with address http://127.0.0.1:8080/debug?port=5858. Once the message is visible the page reloads until it disappears.
This solution is a workaround. It shouldn't be considered the ideal solution (I agree with Miroslav), here follows:
// ==UserScript==
// #name Reload node-inspector tab
// #version 0.1
// #description looks for the detached message and auto reload the page
// #match http://127.0.0.1:8080/debug?port=5858
// ==/UserScript==
var exec = function(){
setTimeout(function(){
var el = document.getElementsByClassName("help-window-title")[0];
if(el && el.innerHTML == "Detached from the target"){
location.reload();
} else {
setTimeout(function(){ exec(); }, 1000);
}
}, 1000);
};
exec();
Step1. don't use node-inspector - new work has been shipped by chrome team, which can't be integrated with node-inspector module. Moving forward you gonna miss those features if you stay with node-inspector.
Step2. To run your script use: nodemon --inspect-brk yourScript.js - the brk part creates an automatic break-point on the first line of code. If you don't have nodemon already installed, you do that first using: npm install -g nodemon.
Step3. Then open chrome app, open chrome dev tools (F12 or Ctrl+Shift+I) and click the node icon like so:
Step4. Make changes to yourScript.js - chrome devtools automagically reloads the debugger for every change you make in your project. This is because nodemon watches the project folder and resets the process - which resets the debugger connection.
More here: Debugging in 2017 with Node.js - i'm writing this in 29 august 2019 but 2 years later is still relevant.
Cross-posting slightly from this SO, with an update to this topic.
There is a link in Chrome (58) standard Developer Pane which opens a new "headless" window which reconnects magically to node inspect no matter how the app is rebuilt / restarted.
I'm running Express.js e.g. DEBUG=myapp:* supervisor -- --inspect bin/www & and found it difficult to reconnect using the normal guid-laden URL which keeps changing. But this Chrome tool works all day reconnecting reliably.
Under Threads > Main, you should see "Node instance available. Connect".
I find the new-window less usable as I'd prefer a tab, but the auto-reconnect is so reliable I'll live with that!
The only downside I've found is when it does reconnect it clears all breakpoints.
Sure, it's easy. First install npm install -g nodemon
Then you can run node-inspector & nodemon --debug app.js
(replacing app.js with the name of your script)
Though on syntax error you still may need to reload node-inspector tab manually

How to register a url protocol handler in Node.js

I am developing a command line node module and would like to be able to launch it via links on a website.
I want to register a custom protocol my-module:// such that links would have the following format: my-module://action:some-action and clicking on them would start the node package.
If there isn't a node API for this (I'm sure there won't be) then is there a way I can do it from node by invoking system commands?
It must work on Windows, Linux, and MacOS.
Its an interesting idea. I don't think there is currently a cross platform node.js solution out there. I did come across this thread of people asking for the same thing:
https://github.com/rogerwang/node-webkit/issues/951
Electron now supports it with the app.setAsDefaultProtocolClient API (since v0.37.4) for macOS and Windows.
It wouldn't be terribly difficult to write the library to do this.
Windows:
On the windows side you'd have to register the app as the application that handles that URI scheme.
You'll need to set up a registry entry for your application:
HKEY_CLASSES_ROOT
alert
(Default) = "URL:Alert Protocol"
URL Protocol = ""
DefaultIcon
(Default) = "alert.exe,1"
shell
open
command
(Default) = "C:\Program Files\Alert\alert.exe" "%1"
Then, when your application is run by windows, you should be able to see the arguments in process.argv[]. Make sure that you launch a shell to run node, not just your application directly.
Original MSDN article
Note this requires administrator privileges and sets the handler system-wide. To do it per user, you can use HKEY_CURRENT_USER\Software\Classes instead, as the Electron's implementation does it.
Apple:
The cited "OS X" article in the github comment is actually for iOS. I'd look at the following programming guide for info on registering an application to handle a URL scheme:
Apple Dev Documentation
In summary, you'll need to create a launch service and populate the .plist file with CFBundleURLTypes, this field is an array and should be populated with just the protocol name i.e. http
The following Super User Question has a better solution, but is a per user setting.
"The file you seek is ~/Library/Preferences/com.apple.LaunchServices.plist.
It holds an array called LSHandlers, and the Dictionary children that define an LSHandlerURLScheme can be modified accordingly with the LSHandlerRole."
Linux:
From what I can tell, there are several ways to accomplish this in Linux (surprise?)
Gnome has a tool that will let you register a url handler w3 archives
gconftool-2 -t string -s /desktop/gnome/url-handlers/tel/command "bin/vonage-call %s"
gconftool-2 -s /desktop/gnome/url-handlers/tel/needs_terminal false -t bool
gconftool-2 -t bool -s /desktop/gnome/url-handlers/tel/enabled true
Some of the lighter weight managers look like they allow you to create fake mime types and register them as URI Protocol handlers.
"Fake mime-types are created for URIs with various scheme like this:
application/x-xdg-protocol-
Applications supporting specific URI protocol can add the fake mime-type to their MimeType key in their desktop entry files. So it's easy to find out all applications installed on the system supporting a URI scheme by looking in mimeinfo.cache file. Again defaults.list file can be used to specify a default program for speficied URI type." wiki.lxde.org
KDE also supports their own method of handling URL Protocol Handlers:
Create a file: $KDEDIR/share/services/your.protocol and populate it with relevant data:
[Protocol]
exec=/path/to/player "%u"
protocol=lastfm
input=none
output=none
helper=true
listing=
reading=false
writing=false
makedir=false
deleting=false
from last.fm forums of all places
Hope that helps.
Here's how I did on Mac OS with an application NW.js :
Open the app /Applications/Utilities/Script Editor
type the following code in the editor
on open location this_URL
do shell script "/Applications/X.app/Contents/MacOS/x '" & this_URL & "'"
end open location
Replace X by the name of your App.
Save the script as an Application Bundle anywhere
Go to the script, right click then 'Show Package Contents' then edit Contents/info.plist
Add these lines at the end of the file, just before </dict></plist> :
<key>CFBundleIdentifier</key>
<string>com.mycompany.AppleScript.AppName</string> <!-- edit here -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>AppName</string> <!-- edit here -->
<key>CFBundleURLSchemes</key>
<array>
<string>myurlscheme</string> <!-- your url scheme here -->
</array>
</dict>
</array>
You can now open a link starting with myurlscheme: and see your app is opening!
Edit :
Looks like the module has changed the registration process for good:
const path = require('path');
const ProtocolRegistry = require('protocol-registry');
console.log('Registering...');
// Registers the Protocol
ProtocolRegistry.register({
protocol: 'testproto', // sets protocol for your command , testproto://**
command: `node ${path.join(__dirname, './tester.js')} $_URL_`, // this will be executed with a extra argument %url from which it was initiated
override: true, // Use this with caution as it will destroy all previous Registrations on this protocol
terminal: true, // Use this to run your command inside a terminal
script: false
}).then(async () => {
console.log('Successfully registered');
});
Original Answer :
There is an npm module for this purpose.
link :https://www.npmjs.com/package/protocol-registry
So to do this in nodejs you just need to run the code below:
First Install it
npm i protocol-registry
Then use the code below to register you entry file.
const path = require('path');
const ProtocolRegistry = require('protocol-registry');
console.log('Registering...');
// Registers the Protocol
ProtocolRegistry.register({
protocol: 'testproto', // set your app for testproto://**
command: `node ${path.join(__dirname, './index.js')}`, // this will be executed with a extra argument %url from which it was initiated
}).then(async () => {
console.log('Successfully registered');
});
Then suppose someone opens testproto://test
then a new terminal will be launched executing :
node yourapp/index.js testproto://test

Categories