Skip to content

Instantly share code, notes, and snippets.

@freiguy1
Created March 20, 2015 04:00
Show Gist options
  • Save freiguy1/1f7e9606288561a51cc9 to your computer and use it in GitHub Desktop.
Save freiguy1/1f7e9606288561a51cc9 to your computer and use it in GitHub Desktop.
Using grunt to compile runtime assets in Play Framework app
...
playRunHooks <+= baseDirectory.map(base => Grunt())
...

This description works for a Play 2.2.x application.

At the root of the project exists package.json. It describes that you want to install grunt-cli, grunt-contrib-sass, and grunt-contrib-watch. You need to make sure you run npm install to pick up these packages. You'll probably need to install grunt-cli globally.

/gruntfile.js describes what you want grunt to watch. This is my least favorite part, since I have to designate where I'd like the compiled files to go. Seems a bit brittle.

In /project/Grunt.scala exists the hook which starts and stops grunt when you run the application.

A line needs to be added in build.sbt to let play know about the run hook.

Then you can initiate play run command and it should auto-compile on scss change.

For deployment, I have play installed on my server and initiate play start. If this is your case, then you just need to remember to run grunt sass beforehand.

import sbt._
import Keys._
import java.net._
import java.io.File
import play.PlayRunHook
/*
Grunt runner should be in project directory to be picked up by sbt
*/
object Grunt {
def apply(): PlayRunHook = {
object GruntProcess extends PlayRunHook {
var process: Option[Process] = None
override def beforeStarted(): Unit = {
}
override def afterStarted(addr: InetSocketAddress): Unit = {
Process("grunt sass").run
process = Some(Process("grunt watch").run)
}
override def afterStopped(): Unit = {
process.map(p => p.destroy())
process = None
}
}
GruntProcess
}
}
module.exports = function(grunt) {
grunt.initConfig({
sass: {
options: {
update: false
},
dist: {
files: [{
expand: true,
cwd: 'app/assets',
src: ['**/*.scss'],
dest: 'target/scala-2.10/classes/public/',
ext: '.css'
}]
}
},
watch: {
sass: {
files: ['app/assets/**/*.scss'],
tasks: ['sass']
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
}
{
"name": "app-name",
"version": "1.0.0",
"description": "",
"repository": {
"type": "git",
"url": ""
},
"dependencies": {
"grunt-cli": "^0.1.13",
"grunt-contrib-sass": "^0.9.2",
"grunt-contrib-watch": "^0.6.1"
}
}
@iphilgood
Copy link

I just wanna thank you! 🎉 Everything seems to work so well so far except the part with the compiled CSS files. First of all I want to get rid of the whole play-sass plugin. Now I got my application running on production server and the app is working fine which I first prepare locally with the stage task.

You wrote that the specific destination path target/scala-2.10/classes/public/ is a bit brittle. Let me show you how I develop locally

  1. I've got Play running with activator
  2. Grunt watches my SASS files and compiles them lovely
  3. After reloading the page I see my changes (so far so good)
  4. When I reach a deployable state I run $ grunt sass and this compiles it to the brittle directory
  5. I run $ activator stage to prepare the whole package which I'll deploy on my production environment
  6. After reloading my production page I have no access to the main.css file and see the plain HTML

Do you have an idea, why? Probably it's a thing with the asset pipeline of Play but I'm sure there's a way to serve static CSS files. Do you know how? In addition to this I'd like to minify my CSS files for production but this is an easy thing with Grunt. 😉

Let me know if you have a clue and one more time, thank you so much for this gist 👍

@freiguy1
Copy link
Author

I'm sorry I didn't see this response until now! With $ activator stage, I'm sure those css assets aren't being copied to the output package. I'm not sure how to do this. I've not had this problem since I have activator installed/running right on my server, at the moment, and $ activator run $ activator start uses the brittle directory.

Edit: updated the strikethrough part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment