Code Monkey home page Code Monkey logo

stefon's Introduction

Stefon

Stefon is an asset pipeline for Clojure, closely modelled after Ruby's Sprockets. It is a rewrite of dieter.

Stefon is fast, easy to use, and easy to extend. It uses idiomatic clojure, and is written to support both development use (ie it is very fast), and production use (it precompiles for deployment to a CDN). Stefon's major selling points are speed, its ease of use in production and development, and its ability to support multiple languages and compressors.

Usage

Stefon is an asset pipeline. In production, it is used to precompile assets to be served by a CDN or via Ring's file-wrap middleware. In develepment mode, it serves files directly, recompiling them on changes.

Installation

Add stefon as a dependency in project.clj

:dependencies [[circleci/stefon "0.5.0-SNAPSHOT"]]
:plugins [[lein-stefon-precompile "0.5.0"]]
:jvm-opts ["-Djna.library.path=target/native/macosx/x86_64:target/native/linux/x86_64:target/native/linux/x86"]

Insert it into your ring middleware stack

(-> app
    (stefon/asset-pipeline config-options))

Or if you use noir

(server/add-middleware stefon/asset-pipeline config-options)

Supported passes in the pipeline

  • Minifying JS using the Google Closure compiler (*.closure.js - coming soon)
  • Minifying CSS using by removing whitespace (coming soon)
  • Replacing asset references (calls to data-uri, etc) with the relevant information about the asset (*.ref)

.stefon files

Concatenation of assets is handled by a Stefon manifest file. A manifest is a file whose name ends in .stefon and whose contents are a clojure vector of file names / directories to concatenate.

For example, a file named assets/javascripts/app.js.stefon with the following contents:

[
  "./base.js"
  "framework.js"
  "./lib/"
  "./models/"
]

Stefon would look for base.js in the same directory, and then concatenate each file from the lib and models directories. It concatenated all files in order. Directory contents are concatenated in alphabetical order.

.less files

Less files have one caveat at present: they read their imports directly from file system, without going through stefon. That means that you can't use .less.ref files. As a workaround, make your root file a .ref.less file, and do the assetifying after less compilation has finished.

.ref files

To refer to other assets from your asset, use a .ref file. This allows you to write functions that reference other assets, such as data-uri and asset-path. If you're familiar with sprockets, this is similar to how you might use a .erb file.

There are some sharp edges here, at the moment. In particular, there is no dependency tracking, and caching compiled assets is very naive. This means if you refer to asset A from asset B, and then change A, B won't actually change unless you restart your program.

Linkage

In order to include links to your assets you may use the link-to-asset function.

(link-to-asset "stylesheets/reset.css" config-options)
(link-to-asset "javascripts/app.js.stefon" config-options)

Precompilation

To use precompilation, we need to actually precompile files:

lein stefon-precompile

and then load the precompiled files

(defn init []
  (stefon/init stefon-options))

Configuration Options

The following configuration options are available.

;; Searched for assets in the order listed. Must have a directory called 'assets'.
:asset-roots ["resources"]

;; The root for compiled assets, which are written to (serving-root)/assets. In dev mode defaults to "/tmp/stefon")
:serving-root "public"

;; Set to :production to serve precompiled files, or when running `lein stefon-precompile`
:mode :development

;; Where the result of the precompile should be stored. Might be good to keep it out of the web root.
:manifest-file "manifest.json"

;; When precompiling, the list of files to precompile. Can take regexes (coming soon), which will attempt to match all files in the asset roots.
:precompiles ["./assets/myfile.js.stefon"]

Note you need to pass your config options to asset-pipeline as well as link-to-asset.

Contributing

It is easy to add new preprocessors to stefon. Most asset types uses the default library for that language, hooked up to stefon using V8. See the source for easy-to-follow examples.

License

Distributed under the Eclipse Public License, the same as Clojure.

Authors

Mostly written by Paul Biggar from CircleCI. Based on a fork of dieter by John Andrews from EdgeCase. With contributions by many others.

Changelog

Version 0.5.0 (first release of stefon)

  • Almost complete rewrite, with many backward incompatible changes
  • forked to circleci/stefon
  • No longer supports Rhino
  • production mode always loads from disk - there is no option to compile lazily
  • dev mode mirrors production mode exactly
  • the timestamp thing is gone
  • Many settings removed, we're down to :asset-roots, :serving-root, :mode, manifest-file and :precompiles
  • The pipeline is now truly a pipeline, supporting more than one transformation per file
  • Add data-uri support
  • drop support for lein1, lein2 only
  • use proper tmp dirs

