Manage frontend dependencies in Python web projects with FrontMan
Tags: python, web, javascript, css
Published: 2021-02-08 12:09:27

---
title: Manage frontend dependencies in Python web projects with FrontMan
published: true
description: Manage Javascript and CSS dependencies for you Python projects without having to install npm by using .
tags: python, web, javascript, css
//cover_image: https://direct_url_to_image.jpg
---

Web applications always need some Javascript and CSS to look good and make user experience better (JQuery and Bootstrap, for instance), but managing all the libraries we need can be a source of trouble, specially when executing CI/CD pipelines.

Using npm to declare and retrieve frontend dependencies is a solution, but it is a bit too much if we are not building single page application with Angular or Vuejs, and besides that, it adds one significant dependency that in some cases could be avoided.

Because of that, and inspired by [AspNet LibMan](https://docs.microsoft.com/en-us/aspnet/core/client-side/libman), I built [FrontMan](https://github.com/livioribeiro/frontman), a dependency manager written in Python for frontend dependencies that fetches files from CDNs (cdnjs, jsdelivr and unpkg).

You can install FrontMan by running `pip install frontman` (`pipenv install --dev frontman` for [Pipenv](https://docs.pipenv.org/) and `poetry add --dev frontman` for [Poetry](https://python-poetry.org/))

Usage is simple, create a manifest (frontman.json) and execute `frontman install`.

The manifest is a json file like the following:

```json
{
  "provider": "jsdelivr",
  "destination": "assets",
  "packages": [
    {
      "name": "jquery",
      "version": "3.5.1",
      "provider": "cdnjs",
      "destination": "jquery",
      "files": [
        "jquery.min.js"
      ]
    },
    {
      "name": "@popperjs/core",
      "version": "2.6.0",
      "path": "dist/umd",
      "files": [
        {
          "name": "popper.min.js",
          "rename": "popper.js",
          "destination":"popper"
        }
      ]
    },
    {
      "name": "bootstrap",
      "version": "4.6.0",
      "path": "dist",
      "destination": "bootstrap",
      "files": [
        "js/bootstrap.min.js",
        "css/bootstrap.min.css"
      ]
    }
  ]
}
```

The output will be like:

```
OK   https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js -> assets/jquery/jquery.min.js
OK   https://cdn.jsdelivr.net/npm/@popperjs/core@2.6.0/dist/umd/popper.min.js -> assets/popper/popper.js
OK   https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js -> assets/bootstrap/js/bootstrap.min.js
OK   https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css -> assets/bootstrap/css/bootstrap.min.css
```

After runnig `frontman install` there will be a file structure like this:

```
assets
├── bootstrap
│   ├── css
│   │   └── bootstrap.min.css
│   └── js
│       └── bootstrap.min.js
├── jquery
│   └── jquery.min.js
└── popper
    └── popper.js
```

Running the install command again will give the following output:

```
SKIP https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js -> assets/jquery/jquery.min.js
SKIP https://cdn.jsdelivr.net/npm/@popperjs/core@2.6.0/dist/umd/popper.min.js -> assets/popper/popper.js
SKIP https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js -> assets/bootstrap/js/bootstrap.min.js
SKIP https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css -> assets/bootstrap/css/bootstrap.min.css
```

If a file is already downloaded, FrontMan will not download it again, unless you pass the `--force` flag.

I hope you like FrontMan and find it useful.