如何使本地HTML页面在文件更改时自动刷新?

12

我通过 file:// 协议在我的默认浏览器中查看本地HTML文件。

我想向HTML文件中添加一些代码/脚本,以便在文件更改时(最好是当引入的CSS文件更改时)浏览器可以刷新页面。

我尝试使用Live.js进行包含。

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

但是对于通过file://访问的文件似乎没有任何影响。 - 有没有已知的解决方案适用于此处?

附注1:我找到了另一个与此问题相关的问题,但它并未涉及本地文件的情况。

附注2:我知道我可以通过定期重新加载页面来进行更新

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

但那不是我需要的,我需要在更改时重新加载。


@Mark 好主意,但不起作用。(我刚试过了。) - halloleo
Live.js 不支持本地文件。请检查您的控制台输出。 - Herohtar
Brackets io 可以在刷新时更新预览。 - Jacob
@Jacob 谢谢,但我不想改变编辑器 - 只是添加一个页面刷新。浏览器的扩展程序可以在更改时进行刷新。 - halloleo
@Mark 我的意思是“本地”指的是来自file:///协议的文件。如果你将它们在localhost或其他地方本地服务,那应该没问题。 - Herohtar
显示剩余8条评论
4个回答

5

一个更通用的解决方案

仅使用Javascript似乎无法解决这个问题。在浏览器重新添加以前支持此功能之前,我认为没有完美的通用解决方案。

虽然我认为我之前的Emacs解决方案很好,但是对于那些没有内置Web服务器的文本编辑器用户,这里有另一个更广泛的答案。

使用inotifywait

许多操作系统可以设置程序在文件修改时执行,而无需轮询。并非所有操作系统都有一种API,但Linux的inotify比大多数OSes都要好,并且易于使用。

以下是一个Shell脚本,在您的HTML和CSS文件所在的目录中运行时,将告诉Firefox在保存更改时重新加载。如果您只想监视几个文件,则还可以使用特定的文件名调用它。

#!/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

先决条件:inotifywait 和 xdotool

为了使这个操作生效,你需要安装 inotifywaitxdotool。在 Debian GNU/Linux(以及其派生版,如 Ubuntu 和 Mint)中,你可以使用一个命令获取这些程序:

sudo apt install inotify-tools xdotool

可选:使用Chromium

由于Chromium(和Chrome)在没有焦点的窗口中处理输入的方式很奇怪,我建议使用Firefox。如果您非常需要使用Chromium,可以使用此sendkey()例程代替:

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" 
}

可选项:在Wayland下工作

我没有进行过测试,但是读到现在Wayland有一个叫做ydotool的程序,它可以代替xdotool


Chrome在Mac上使用osascript有一个更好的替代xdotool:https://dev59.com/questions/oG035IYBdhLWcg3wKsqa#39625090 - user202729

4

Emacs Impatient Mode

在评论中,提问者提到他们使用 Emacs 文本编辑器。Emacs 有一个简单的解决方案,可以在输入时实时更新 HTML(和 CSS):Impatient Mode

它使用 Emacs Web 服务器来提供一个带有 JavaScript 的页面,以显示每次按键的实时更新。

安装

如果您已经设置了 MELPA,则可以轻松安装 Impatient Mode:

M-x package-install

如果您喜欢手动安装,请参阅下面的说明。

使用impatient-mode

只需要三个步骤:

  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.

现在,只需在Emacs中键入并观看神奇的事情发生!
使用须知
我已经向Impatient Mode的维护者提交了一个补丁,当您运行M-x impatient-mode时,它会自动启动Web服务器并在浏览器中打开正确的URL。希望这将被接受,这样您只需要一步即可完成所有操作。如果发生这种情况,我将编辑此答案。

可选:手动安装

以下步骤并非必需,但是有些人可能不希望将MELPA添加到他们的Emacs包存储库列表中。如果是这种情况,您可以按照以下方式安装Impatient Mode:

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/

现在编辑你的.emacs文件,使其将~/.emacs.d/lisp/子目录添加到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)

这应该足够让“不耐烦模式”正常运行,但如果您想让它更快一些,可以将Emacs Lisp文件进行字节编译。


1
我的问题意思更广泛一些,但是在使用Emacs时这是一个超级酷的解决方案,谢谢。 :-) - halloleo

2
浏览器出于安全考虑限制了对file:///协议的访问。在Firefox中,即使是扩展程序也无法访问本地文件,因此您很可能需要在本地提供文件以使用实时重新加载脚本。如果您这样做,可以直接使用Live.js,但类似这个的工具可能更容易设置。(需要Node.js)

有道理,然而 Jacob 提到的 flymd 包似乎可以实现这一点。我刚刚简单地测试了一下:它有一个 HTML 主文件,通过 JavaScript 读取并渲染 Markdown 文件。它确实能够从本地的 Markdown 文件获取最新更改,并且主文件被作为 file:///path/to/flymd.html 在浏览器中打开。 - halloleo
那个能满足你的需求吗?它似乎只处理Markdown渲染,而不是完整的HTML/CSS。 - Herohtar
不,它不能做我想要的(因为源文件是Markdown文件,而不是HTML)。但它向我展示了浏览器(通过JavaScript)以某种方式可以查看文件系统... - halloleo
如果您查看浏览器兼容性,它们指出Chrome不允许文件访问(需要使用解决方法)。虽然Firefox被标记为可用,但该信息最后更新于2016年,可能不适用于当前的浏览器。 - Herohtar

2
轻量级的网络浏览器Gnome-Web(又名Epiphany)会在本地HTML文件被修改时自动更新。
# 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

......对'my-guide.html'文件的任何修改都将自动显示。

在Linux上,另一个选择是'falkon',我猜它是KDE等效的轻量级浏览器。


1
很有趣!不幸的是,我在macOS上,我猜epiphany不能运行。 - halloleo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接