planned before release

  • allow options to be passed to each compiler
  • support different versions of each language
  • add image compression
  • add more compressors
  • add more languages, esp markdown
  • cdn support (port from circleci)

Version 0.4.0 (released as dieter)

  • Remove support for searching for filenames, because it has very sharp edges
  • Throw a FileNotFoundException instead of failing silently when files in a manifest aren't found
  • Directory contents are listed in alphabetical order (avoids intermittent failures due to file directory order on Linux)
  • Rewritten internals, with more reliable and consistent string and filename handling
  • Referring to assets using different extensions is no longer supported

Version 0.3.0 (released as dieter)

  • Use v8 for Less, Hamlcoffee and CoffeeScript
  • Cache and avoid recompiling CoffeeScript and HamlCoffee files which haven't changed
  • Update to lein2
  • Improve stack traces upon failure in Rhino
  • Update Coffeescript (1.3.3), Less (1.3.0) and Hamlcoffee (1.2.0) versions
  • Ignore transient files from vim and emacs
  • Better error reporting of HamlCoffee
  • Support multiple asset directories
  • Add expire-never headers
  • Improve Rhino speed by using one engine per thread
  • Update to latest Rhino for better performance
  • Support for lein stefon-precompile
  • Add mime type headers for stefon files

Version 0.2.0 (released as dieter)

  • Handlebars templates are now a separate library. dieter-ember

stefon's People

Contributors

pbiggar avatar ivanstojic avatar dwwoelfel avatar gordonsyme avatar ryanmcg avatar danthiffault avatar anaisbetts avatar sridatta avatar bostonaholic avatar notnoop avatar jxa avatar arohner avatar cbui avatar cgmartin avatar circleci-bot avatar bitemyapp avatar dlowe avatar notnoopci avatar bear avatar tobiasbayer avatar

Stargazers

vemv avatar  avatar swlkr avatar Petter Eriksson avatar Forrest avatar Josh Kingsley avatar Mohammad Sadegh Khoeini avatar Darong Mean avatar Daniel Janus avatar Xiyang Chen avatar Michael Wong avatar Ryan Kee avatar Johnny Eradus avatar Zak Kristjanson avatar Josh Mize avatar Andrew Carr avatar  avatar Alan Moore avatar dqd avatar Christoffer Sawicki avatar Johanna Larsson avatar André Ligné avatar Eduard Bondarenko avatar Sumeet Singh avatar CP Clermont avatar Mike Haney avatar Alexey Dorofeev avatar Tom Hickey avatar Jim Myers avatar Roma Chi avatar Adrian Rosian avatar Dominic LoBue avatar Paul Lam avatar Isaac Cambron avatar Gert Goet avatar  avatar Ju avatar Eunpyoung Kim avatar Fyodor avatar Matt Dean avatar Petrus Theron avatar Michel Rasschaert avatar Thomas Crowley avatar Adam Stokes avatar Tomáš Bílek avatar Andrew Meredith avatar Michael Rubanov avatar Max Weber avatar James Conroy-Finn avatar Azizur Rahman avatar Brandon Bloom avatar  avatar Aaron Abrams avatar Jean-Hadrien Chabran avatar Matthew Moore avatar Bo Jeanes avatar HM. Yen avatar humanitiesNerd avatar Joshua Griffith avatar Ilshad Khabibullin avatar Tony Seing avatar Trevor Hartman avatar  avatar Baptiste Fontaine avatar Brandon Leonardo avatar James Peterson avatar Koji Yusa avatar Scott Walkinshaw avatar Owain Lewis avatar Jason Bennett avatar sitch avatar Kurt Ruppel avatar h h avatar kilroySoft avatar  avatar Robbie Vanbrabant avatar  avatar Kofi avatar Ticean Bennett avatar Adam Bozanich avatar Josh Chaney avatar Vesa Vänskä avatar lorthos avatar Ted McFadden avatar Alexandr Kurilin avatar Denis Fuenzalida avatar John Anderson avatar Joel Boehland avatar Aaron Miller avatar Don Jackson avatar Dmitri Sotnikov avatar Gordon Stratton avatar  avatar Dave Della Costa avatar Daniel Ribeiro avatar  avatar Lyle Hanson avatar Jared Lobberecht avatar

