Deploying A Flask App With NPM Modules On Heroku - Codeburst
Deploying A Flask App With NPM Modules On Heroku - Codeburst
Follow
Richard So Follow
Introduction
Let’s say you are making a website with a Flask backend and suddenly you
find that it’s necessary to use a JavaScript package/module for your project.
Maybe you’re doing this to give your website a bit more interaction, or
you’re working with a module that’s not available as a CDN. That leaves you
with the option of using the Node Package Manager (NPM). Normally, you
would cast npm init on the root directory of your web development project
and install your wanted modules with npm install <package> , if it weren’t
If you tried doing so, you’ll ultimately fail with unresolvable JavaScript
errors, or the HTML not linking properly with your NPM module. Jokes
aside, the pressing question still remains: how might one go about this?
This article aims to answer this quandry.
Important Note: This short tutorial assumes that you’re familar with Flask,
NPM, and Heroku, and already have a Flask app deployed on Heroku.
The Trick
If you’re familiar with Flask, you should know that a bare-bones directory
structure for a (very) simple web app should look something like this:
/<your_flask_proj_directory>/
├── app.py (or __init__.py)
├── requirements.txt
├── venv (python_environment)
│ └── ...
├── static
│ ├── css
│ │ └── styles.css
│ └── img
│ ├── img1.jpg
│ └── img2.png
└── templates
├── layout.html
├── index.html
└── about.html
The key to this dilemma is to use your /static folder. It’s simple: run npm
init on your static folder and install your NPM modules on that directory.
Why? Remember, the static folder is used to store files that are literally static
(non-changing), unlike the HTML templates — hence the name “static”. CSS
files, images, and more importantly, JavaScript code fit this criteria for a
Flask app. On the other hand, files from outside the static folder won’t work
properly if you try to link them with the <script> tag in your HTML templates.
Your node_modules should appear inside your static folder. At that point,
you are able to link an NPM module into your HTML templates using a
<script> tag. For instance, if I was trying to use swup.js to add snazzy page
transitions to my site, I’ll link that module to my layout HTML like this:
We use the url_for() function to create the path without needing to worry
about trying to get the right relative path. Now you can use your NPM
modules in your app and see them working in your local server!
Oh, Heroku!
You might be thinking “It works in my setup so surely it’ll work once I
deploy it onto Heroku!” This is a naive train of thought, but I’ll admit I
thought the same not long ago. At this state, your installed NPM modules
on static will NOT work out of the box when deploying on Heroku.
What’s worse is that Node.js or NPM is not installed if you try running with
your Procfile. That’s because the original Buildpack you were using on
Heroku prepares only the bare minimum of what you need to deploy your
app; the Python buildpack won’t waste storage space trying to install
Node.js, and vice versa. What we need is two buildpacks for this Heroku
project: Node.js and Python (both officially supported in this order
listed).
Assuming that you already have the Python buildpack, run the command
on the root directory of your project below:
This adds the Node.js buildpack in front of the Python counterpart when
building the app. This is to make sure all our NPM module assets are
installed and good to go before setting up the Flask server and running it.
If you do not have the Heroku CLI, you are able to configure in your Heroku
settings page for your project/app.
There’s one little problem left that we have to take care of: the Node.js
buildpack only searches for package.json at the root level of the project
directory, meaning it won’t actually install the modules in the static
folder. A simple fix is to create another package.json file at the root of your
project with a postinstall entry that points to script and runs npm
"scripts": {
"postinstall": "cd static && npm install"
},
Conclusion
This problem bugged me not so long ago when I had to maintain an
organization website with a Flask backend. Both myself and the
organization thought of using page transitions with swup.js to make for a
better user experience. However, swup with the plugins I needed only came
as NPM modules (so CDNs are out of the picture). This article is a
culmination of my findings for tackling a pretty niche use case scenario but
I hope this was helpful — or at least interesting — for those of you reading
this article.
70 2
WRITTEN BY
Richard So Follow
codeburst Follow
Firestore on Node in Build a Power 3D Robot Control with Why Should You Use a
Production. Part 1: Animation with React Amazon Lex React Component Library
Repositories Gapur Kassym in JavaScript in Gene Foxwell
for your Project?
Dominic Bartl Plain English Timur Catakli
Form Validations in Reusable form-inputs in You don't need a library Moleculer start with
Angular 8 React. Simple and for Skeletons!!! typescript
Sai Kiran
flexible! Jamal RahimZadegan Alexandre E Souza in jslovers
Henrik Haugberg in Techtive