Giter Site home page Giter Site logo

Auto-reloading of templates about enlive HOT 30 CLOSED

cgrand avatar cgrand commented on August 11, 2024
Auto-reloading of templates

from enlive.

Comments (30)

djpowell avatar djpowell commented on August 11, 2024 1

Ok - well reload is working fine for me on Windows, at least if I execute the following code to monkey-patch enlive's broken url-to-path conversion:

(require 'net.cgrand.reload)

(defmethod watch-url "file" [^java.net.URL url ns]
  (let [fs (java.nio.file.FileSystems/getDefault)
        path (.getPath fs (.getAbsolutePath (java.io.File. (.toURI url))) no-strings)
        ws (watch-service ns)]
    (ws path)))

Additionally in my startup namespace, which doesn't contain any deftemplate/defsnippet code, I execute:

(net.cgrand.reload/auto-reload (find-ns 'com.example.namespace1))

for each namespace with templates.

Alternatively, you could automate that with something like:

(doseq [n (->> (loaded-libs)
                 (filter #(.startsWith (name %) "com.example.mytemplates."))
                 (map find-ns)
                 (filter #(:net.cgrand.reload/deps (meta %))))]
    (net.cgrand.reload/auto-reload n))

This works for me with [enlive "1.1.5"]

from enlive.

ctran avatar ctran commented on August 11, 2024

Is this already possible but not documented somewhere?

from enlive.

cgrand avatar cgrand commented on August 11, 2024

Usually one achieve auto-reloading through http://mmcgrana.github.com/ring/middleware.reload-api.html

from enlive.

djpowell avatar djpowell commented on August 11, 2024

Ring's middleware.reload was recently changed so that namespaces are only reloaded if their source files or dependencies change, so now templates don't automatically get reloaded by middleware.reload.

I'm not sure how best to handle this? Perhaps there is some way that enlive could expose the set of files and namespace mappings so that an enlive reloader middleware could reload the namespaces if any of the related templates change?

from enlive.

ptaoussanis avatar ptaoussanis commented on August 11, 2024

Any developments on this? djpowell is correct in pointing out that the Ring reload middleware doesn't solve the issue.

To clarify, if mytemplates.clj defines some Enlive templates using html resource files foo.html and bar.html and ring-reload-modified is loaded:

Changes to mytemplates.clj will trigger a reload of mytemplates.clj.
Changes to foo.html or bar.html will not trigger a reload of mytemplates.clj.

This isn't a major issue, but it'd be nice if we could figure out a way of handing dependency reloading automatically.

Christophe, any thoughts on David's experiment? https://gist.github.com/1396481

from enlive.

sritchie avatar sritchie commented on August 11, 2024

Hey guys, what was the resolution for this ticket? I'm very interested in the case where editing and saving an HTML template file will trigger a reload. I'd be happy to try another approach to this and submit a pull request, if the above weren't suitable for some reason.

Thanks!
Sam

from enlive.

sritchie avatar sritchie commented on August 11, 2024

Ping

from enlive.

tjtuom avatar tjtuom commented on August 11, 2024

Since there is no official solution for this I solved it using guard. Basically I just use the guard-shell (https://github.com/guard/guard-shell) plugin to monitor my template files and if they change I use touch to update the correspoding clojure file. Works like a charm for my use case.

My guard file:

guard 'shell' do
  watch(%r{^resources/public/templates/(.*)/(.*)\.html$}) {|m| `touch src/workoutbook/templates/#{m[1]}.clj` }
end

from enlive.

sparkertime avatar sparkertime commented on August 11, 2024

Configurable auto-reloading of templates would indeed be awesome. In the meantime, I've used the relatively simple fix of creating a custom middleware for my projects based on the old "brute-force" version of ring.middleware.reload prior to this commit: mmcgrana/ring@f39e24d#ring-devel/src/ring/middleware/reload.clj

from enlive.

ifesdjeen avatar ifesdjeen commented on August 11, 2024

Reloading everything is quite an expensive operation.

So far the best solution I could come up with is similar to guard one. I only use https://github.com/ibdknox/watchtower instead of guard. I watch resources directory, and as we have dirs structured in a similar way to the enlive template namespaces, it's basically a require :reload call.

from enlive.

philc avatar philc commented on August 11, 2024

How does the auto reload functionality work? I've added (net.cgrand.reload/auto-reload *ns*) at the bottom of the file which defines my templates & snippets, but changing them does not result in the changes being picked up. I have java 7.

Also, if java 7 is required for this, it's worth documenting in the readme.

from enlive.

lminaudier avatar lminaudier commented on August 11, 2024

Same here. I don't really understand how auto reload actually works. Can you explain how ?

from enlive.

eunomie avatar eunomie commented on August 11, 2024

See touchme: a leiningen plugin to touch clj files when html are modified.

from enlive.

philc avatar philc commented on August 11, 2024

Touching files isn't ideal, because it can confuse your editor (triggering a prompt to revert to the file on disk, for instance). I've been using this approach in my projects. It leverages watchtower.

(defn- handle-template-file-change [files]
  (require 'my-project.handler :reload))

(defn init []
  ; Reload this namespace and its templates when one of the templates changes.
  (when-not (= (System/getenv "RING_ENV") "production")
    (watcher/watcher ["resources"]
                     (watcher/rate 50) ; poll every 50ms
                     (watcher/file-filter (watcher/extensions :html))
                     (watcher/on-change handle-template-file-change)))

This init function is called by Ring on startup. See Ring's :init setting for project.clj.

from enlive.

xpe avatar xpe commented on August 11, 2024

@cgrand Given your recent changes, what is the proper way to setup reloading?

Is this a correct way to explain it? "Put this line in every Clojure file that uses deftemplate or defsnippet?"

(net.cgrand.reload/auto-reload *ns*)

If so, perhaps a few clarifying words in the README would help?

from enlive.

eunomie avatar eunomie commented on August 11, 2024

@philc
Right. But I prefer having this type of feature outside my code. And a lein plugin is good for that. I don't really like having my reloading code inside init method (or other), this is just a development helper, not my software's code.

from enlive.

cgrand avatar cgrand commented on August 11, 2024

@xpe auto-reloading is, to me, first and foremost a dev-time feature so I wouldn't put

(net.cgrand.reload/auto-reload *ns*)

in my main source files. Rather in a bunck of helper files I source in the repl.

from enlive.

magnars avatar magnars commented on August 11, 2024

Adding

(net.cgrand.reload/auto-reload *ns*)

to my Clojure file that uses deftemplate doesn't seem to help much.

I occationally get Reloading what-the-emacsd.core in the terminal process running the app, but it seems to have nothing to do with when I touch a template file - and it doesn't update the defined template.

Am I using it wrong?

from enlive.

jcromartie avatar jcromartie commented on August 11, 2024

Yeah, this does not do what it says on the tin. It should be removed from the README in order to cut down on confusion. Don't pretend to have features you don't!

from enlive.

iwinux avatar iwinux commented on August 11, 2024

Any update on this?

from enlive.

djpowell avatar djpowell commented on August 11, 2024

Are you running Windows? I had to use this patch to get things running on
Windows:
#106

Then I also only got it to work by putting the calls to auto-reload
external to the namespace that I was trying to make reload.

On Wed, Jul 2, 2014 at 5:55 PM, Limbo Peng [email protected] wrote:

Any update on this?


Reply to this email directly or view it on GitHub
#6 (comment).

from enlive.

iwinux avatar iwinux commented on August 11, 2024

@djpowell It's on Linux. Where should (net.cgrand.reload/auto-reload *ns*) be placed?

from enlive.

djpowell avatar djpowell commented on August 11, 2024

I have a app.core namespace that starts up ring etc, and then the various
bits of the app have there own namespaces with code + deftemplates. I had
think I had some problems when I put auto-reload together with the
deftemplates, but it worked fine when I put it in app.core.

In fact, I put a loop in, to find all namespaces in (loaded-libs) and
called auto-reload on everything in my packages that
had :net.cgrand.reload/deps defined. Bit of a hack, but it saves me
listing each one.

On Thu, Jul 3, 2014 at 5:05 PM, Limbo Peng [email protected] wrote:

@djpowell https://github.com/djpowell It's on Linux. Where should (net.cgrand.reload/auto-reload
ns) be placed?


Reply to this email directly or view it on GitHub
#6 (comment).

from enlive.

iwinux avatar iwinux commented on August 11, 2024

@djpowell thx :) I'd try it later

from enlive.

iwinux avatar iwinux commented on August 11, 2024

@djpowell Still not working.

Here's my setup:

  1. dev server is started via lein ring server-headless
  2. I've put the line (net.cgrand.reload/auto-reload *ns*) inside views.clj (in which the template is defined)

Expected: modify the HTML file, refresh browser, and see modification in effect.

Actually got: refreshed and nothing happened. But if I touch views.clj (which triggers reloading done bylein-ring) and refresh, the modification is applied.

from enlive.

CmdrDats avatar CmdrDats commented on August 11, 2024

Hey guys,

Just my 2c, this might be considered a slightly grotesque approach - but in my project, I simply introduced my own deftemplate and defsnippet macro's that add the namespace and the resource file to a watchlist, then simply polled for changes and fired off an ns reload based on the changes..

Code below, hope this helps someone..

(ns server.web.enlive
  (:use [server.util])
  (:require [net.cgrand.enlive-html :as en]
            [clojure.java.io :as io]))

(defonce template-list (atom {}))

(defn last-modified [source]
  (-> (clojure.lang.RT/baseLoader) (.getResource source) (clojure.lang.RT/lastModified source)))

(defn update-source-time [source]
  (swap! template-list assoc-in [source :time] (last-modified source)))

(defn register-template [source namespace]
  (swap! template-list update-in [source :ns] assoc namespace true)
  (update-source-time source))

(defmacro defsnippet [nm source selector args & forms]
  `(do
     (register-template ~source ~*ns*)
     (en/defsnippet ~nm ~source ~selector ~args ~@forms)))

(defmacro deftemplate [nm source args & forms]
  `(do
     (register-template ~source ~*ns*)
     (en/deftemplate ~nm ~source ~args ~@forms)))

(defn get-changes [tlist]
  (for [source (keys tlist)
        :let [entry (get tlist source)
              time (:time entry)
              newtime (last-modified source)]
        :when (< time newtime)]
    (assoc entry :source source)))

(defn reload-changed []
  (doseq [{:keys [source ns]} (get-changes @template-list)]
    (info source " changed")
    (update-source-time source)
    (doseq [n (keys ns)]
      (require (ns-name n) :reload))))

from enlive.

CmdrDats avatar CmdrDats commented on August 11, 2024

I guess the problem here is that "auto-reloading templates" has two sides - auto-reloading the Clojure source when the Clojure source changes and auto-reloading the Clojure source when the HTML source files changes. The (net.cgrand.reload/auto-reload ns) achieves the former and my code snippet earlier achieves the latter.

from enlive.

djpowell avatar djpowell commented on August 11, 2024

Ah that is true. I just embed an nrepl that gets turned on in a development environment, and use that to reload code changes.

from enlive.

kolov avatar kolov commented on August 11, 2024

On my Macbook detecting a file change with the watch service used by net.cgrand.reload takes up to 8 seconds, so I came up with alternative polling solution (ring middleware), see https://github.com/kolov/enlive-reload. I've used it extensively on Mac OS Yosemite, no experience whatsoever on other platforms.

from enlive.

fdserr avatar fdserr commented on August 11, 2024

Reload fixed in 1.1.6.
8 sec reload on Mac not experienced, rather in the order of 1 sec.
Closing for now, thankies!

from enlive.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.