Switch to offline compressed assets

This commit is contained in:
Gabriel Augendre 2021-01-05 17:59:58 +01:00
parent 3c64795f7a
commit 0fc99c2a0c
No known key found for this signature in database
GPG key ID: 1E693F4CE4AEE7B4
9 changed files with 117 additions and 24 deletions

37
articles/compressor.py Normal file
View file

@ -0,0 +1,37 @@
import itertools
from django.conf import settings
class DummyArticleWithCode:
has_code = True
class DummyArticleNoCode:
has_code = False
class DummyNonAuthenticatedUser:
is_authenticated = False
class DummyAuthenticatedUser:
is_authenticated = True
def offline_context():
article_possibilities = [None, DummyArticleWithCode(), DummyArticleNoCode()]
user_possibilities = [DummyAuthenticatedUser(), DummyNonAuthenticatedUser()]
goatcounter_possibilities = [None, settings.GOATCOUNTER_DOMAIN]
all_possibilities = [
article_possibilities,
user_possibilities,
goatcounter_possibilities,
]
for _tuple in itertools.product(*all_possibilities):
yield {
"STATIC_URL": settings.STATIC_URL,
"article": _tuple[0],
"user": _tuple[1],
"goatcounter_domain": _tuple[2],
}

View file

@ -1,7 +1,8 @@
import random
import uuid
from functools import cached_property, reduce
from functools import cached_property
import rcssmin
import readtime
from django.contrib.auth.models import AbstractUser
from django.contrib.contenttypes.models import ContentType
@ -121,6 +122,10 @@ class Article(models.Model):
filter(None, map(lambda k: k.strip().lower(), self.keywords.split(",")))
)
@cached_property
def get_minified_custom_css(self):
return rcssmin.cssmin(self.custom_css)
def get_admin_url(self):
content_type = ContentType.objects.get_for_model(self.__class__)
return reverse(

View file

@ -1,9 +1,7 @@
{% extends 'articles/base.html' %}
{% block append_css %}
<style>
{{ article.custom_css }}
</style>
<style>{{ article.get_minified_custom_css }}</style>
{% endblock %}
{% block title %}{{ article.title }} | {% endblock %}

View file

@ -1,15 +1,8 @@
{% extends 'articles/base.html' %}
{% block append_css %}
<style>
{{ article.custom_css }}
</style>
<style>
.pagination {
display: flex;
justify-content: space-between;
}
</style>
<style>{{ article.get_minified_custom_css }}</style>
<style>.pagination{display:flex;justify-content:space-between}</style>
{% endblock %}
{% block title %}{% endblock %}

View file

@ -22,15 +22,10 @@
{% if user.is_authenticated %}
<link rel="stylesheet" href="{% static "authenticated.css" %}">
{% endif %}
{% block append_css %}
{% endblock %}
{% endcompress %}
{% compress js inline %}
{% if user.is_authenticated %}
<script src="{% static 'edit-keymap.js' %}" async></script>
{% endif %}
{% endcompress %}
{% block append_css %}
{% endblock %}
{% include "articles/snippets/favicon.html" %}
</head>
@ -60,7 +55,14 @@
for ongoing builds <a href="{{ blog_pipelines_url }}">here</a>.
</p>
</footer>
{% include "articles/snippets/analytics.html" %}
{% compress js inline %}
{% if user.is_authenticated %}
<script src="{% static 'edit-keymap.js' %}" async defer></script>
{% endif %}
{% endcompress %}
</body>
{% endspaceless %}
</html>

View file

@ -1,6 +1,7 @@
import uuid
import pytest
from django.core.management import call_command
from django.utils import timezone
from articles.models import Article, User
@ -43,3 +44,14 @@ def unpublished_article(author: User) -> Article:
content="## some draft article markdown\n\n[a draft article link](https://article.com)",
draft_key=uuid.uuid4(),
)
@pytest.fixture(autouse=True)
def enable_compressor(settings):
settings.COMPRESS_ENABLED = True
@pytest.fixture(autouse=True, scope="session")
def collect_static():
call_command("collectstatic", "--no-input", "--clear")
call_command("compress", "--force")

View file

@ -39,3 +39,41 @@ def test_save_article_doesnt_change_existing_slug(published_article: Article):
published_article.title = "This is a brand new title"
published_article.save()
assert published_article.slug == original_slug
@pytest.mark.django_db
def test_empty_custom_css_minified(published_article):
published_article.custom_css = ""
assert published_article.get_minified_custom_css == ""
@pytest.mark.django_db
def test_simple_custom_css_minified(published_article):
published_article.custom_css = ".cls {\n background-color: red;\n}"
assert published_article.get_minified_custom_css == ".cls{background-color:red}"
@pytest.mark.django_db
def test_larger_custom_css_minified(published_article):
published_article.custom_css = """\
.profile {
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
}
.profile img {
max-width: 200px;
min-width: 100px;
max-height: 200px;
min-height: 100px;
border-radius: 10%;
padding: 1rem;
flex-shrink: 1;
flex-grow: 0;
padding: 0;
}"""
assert (
published_article.get_minified_custom_css
== ".profile{display:flex;justify-content:space-evenly;flex-wrap:wrap}.profile img{max-width:200px;min-width:100px;max-height:200px;min-height:100px;border-radius:10%;padding:1rem;flex-shrink:1;flex-grow:0;padding:0}"
)

View file

@ -117,6 +117,13 @@ if MEMCACHED_LOCATION:
"LOCATION": MEMCACHED_LOCATION,
}
}
else:
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.db.DatabaseCache",
"LOCATION": "cache",
}
}
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
@ -203,10 +210,7 @@ GOATCOUNTER_DOMAIN = os.getenv("GOATCOUNTER_DOMAIN")
LOGIN_URL = "admin:login"
# ASSETS_AUTO_BUILD = DEBUG
# ASSETS_DEBUG = False
COMPRESS_ENABLED = True
# COMPRESS_ENABLED = True # Enable this if you want to force compression during dev
COMPRESS_FILTERS = {
"css": [
"compressor.filters.css_default.CssAbsoluteFilter",
@ -218,3 +222,6 @@ COMPRESS_FILTERS = {
}
if DEBUG:
COMPRESS_DEBUG_TOGGLE = "nocompress"
COMPRESS_OFFLINE = True
COMPRESS_OFFLINE_CONTEXT = "articles.compressor.offline_context"

View file

@ -2,4 +2,5 @@
set -eux
yes yes | python manage.py migrate
python manage.py collectstatic --noinput --clear
python manage.py compress
gunicorn blog.wsgi -b 0.0.0.0:8000 --log-file -