How to use SCSS/SASS in your Django project (NPM Way)

Last updated on Jul 29 2019 by Michael Yin

Introduction

This is #2 of my Django SASS/SCSS Tutorial Series. In this blog post, I will talk about how to use SCSS/SASS in your Django project with NPM.

After reading this article, you will get:

  1. How to write SCSS/SASS using NPM for your Django project

  2. How to deploy Django project which uses NPM as front-end solution

NOTE: You can find the source code in wagtail-react-blog , I would appreciate that if you could give this repo a star.

Prerequisite

First, please make sure you have installed Node in your dev env.

I recommend you to use nvm to do this job and you can find more details on NVM Github

Step 1: Directory structure and workflow

Below is our directory structure and the basic workflow:

./static_src
        ↓
  $ ./node_modules/node-sass/bin/node-sass
        ↓
./static_compiled
        ↓
  $ ./manage.py collectstatic
        ↓
./static_root

The static_src includes all front-end stuff(JS, CSS, etc) of our project. We can use node-sass (gulp, grunt, webpack also ok) to compile the files in static_src and put the build files in static_compiled

Then we can let our Django dev server to find static files from static_compiled. Code below should be added to our settings.py

STATICFILES_DIRS = [
    os.path.join(PROJECT_DIR, 'static_compiled'),
    ]

The final ./manage.py collectstatic would copied and compress files from static_compiled and other django package static files into the static_root directory.

Step 2: Install NPM dependencies

Please make sure you are in static_src directory, and then keep reading

First, please run npm init to create package.json

Then, please install node-sass package using npm, node-sass is a tool which can help us combine SCSS to CSS

npm install node-sass
npm install bootstrap

And then create directory sass as child of static_src

Here we put a sample main.scss to the sass directory, it has code below.

@import 'node_modules/bootstrap/scss/bootstrap';

As you can see in the main.scss, we import bootstrap, we can also add custom variables to customize our Bootstrap theme as we like.

Now our goal is to combine main.scss to main.css, then in Django template, we can only import main.css to make the theme work as expected.

Step 3: Setup NPM command

In package.json, there is a property called scripts, we can add commands to this property, and then call it using npm run

"scripts": {
  "compile:css": "node-sass -o ../static_compiled/css sass"
}

As you can see, we add a command compile:css to compile the sass to ../static_compiled/css

Now you can run npm run compile:css to check the result

> node-sass -o ../static_compiled/css sass

Rendering Complete, saving .css file...

Congratulations, you just compiled the SCSS/SASS using node-sass package.

Step 4: SCSS/SASS Auto Compile feature

It is annoying if we need to run the command above each time after we edit our SCSS files. So we need to find a way to monitor SCSS files and auto compile after they are modified.

"scripts": {
  "compile:css": "node-sass -o ../static_compiled/css sass",
  "compile:css:watch": "node-sass -o ../static_compiled/css sass --watch"
}

You can npm run compile:css:watch in a terminal (recommend Tmux here) and edit SCSS/SASS in your editor, after you change the file, new CSS files would be generated, which is convenient

Step 5: How to check code style of your SCSS/SASS

Node ecosystem is like Python ecosystem, we can always find some tool to help us solve specific problem.

Here we use sass-lint to help us to do lint job. If you also want to know how to lint Python code, please check How to make your Wagtail/Django project have good Python coding style

# first, please install sass-lint package
npm install sass-lint

# Then add commands to your package.json
"scripts": {
  "compile:css": "node-sass -o ../static_compiled/css sass",
  "compile:css:watch": "node-sass -o ../static_compiled/css sass --watch",
  "lint:css": "sass-lint sass/** -v -q"
}

We can add some sample SCSS code to the main.scss file and the run npm command to lint the SCSS.

