So my purpose is to build a tiny site with Flask, and want to use Sass for style sheet.
What I could found from (the first page of) google mostly goes to flask-scss packages. But this package is still in a version number of 0.5
, which looks like still under development, and have been updated for 7 years (last commit in 2015). Some of them uses flask-assets, but still not looks like a stable solution.
Fortunately, libsass-python now having official support on this: Using with Flask.
So this article is for the experience on integrating libsass into flask. I'm writing this article based on Flask 2.0.2
and libsass 0.21.0
.
Building Sass on request
libsass-python
natively comes with the package sassutils
. And I'm having a folder with following layout:
Folder layout
|- static
| |- sass
| |- main.scss
|- app.py
Sample app
Now add SassMiddleware the wsgi middleware to the site app:
import flask
import sassutils.wsgi
app = flask.Flask(__name__)
app.wsgi_app = sassutils.wsgi.SassMiddleware(
app.wsgi_app,
{
"app": {
"sass_path": "static/sass",
"css_path": "static/css",
"wsgi_path": "style",
"strip_extension": True,
}
},
)
Note it's using a strange layout to clearify the behavior. It comes with some pitfall, would be addressed below.
On official doc, it suggests a simpler format for manifest. But that one raises FutureWarning. So adding strip_extension
to address this.
Mainfest
Here's the detail on each parameters in mainfest:
sass_path
Path for the folder that contains source Sass/SCSS filesThis is the only required parameter.
css_path
Path to store the generated outputWe don't need to create it first. During request, libsass compile the code from
sass_path
than put it tocss_path
. So we could see the output appears atstatic/css/main.css
after any request.If we do not specific it, that the data would be saved to
sass_path
. I do not want to mix generated data with source code, so strongly recommand to use it.wsgi_path
Overriding prefix to get compiled data on routingBy specificing this, we would be avaliable to get the compiled stylesheet with
/style/main.css
.If we do not specific it, it uses
css_path
. Then we should get it from/static/css/main.css
.strip_extension
Remove original file extension or notWhen set to
False
(default value), libsass only append.css
to original file name. Somain.scss
now becomemain.scss.css
.And if we enabling this, they would remove the extension, so we could get
main.css
.
On using this config, it generates data to static/css
and we could reach the output via:
curl http://localhost:5000/style/main.css
Template
A simple way could be directly specific the path:
<link href="/style/main.css" rel="stylesheet" type="text/css">
But be careful, it is not suggested to use SassMiddleware
for production. You should compile it into static files and serving it with other server.
So using url_for might be better. But:
<link href="{{ url_for('static', filename='/style/main.css') }}" rel="stylesheet" type="text/css">
# above template code generates
<link href="/static/style/main.css" rel="stylesheet" type="text/css">
Flask prepends static/
prefix to the filename. So it is not feasible to use the provided config. We could solve this by removing wsgi_path
parameters, or set it to a string with static/
prefix.
(Building for deployment)
Not trying yet. Not sure if I remember to fill this in the futrue.