最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I make a local HTML page auto-refresh on file change? - Stack Overflow

programmeradmin3浏览0评论

I view local HTML files in my default browser via the file:// protocol.

I would like to add some code/script to the HTML file, so that on change of the file (and ideally on change of the sucked-in CSS files) the browser refreshes the page.

I tried including Live.js via

<script type="text/javascript" src=".js"></script>

but it does not seem to have any effect for files accessed via file://. - Any solution known which works here?

PS 1: I found another question relating to this problem, but it does not address the local file case.

PS 2: I know I can reload the page periodically via

<meta http-equiv="refresh" content="1">

but that is not what I need; I need reload on change.

I view local HTML files in my default browser via the file:// protocol.

I would like to add some code/script to the HTML file, so that on change of the file (and ideally on change of the sucked-in CSS files) the browser refreshes the page.

I tried including Live.js via

<script type="text/javascript" src="http://livejs.com/live.js"></script>

but it does not seem to have any effect for files accessed via file://. - Any solution known which works here?

PS 1: I found another question relating to this problem, but it does not address the local file case.

PS 2: I know I can reload the page periodically via

<meta http-equiv="refresh" content="1">

but that is not what I need; I need reload on change.

Share Improve this question edited Feb 21, 2018 at 5:18 halloleo asked Feb 19, 2018 at 2:20 halloleohalloleo 10.4k17 gold badges78 silver badges150 bronze badges 13
  • What happens if you just download live.js and link to your local copy instead of to livejs.com/live.js? I would try that first. – Mark Commented Feb 19, 2018 at 2:29
  • What editor are you using? – Jacob Commented Feb 19, 2018 at 2:30
  • @Mark Good idea, but doesn't work. (I've just tried it.) – halloleo Commented Feb 19, 2018 at 2:35
  • @Jacob Emacs. I am certain the file gets written to disk (with the new timestamp). When I issue a manual reload in the browser, the changes come through. – halloleo Commented Feb 19, 2018 at 2:37
  • Live.js doesn't support local files. Check your console output. – Herohtar Commented Feb 19, 2018 at 2:39
 |  Show 8 more comments

4 Answers 4

Reset to default 5

A More General Solution

Javascript alone does not seem to be able to solve this problem. Until browsers add back in the support they used to have for doing this, I don't think there's a perfectly general solution.

While I think my previous Emacs solution is a good one, for people who use text editors that do not have builtin web servers, here's another answer which is a bit broader.

Use inotifywait

Many OSes can setup a program to execute whenever a file is modified without having to poll. There is no one API for all OSes, but Linux's inotify works better than most and is easy to use.

Here is a shell script which, when run in the directory where your HTML and CSS files are, will tell Firefox to reload whenever changes are saved. You could also call it with specific filenames if you want it to only watch a few files.

#!/bin/bash
# htmlreload
# When an HTML or CSS file changes, reload any visible browser windows.
# Usage:
# 
#     htmlreload [ --browsername ] [ files ... ]
#
# If no files to watch are specified, all files (recursively) in the
# current working directory are monitored. (Note: this can take a long
# time to initially setup if you have a lot of files).
#
# An argument that begins with a dash is the browser to control.
# `htmlreload --chrom` will match both Chromium and Chrome.

set -o errexit
set -o nounset

browser="firefox"      # Default browser name. (Technically "X11 Class")
keystroke="CTRL+F5"    # The key that tells the browser to reload.

sendkey() {
    # Given an application name and a keystroke,
    # type the key in all windows owned by that application.
    xdotool search --all --onlyvisible --class "$1" \
        key --window %@ "$2"
}

# You may specify the browser name after one or more dashes (e.g., --chromium)
if [[ "${1:-}" == -* ]]; then
    browser="${1##*-}"
    shift
fi