> sass-lint sass/** -v -q


sass/main.scss
   6:16  warning  Selectors must be placed on new lines                   single-line-per-selector
   7:13  warning  @extend must be used with a %placeholder                placeholder-in-extend
   8:13  warning  @extend must be used with a %placeholder                placeholder-in-extend
  14:3   warning  Type-selector should be nested within its parent Class  force-element-nesting
  15:13  warning  @extend must be used with a %placeholder                placeholder-in-extend

✖ 5 problems (0 errors, 5 warnings)

You can also create some custom rule for sass-lint, please check sass-lint official doc for more detail.

Step 6: NPM config

If you check above scripts section, you will find a problem. We need to replace many times if we want to rename static_compiled.

npm config is like variable in programming, which can help us solve this problem.

"config": {
    "src_css": "sass",
    "dest_css": "../static_compiled/css",
},
"scripts": {
  "compile:css": "node-sass -o $npm_package_config_dest_css $npm_package_config_src_css",
}

You can use npm_package_config_{name} in the scripts.

Step 7: How to deploy it using Docker

Now there are many platforms which support Django deployment very well. However, they have different deployment config files and syntax.

So I'd like to suggest you to use Docker to deploy your project because it is easy to make it work across different platforms. Once you get it working on one platform, it is easy for you to migrate to another one.

What is more, Dockerfile can let you do custom jobs as you like during the deployment.

# Build Django app which use NPM as front-end solution
# Michael Yin <[email protected]>

FROM python:3.6-stretch

WORKDIR /app

ENV PYTHONUNBUFFERED=1 \
    PYTHONPATH=/app \
    DJANGO_SETTINGS_MODULE=config.settings.production \
    PORT=8000 \
    WEB_CONCURRENCY=3 \
    GUNICORN_CMD_ARGS="--max-requests 1200 --access-logfile -"

EXPOSE 8000

# Install operating system dependencies.
RUN apt-get update -y && \
    apt-get install -y apt-transport-https rsync gettext libgettextpo-dev && \
    curl -sL https://deb.nodesource.com/setup_8.x | bash - &&\
    apt-get install -y nodejs &&\
    rm -rf /var/lib/apt/lists/*

# Install Gunicorn.
RUN pip install "gunicorn>=19.8,<19.9"

WORKDIR wagtail_react_blog/static_src

# Install front-end dependencies.
COPY ./wagtail_react_blog/static_src/package.json ./wagtail_react_blog/static_src/package-lock.json ./
RUN npm install

# Install Python requirements.
COPY requirements.txt .
RUN pip install -r requirements.txt

# Compile static files
COPY ./wagtail_react_blog/static_src/ ./
RUN npm run build:prod

WORKDIR /app

# Copy application code.
COPY . .

# Install assets
RUN python manage.py collectstatic --noinput --clear

# Run application
CMD ["sh", "config/docker_start.sh"]

In docker_start.sh, you can add custom scripts as you like.

# Migrate database
python manage.py migrate

# run server
gunicorn config.wsgi:application

You can only change the wagtail_react_blog to make it work in your project.

Some Tips

Below are some tip which can help you.

  1. Note, both the static_compiled and static_root directories should be excluded from Git (e.g. through .gitignore) and only the static_src directory should be added in Git repo.

  2. If you use docker to deploy project, it is recommended to use whitenoise to serve static assets and AWS S3 to serve media files.

  3. If you do not like Docker, you can also use Fabric to help you deploy.

Pros and Cons of NPM solution

I already wrote a post talking about how to do this using pure Python way How to use SCSS/SASS in your Django project (Python Way)

The npm solution is a little more complex than the python way, however, it can benefit with the Node ecosystem so it is more powerful and flexible.

So if you already have SCSS/SASS theme code and just want to make it work with Django, you can use the python way.

If you want to write SCSS/SASS a lot and also need to write more js code, please use the npm way.

Conclusion

In this blog post, I talked about how to write SCSS/SASS using NPM in your Django project.

NOTE: You can find source code in wagtail-react-blog, I would appreciate that if you could give this repo a star.

What should you go next?

  1. You can find more useful NPM commands in above project, just check how it works and feel free to use it in your project.

  2. You can try to deploy the project to Heroku (which support docker deployment and also have a free plan)

As you know, NPM can do a lot of stuff so in this post I did not talk about js part, I plan to do it in another series.

If you still have problem, please feel free to contact us.

Michael is a passionate Python developer from China and love writing code, articles about Django and Wagtail CMS.

Michael Yin

Full Stack Developer

Need any Help in your Project?

Sign up to our newsletter