Home Articles Categories Series
Pythonise Just now

Minifying static assets and compiling SCSS to CSS with Python

Using the sass, rcssmin and rjsmin Python packages to optimize web assets, including Bootstrap


Article Posted on by in Python
Julian Nash · 7 months ago in Python

I wanted a way to minify JS and CSS files, along with compile SCSS to CSS, without messing around with NPM or YARN.

Also, I didn't want to bake it into the application, rather just a simple script that can be ran from the command line.

libsass

Python scss to css compiler:

pip install libsass

rcssmin

Python CSS minifier:

pip install rcssmin

rjsmin

Python JavaScript minifier:

pip install rjsmin

Example app structure

Most of the Bootstrap scss files have been omitted for illustration.

base
├── app
│   ├── __init__.py
│   ├── static
│   │   ├── css
│   │   │   ├── style.css
│   │   │   ├── style.css.map
│   │   │   └── style.min.css
│   │   ├── js
│   │   │   ├── app.js
│   │   │   ├── app.min.js
│   │   └── scss
│   │       ├── bootstrap
│   │       │   ├── bootstrap.scss
│   │       │   ├── mixins
│   │       │   │   ├── _alert.scss
│   │       │   ├── utilities
│   │       │   │   ├── _align.scss
│   │       │   └── vendor
│   │       │       └── _rfs.scss
│   │       ├── custom
│   │       │   └── custom.scss
│   │       └── style.scss
│   ├── templates
│   │   └── index.html
│   └── views.py
├── run.py
└── runner.py
  • All scss imports are declared in style.scss

Example usage with Flask

A simple script that compiles and minifies the files:

runner.py

import rcssmin
import rjsmin
import sass

"""
This script does 3 things:
    - Compiles scss to css
    - Minifies css
    - Minifies JavaScript
"""

# Map scss source files to css destination files
sass_map = {"app/static/scss/style.scss": "app/static/css/style.css"}

# Map un-minified css source files to minified css destination files
css_map = {"app/static/css/style.css": "app/static/css/style.min.css"}

# Map un-minified JavaScript source files to minified JavaScript destination files
js_map = {"app/static/js/app.js": "app/static/js/app.min.js"}


def compile_sass_to_css(sass_map):

    print("Compiling scss to css:")

    for source, dest in sass_map.items():
        with open(dest, "w") as outfile:
            outfile.write(sass.compile(filename=source))
        print(f"{source} compiled to {dest}")


def minify_css(css_map):

    print("Minifying css files:")

    for source, dest in css_map.items():
        with open(source, "r") as infile:
            with open(dest, "w") as outfile:
                outfile.write(rcssmin.cssmin(infile.read()))
        print(f"{source} minified to {dest}")


def minify_javascript(js_map):

    print("Minifying JavaScript files:")

    for source, dest in js_map.items():
        with open(source, "r") as infile:
            with open(dest, "w") as outfile:
                outfile.write(rjsmin.jsmin(infile.read()))
        print(f"{source} minified to {dest}")


if __name__ == "__main__":
    print()
    print("Starting runner")
    print("--------------------")
    compile_sass_to_css(sass_map)
    print("--------------------")
    minify_css(css_map)
    print("--------------------")
    minify_javascript(js_map)
    print("--------------------")
    print("Done")
    print()

Running this file from the base directory:

python runner.py

Output

Expected output:

Starting runner
--------------------
Compiling scss to css:
app/static/scss/style.scss compiled to app/static/css/style.css
--------------------
Minifying css files:
app/static/css/style.css minified to app/static/css/style.min.css
--------------------
Minifying JavaScript files:
app/static/js/app.js minified to app/static/js/app.min.js
--------------------
Done

HTML

Using the CSS & JS in an HTML/Jinja template:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <link rel="stylesheet" href="{{ url_for('static', filename='css/style.min.css') }}">

  <title>Hello, world!</title>
</head>

<body>

  <div class="container mt-3">
    <div class="row">
      <div class="col">
        <h5>Hello world</h5>
        <div class="card">
          <div class="card-body">
            <h5>Card</h5>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script src="{{ url_for('static', filename='js/jquery/jquery-3.4.0.min.js') }}"></script>
  <script src="{{ url_for('static', filename='js/popper/popper-1.15.0.min.js') }}"></script>
  <script src="{{ url_for('static', filename='js/bootstrap/bootstrap.min.js') }}"></script>
  <script src="{{ url_for('static', filename='js/app.min.js') }}"></script>
</body>

</html>

Resources:

Last modified · 18 Apr 2019
Did you find this article useful?
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License
Contents
Loading...