# If no filenames given to watch, watch current working directory.
if [[ $# -eq 0 ]]; then
    echo "Watching all files under `pwd`"
    set - --recursive "`pwd`" #Added quotes for whitespace in path
fi

inotifywait --monitor --event CLOSE_WRITE "$@" | while read; do
    #echo "$REPLY"
    sendkey $browser $keystroke
done

Prerequisites: inotifywait and xdotool

You'll need inotifywait and xdotool installed for this to work. On Debian GNU/Linux (and descendants, such as Ubuntu and Mint) you can get those programs using a single command:

sudo apt install inotify-tools xdotool

Optional: Working with Chromium

I suggest using Firefox due to a strangeness in the way Chromium (and Chrome) handle input in windows that do not have focus. If you absolutely must use Chromium, you can use this sendkey() routine instead:

sendkeywithfocus() {
    # Given an application name and a keystroke, give each window
    # focus and type the key in all windows owned by that application.

    # This is apparently needed by chromium, but is annoying because
    # whatever you're typing in your text editor shortly after saving
    # will also go to the chromium window. 

    # Save previous window id so we can restore focus.
    local current_focus="$(xdotool getwindowfocus)"

    # For each visible window, focus it and send the keystroke.
    xdotool search --all --onlyvisible --class "$1" \
        windowfocus \
        key --window %@ "$2"

    # Restore previous focus.
    xdotool windowfocus "$current_focus" 
}

Optional: Working in Wayland

I have not tested it out, but read that Wayland now has a program called ydotool which is a drop in replacement for xdotool.

Emacs Impatient Mode

In one of the comments, the questioner mentioned that they use the Emacs text editor. Emacs has a simple solution for live updating HTML (and CSS) as you type: Impatient Mode.

It uses an Emacs web server to serve a page with Javascript that shows live updates on each keystroke.

Installation

If you have setup MELPA, Impatient Mode can be easily installed with

M-x package-install

Alternately, if you prefer to install by hand, see my instructions below.

Using impatient-mode

There are just three steps:

  1. Run once:

     M-x httpd-start
    
  2. Run in any HTML or CSS buffer you're editing:

     M-x impatient-mode
    
  3. Open your browser to http://localhost:8080/imp and click on the name of the buffer.

Now, just type in Emacs and watch the magic happen!

Usage Side Note

I've submitted a patch to the maintainer of Impatient Mode that automatically starts the web server and opens up the proper URL in your browser when you run M-x impatient-mode. Hopefully that will be accepted and you'll only need one step to do everything. I will edit this answer if that occurs.


Optional: Installing by hand

The following is not necessary, but some people would prefer to not add MELPA to their Emacs package repository list. If that is the case, you can install Impatient Mode like so:

cd ~/.emacs.d
mkdir lisp
cd lisp
git clone https://github.com/skeeto/impatient-mode
git clone https://github.com/skeeto/simple-httpd
git clone https://github.com/hniksic/emacs-htmlize/

Now edit your .emacs file so it adds subdirs of ~/.emacs.d/lisp/ to the load-path:

;; Add subdirectories of my lisp directory. 
(let ((default-directory  "~/.emacs.d/lisp"))
     (normal-top-level-add-subdirs-to-load-path))
(autoload 'impatient-mode "~/.emacs.d/lisp/impatient-mode/impatient-mode" "\
Serves the buffer live over HTTP.

\(fn &optional ARG)" t nil)

That should be enough for Impatient Mode to work, but if you'd like it to be slightly faster, you can byte-compile the emacs lisp files.

Browsers restrict access to the file:/// protocol for security reasons. In Firefox, even extensions no longer have access to local files, so you will most likely have to serve the files locally in order to use a live reload script. If you do that you could just use Live.js, but something like this might be slightly simpler to set up. (Requires Node.js)

The lightweight web browser Gnome-Web (aka epiphany), automatically updates when a local HTML file is modified.

# Either containerized for security:
sudo snap install epiphany
# or traditional, lightweight install directly into your host:
sudo apt install epiphany

# Then launch the browser on your html using file:// protocol
epiphany my-guide.html

...and any modifications to 'my-guide.html' will be displayed automatically.

Another alternative on Linux is 'falkon', which I guess is the KDE equivalent lightweight browser.

发布评论

评论列表(0)

  1. 暂无评论