Django Pipeline, Heroku, and SASS
Asked Answered
S

4

12

I've been trying to get django-pipeline setup so that I can compile and concat my assets. I would also like to remove the compiled css files from my repository to avoid merge conflicts in pull requests.

I've been trying to get django-pipeline to compile the files as part of the deploy process but can't figure this out. I use SASS to write my CSS. My pipeline settings look like this:

STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'

PIPELINE_CSS = {
    'main': {
        'source_filenames': (
            'sass/blah.scss',
            'sass/main.scss',
        ),
        'output_filename': 'css/main.css',
        'extra_context': {
            'media': 'screen',
        },
    },
}

PIPELINE_COMPILERS = (
  'pipeline.compilers.sass.SASSCompiler',
)

This works great locally, and generates .css files in my /sass folder, which are then combined to make the main.css file. If I check those CSS files into my git repository and push to Heroku, it also works fine. However, if I ignore them, which I would like to do so that I'm not committing compiled files, then django-pipeline can't find the files to combine. I'm not sure how I can get the sass compilation working on Heroku and I can't find anything about it.

I can provide more information about my setup if needed, hopefully somebody knows something about this!

Slovene answered 23/12, 2013 at 23:10 Comment(0)
S
9

OK, here's how I got this working using Compass to compile my SASS files.

  • Use multiple Heroku buildpacks - Heroku Buildpack Multi
  • Put the following in your .buildpacks file

    https://github.com/heroku/heroku-buildpack-ruby.git
    https://github.com/heroku/heroku-buildpack-nodejs
    https://github.com/heroku/heroku-buildpack-python.git
    
  • Create a Gemfile with compass and any other requirements you have. Here's mine:

    source 'https://rubygems.org'
    
    ruby '1.9.3'
    
    gem 'bootstrap-sass'
    gem 'compass'
    
  • Create a config.rb file. Here's mine. As you can see it, requires the bootstrap-sass that I included in my Gemfile:

    # Require any additional compass plugins here.
    require 'bootstrap-sass'
    
    # Set this to the root of your project when deployed:
    http_path = "/"
    css_dir = "app_folder/static/css"
    sass_dir = "app_folder/static/sass"
    images_dir = "app_folder/static/images"
    
    output_style = :compact
    

    more details on config.rb can be found here

  • Install node packages (django-pipeline wants yuglify). You'll need a package.json file:

    {
      "dependencies": {
        "yuglify": "0.1.4"
      },
      "engines": {
        "node": "0.10.x",
        "npm": "1.3.x"
      },
      "repository": {
        "type": "git",
        "url": "your repo url"
      }
    }
    
  • almost ready...
  • when Heroku runs the ruby buildpack, it will look for a rake task called assets:precompile. So now you'll need to add a Rakefile with the following:

    namespace 'assets' do
      desc 'Updates the stylesheets generated by Sass/Compass'
      task :precompile do
        print %x(compass compile --time)
      end
    end
    

    this will put compile your stylesheets. You need to make sure you set the output (back in config.rb) to the place that django-pipeline is looking for CSS files (shown in the original question).

  • You should get rid of this part in the original question as django-pipeline isn't compiling your SASS for you:

    PIPELINE_COMPILERS = (
      'pipeline.compilers.sass.SASSCompiler',
    )
    
  • That should be it! Deploys should just work now, and it didn't really add a significant amount of time to my deploy process.

All in all, it amounts to a lot of setup, but for me it was well worth it as I no longer have to commit compiled files into the repository, which was causing a lot of merge conflicts when working with branches and pull requests.

I would like to figure out how to do this using only two buildpacks (obviously only one would be ideal but I don't know if it's possible). The problem is trying to find binary paths so that pipeline can do it's thing when it doesn't find the defaults. I'm not sure if the reason I can't do this is because of how Heroku is installing things, or because there is a bug in django-pipeline, but right now this is good enough for me.

If you try this and it doesn't work for you, let me know, if I missed something I'm happy to make updates.