Watchers

Travis Vachon avatar  avatar Petra Jaros avatar Christopher Miles avatar Caitlyn O'Hanna avatar Mark Fowler avatar Jon Levin avatar Robert Zuber avatar Emile Snyder avatar Patrick Shields avatar  avatar JR Richardson avatar Paul Robinson avatar  avatar Eric Haberkorn avatar Darong Mean avatar Marty Berryman avatar Marc O'Morain avatar  avatar Le Wang avatar Fernando Mouco avatar Kevin Imber avatar Charles Francoise avatar Dot Dotter (they/them) avatar hamlet avatar Chad Chabot avatar James Cloos avatar Shaun Kaasten avatar Nathan Sorenson avatar Romain Sylvian avatar Liene Vērzemnieks avatar Justin Cowperthwaite avatar Taka avatar Kevin Bell avatar Tay Frost avatar Stella Lok avatar Elliot Forbes avatar Atul S avatar David Goeke avatar Miller Peterson avatar  avatar Alex Engelberg avatar  avatar Fernando Martin avatar Zain avatar Fernando Abreu avatar Ryan William O'Hara avatar Eugene C avatar Henry avatar Andrés Cuervo avatar  avatar Cormac O'Riordan avatar Luke Meyers avatar Andrew Welton avatar Marla Zeschin avatar Jessica Woo avatar Ahmed ElNahas avatar Dorothy Jane Wingrove avatar Olivier avatar Spencer Franks avatar Rick Burta avatar Miro Prasil avatar  avatar Daniel Beere avatar An Nguyen avatar Jason Souza avatar Stefi  avatar Patrick Lonergan avatar Kyle Asano avatar Tito Villalobos avatar Shavant Thomas avatar Chris Johnson avatar  avatar George Livas avatar Rafael Torres avatar Christopher Black avatar Anshul Uchil avatar Hannah Henderson avatar Sam Johnson avatar  avatar Emily Woods avatar  avatar Mark Li avatar

stefon's Issues

Namespace 'v8.core' not found

I included dependencies in my project. When I try to reference [stefon.core :as stefon], I get this exception:

Failed trying to require myapp.handler with: java.lang.Exception: namespace 'v8.core' not found

How do I fix this? Do I add a separate dependency for clj-v8?

Problems Finding JNA Library

I'm using a copy of Stefon that I checked out from the master branch. It builds and installs without issue. It works great from within my REPL environment (Cider) or when launched with a REPL via lein (lein repl). However, when I bundle my application as an uberjar, I'm seeing the following error at the top of my stacktrace:

Exception in thread "main" java.lang.UnsatisfiedLinkError: 
  Unable to load library '/usr/java/packages/lib/amd64/libv8.so.clj-v8': 
    /usr/java/packages/lib/amd64/libv8.so.clj-v8: 
      cannot open shared object file: No such file or directory

This seems especially odd since I don't have that path ("/usr/java/packages") on my system. I'm invoking my application with the following incantation:

java -Djna.library.path=target/native/linux/x86_64 \
-jar target/scrumboard-0.0.1-SNAPSHOT-standalone.jar

When I comment out my uses of Stefon and set my application to simply write the value of the "jna.library.path" System property, it does show the value I passed in. I've also tried suppling the absolute path to the library, that doesn't work either. I'm using the "x86_64" path since I'm on a 64bit OS (Ubuntu).

I did find the issue where this is being worked on and it looks like the issue was resolved. Indeed, the fact that it works from "lein repl" and from Cider implies that this is an issue that can be resolved. I'm wondering if maybe I'm doing something very obviously wrong.

My end goal is to deploy this application as a WAR via Tomcat. This is currently the way we deploy all of our Java applications, the goal is to get our Clojure apps to deploy in the same manner.

Any help you can provide will be greatly appreciated! Thank you!

Support a shut down operation

It makes it more convenient to tear everything down and put it back, as in the stuart sierra workflow post or jig.

CPU spins on CoffeeScript error

If I make a CoffeeScript syntax error, my running Compojure application maxes out CPU and spins. Exception is thrown, but the only fix seems to be to end the running Java application. Is this a problem in V8/node, or a loop somewhere in stefon?

Installation instructions are missing a step

On ubuntu 12.04, just referencing the plugin and lib as in the readme gives you the following:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library '/usr/java/packages/lib/amd64/libv8.so.clj-v8': /usr/java/packages/lib/amd64/libv8.so.clj-v8: cannot open shared object file: No such file or directory