Slovene answered 31/1, 2014 at 0:12 Comment(2)
I found this response while trying to get django-compressor to compile Zurb Foundation scss on Heroku and got it to work using this as a guideline! In my case, since no node.js packages are needed, it's possible to only pull in ruby and python in the multi-buildpack. Gemfile only needs to have sass in it, and then no rake or config.rb is required. Heroku will build the sass gem and then a django-compressor precompiler statement like ('text/x-scss', 'sass --scss {infile} {outfile}'), will work. Thanks for the helpful directions on doing this in pipeline!Karren
I had to add the Gemfile.lock as wellHexagon
M
6

I don't want to take away from your excellent solution, but I tried this today and found a few differences that made things simpler for me - likely due to updates in django-pipeline and/or Heroku. My full solution is below, in case anyone else comes looking.

Add the 3 buildpacks to Heroku:

heroku buildpacks:set https://github.com/heroku/heroku-buildpack-ruby.git
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-nodejs
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-python.git

Add django-pipeline and django-pipeline-compass to requirements.txt:

django-pipeline==1.5.2
django-pipeline-compass==0.1.5

Create a Gemfile to install Sass:

source 'https://rubygems.org'
ruby '2.1.5'
gem 'bootstrap-sass'

Create a package.json file to install Yuglify:

{
  "dependencies": {
    "yuglify": "0.1.4"
  },
  "engines": {
    "node": "0.10.x",
    "npm": "1.4.x"
  }
}

I did not need a Rakefile or config.rb.

For reference, here are relevant settings from my settings.py:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '_generated_media')
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    'pipeline.finders.PipelineFinder',
)

PIPELINE_COMPILERS = (
    'pipeline_compass.compiler.CompassCompiler',
)

PIPELINE_YUGLIFY_BINARY = os.path.join(BASE_DIR, 'node_modules', '.bin', 'yuglify')

And I also had to add this entry to urls.py:

url(r'^static/(?P<path>.*)$', serve, kwargs={'document_root': settings.STATIC_ROOT})

Hope it helps someone!

Matthiew answered 15/7, 2015 at 1:27 Comment(1)
Thanks it did, I only needed the sass executable, so adding a Gemfile, Gemfile.lock and the ruby build pack let me get django-static-precompiler up and running on heroku.Jeannettejeannie
D
0

You may need to set PIPELINE_SASS_BINARY so that django-pipeline can find your SASS compiler.

Durgy answered 24/12, 2013 at 4:20 Comment(3)
This is probably part of the solution. Part of the problem though is still installing a sass compiler on Heroku and figuring out the path to it.Slovene
I found a solution using multiple buildpacks so you can install the sass gem with the ruby buildpack and then the pipeline compiler will pick up it's location automatically. I'll update with a full response a bit later.Slovene
I came back to link this myself... Might as well include the link to heroku-buildpack-multi since I have it on my clipboard.Durgy
T
0

You can use the libsass compiler for django-pipeline that uses Sass packaged as a Python package:

pip install libsasscompiler

Update your config:

PIPELINE['COMPILERS'] = (
  'libsasscompiler.LibSassCompiler',
)

The default Yuglify compressor is also a problem on Heroku, which you can temporarily overcome by disabling it. This is my config for enabling Sass on Django for example:

PIPELINE = {
    'COMPILERS': (
        'libsasscompiler.LibSassCompiler',
    ),
    'STYLESHEETS': {
        'main': {
            'source_filenames': (
              'styles/main.scss',
            ),
            'output_filename': 'css/main.css'
        },
    },
    # disable the default Yuglify compressor not available on Heroku
    'CSS_COMPRESSOR': 'pipeline.compressors.NoopCompressor',
    'JS_COMPRESSOR': 'pipeline.compressors.NoopCompressor'
}

The longer-term solution would be to move towards a JS-only build toolchain (as most projects are doing). Rails integrates pretty nicely with Webpack for example and is maintained by the same team. Until that happens in Django (if ever) and trickles into the Heroku Python builpack, you can use Heroku's multiple buildpacks and add an official Node buildpack step that runs npm install; npm run build for you.

Tjaden answered 2/11, 2018 at 16:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.