Stable version outlook (0.5.0)

Any idea when a stable version of stefon will be released?

Not sure if this is the best way to ask the question but I figured it'd work.

Booststrap LESS source compile throws V8 Error

Including standard Bootstrap LESS source files with bootstrap.less as a starting point, the following error is thrown by link-to-asset:

V8 error: ERROR:null:null:-1: 
undefined
TYPE: Syntax
INDEX: undefined
EXTRACT: ,,@import "variables.less";

Here is how I am including it in my view layout function:

(include-css (link-to-asset "bootstrap/less/bootstrap.less" {}))

This seems to be caused by @import. Is this supported by the LESS pipeline?

Support prefixed asset paths for sites not at domain root

I'm using stefon for a github pages project. As you probably know. Github pages are hosted at USERNAME.github.io/PROJECTNAME/. link-to-assets always starts with /assets/ so to make this work the assets need to be hosted at the root site and cannot be in the sub-directory where they belong.

Is there an easy way to do this that i am missing? Otherwise, I'll try to submit a PR for this.

Static link-to-asset with with hash in query parameter

I want to use Stefon to serve up publicly linked to, compiled CoffeeScript files. However, this requires a static URL e.g. /resources/my-script.js?v=1234. Would it take to let (link-to-asset ...) output a static file path with the hash in the query parameter instead of in the file name?

Update depencies for clj-time "0.6.0"?

Ring needs clj-time "0.6.0" while stefon depends on 0.4.4 and thats brake ring. Fix is to specify 0.6.0 depency explicit. May be it's time to update stefon so it's depends on newer version?

Maybe asking for something wrong, pardon then, just started with clojure stuff.

Null Pointer Exception when aot compiling

I'm trying to compile an uberjar for my web application and I'm getting this error:

lein compile
Compiling stefon-compile.core
WARNING: name already refers to: #'clojure.core/name in namespace: stefon.asset, being replaced by: #'stefon.asset/name
Exception in thread "main" java.lang.NullPointerException, compiling:(core.clj:1:1)

Here's a repo that reproduces it:

https://github.com/Christopher-Bui/stefon-compile

Steps to reproduce:

  1. Create a new project.
  2. Add [circleci/stefon "0.5.0-SNAPSHOT"] to dependencies.
  3. Add :aot :all to project.clj
  4. Add (:require [stefon.core :as stefon]) in a namespace.
  5. lein compile

Supposedly the problem is due to the the conflicting names as an answer on SO says: http://stackoverflow.com/a/11534475/90537.

But I've looked in stefon.asset and practically everywhere and I can't find anything that defines name.

Precompile issue

Hello there, was integrating stefon in my project and got this strange error on running precompile:

java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.CharSequence
at clojure.string$split.invoke(string.clj:222)
at leiningen.stefon_precompile$split_ns.invoke(stefon_precompile.clj:9)
at leiningen.stefon_precompile$stefon_precompile.invoke(stefon_precompile.clj:16)
at clojure.lang.Var.invoke(Var.java:415)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.core$apply.invoke(core.clj:619)
at leiningen.core.main$resolve_task$fn__3029.doInvoke(main.clj:189)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.lang.AFunction$1.doInvoke(AFunction.java:29)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at leiningen.core.main$apply_task.invoke(main.clj:230)
at leiningen.core.main$resolve_and_apply.invoke(main.clj:234)
at leiningen.core.main$_main$fn__3092.invoke(main.clj:303)
at leiningen.core.main$_main.doInvoke(main.clj:290)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:415)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.core$apply.invoke(core.clj:617)
at clojure.main$main_opt.invoke(main.clj:335)
at clojure.main$main.doInvoke(main.clj:440)
at clojure.lang.RestFn.invoke(RestFn.java:436)
at clojure.lang.Var.invoke(Var.java:423)
at clojure.lang.AFn.applyToHelper(AFn.java:167)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)

My settings are as follows:

:stefon-options {
:mode :production
:asset-roots ["resources"]
:serving-root "resources/public/assets"
:manifest-file "resources/manifest.json"
:precompiles ["resources/assets/app.js.stefon"]
}

Tried solving the problem myself by looking at the code, I am seeing a str/split on an namespace on a return on (:stefon-options project). Since I have no experience with lein and their plugin structure I could not figure it out. Maybe I am just doing something wrong. Help would be appreciated! :-)

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.