Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ ENV LANGUAGE=en_US.UTF-8
# Python runtime settings:
# - unbuffered output for log visibility in containers
# - add /app to PYTHONPATH for module resolution
ENV PYTHONUNBUFFERED 1
ENV PYTHONPATH /app
ENV PYTHONUNBUFFERED=1 \
PYTHONPATH=/app

# Default Django settings module for container runtime (can be overridden).
ENV DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE:-concordia.settings_docker}
Expand All @@ -105,14 +105,27 @@ COPY . /app

# Front-end build and asset pipeline:
# - update npm to a known major version
# - install JS dependencies (production-only) and build assets via gulp
RUN npm install --silent --global npm@10 && npm install --silent --omit=dev && npx gulp build
# - Install all JS dependencies (including devDependencies for plugins)
RUN npm install --silent --global npm@10 && npm install --silent

# Additional JS build step for Vite.
RUN npm run build
# - Build legacy (gulp css...) and modern assets (Vite)
# - This populates concordia/static/dist with hashed and compressed files.
RUN npx gulp build && npm run build

# Create Log Directory
# - Required for Django logging initialization when running collecstatic.
RUN mkdir -p /app/logs

# Install Python dependencies into the system environment using Pipenv and
# remove Pipenv cache to reduce image size.
RUN pipenv install --system --dev --deploy && rm -rf ~/.cache/
# - Bake static files into the image (Fast, no post-processing)
# - remove Pipenv cache to reduce image size.
RUN pipenv install --system --dev --deploy && \
python manage.py collectstatic --no-input --no-post-process && \
rm -rf ~/.cache/

# - Clean up node artifacts to reduce image size
RUN rm -rf node_modules && rm -rf ~/.cache/

# Container listens on port 80.
EXPOSE 80
Expand Down
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ certifi = "==2025.7.14"
websocket-client = "<1.8.0"
django = "~=5.2.0"
black = "*"
django-vite = "~=3.1.0"

[dev-packages]
invoke = "==2.2.0"
Expand Down
300 changes: 154 additions & 146 deletions Pipfile.lock

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion concordia/settings_dev.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os

from .settings_template import * # NOQA ignore=F405
from .settings_template import INSTALLED_APPS, LOGGING, MIDDLEWARE
from .settings_template import DJANGO_VITE, INSTALLED_APPS, LOGGING, MIDDLEWARE

LOGGING["handlers"]["stream"]["level"] = "DEBUG"
LOGGING["handlers"]["file"]["level"] = "DEBUG"
Expand Down Expand Up @@ -31,6 +31,13 @@

DEBUG = True

# Toggle this to True only when you run 'npm run dev' - vite dev server
# Otherwise, it will look for the manifest.json in /dist/
USE_VITE_DEV_SERVER = os.getenv("USE_VITE_DEV_SERVER", "false").lower() == "true"

DJANGO_VITE["default"]["dev_mode"] = USE_VITE_DEV_SERVER
DJANGO_VITE["default"]["dev_server_port"] = 5173

ALLOWED_HOSTS = ["127.0.0.1", "0.0.0.0", "*"] # nosec

EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
Expand Down
13 changes: 12 additions & 1 deletion concordia/settings_docker.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import os

from .settings_template import * # NOQA ignore=F405
from .settings_template import INSTALLED_APPS
from .settings_template import INSTALLED_APPS, STATIC_URL

DEBUG = os.getenv("DEBUG", "").lower() == "true"

EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"

INSTALLED_APPS += ["django_opensearch_dsl"]


def whitenoise_immutable_file_test(static_url):
"""
Determine if a file is immutable based on its URL.
Vite assets in the 'dist/' directory are hashed and safe to cache forever.
"""
return static_url.startswith(f"{STATIC_URL}dist/")


WHITENOISE_IMMUTABLE_FILE_TEST = whitenoise_immutable_file_test

# Globally disable auto-syncing
OPENSEARCH_DSL_AUTOSYNC = os.getenv("OPENSEARCH_DSL_AUTOSYNC", False)

Expand Down
2 changes: 1 addition & 1 deletion concordia/settings_local_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

DEBUG = False

DATABASES["default"]["PORT"] = "54323"
DATABASES["default"]["PORT"] = "5432"

CHANNEL_LAYERS = {
"default": {
Expand Down
21 changes: 19 additions & 2 deletions concordia/settings_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@
]

STATICFILES_DIRS = [
# Vite's new home (JS/Manifest)
os.path.join(SITE_ROOT_DIR, "concordia", "static", "dist"),
# Gulp's home (where base.css lives), based on gulpfile .dest('static/')
os.path.join(SITE_ROOT_DIR, "static"),
# Standard Admin assets
os.path.join(SITE_ROOT_DIR, "concordia", "static", "admin"),
]

NPM_FILE_PATTERNS = {
Expand Down Expand Up @@ -129,6 +134,7 @@
"channels",
"django_admin_multiple_choice_list_filter",
"tinymce",
"django_vite",
]

MIDDLEWARE = [
Expand Down Expand Up @@ -174,6 +180,7 @@
],
"libraries": {
"staticfiles": "django.templatetags.static",
"django_vite": "django_vite.templatetags.django_vite",
},
"loaders": [
"django.template.loaders.filesystem.Loader",
Expand Down Expand Up @@ -422,7 +429,8 @@
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
# Use the basic Compressed backend because Vite handled hashing and compression.
"BACKEND": "whitenoise.storage.CompressedStaticFilesStorage",
},
"assets": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
Expand All @@ -431,7 +439,16 @@
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
}
WHITENOISE_ROOT = os.path.join(SITE_ROOT_DIR, "static")

DJANGO_VITE = {
"default": {
"dev_mode": DEBUG,
"manifest_path": os.path.join(
SITE_ROOT_DIR, "concordia", "static", "dist", "manifest.json"
),
"static_url_prefix": "",
}
}

PASSWORD_RESET_TIMEOUT = 604800
ACCOUNT_ACTIVATION_DAYS = 7
Expand Down
8 changes: 2 additions & 6 deletions concordia/templates/account/profile.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% extends "base.html" %}

{% load humanize %}
{% load staticfiles %}
{% load staticfiles django_vite %}
{% load django_bootstrap5 %}

{% block prefetch %}
Expand Down Expand Up @@ -206,9 +206,5 @@ <h3>Volunteer Hours Spreadsheet</h3>
<script type="module" src="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.4.0/dist/duet/duet.esm.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.4.0/dist/duet/duet.js"></script>
{{ block.super }}
{% if LOCAL_DEV %}
<script type="module" src="http://localhost:5173/static/src/profile.js"></script>
{% else %}
<script type="module" src="{% static 'js/profile.js' %}"></script>
{% endif %}
{% vite_asset 'src/profile.js' %}
{% endblock body_scripts %}
10 changes: 4 additions & 6 deletions concordia/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% spaceless %}
{% load static staticfiles %}
{% load static django_vite %}
{% endspaceless %}<!DOCTYPE html>
<html lang="{{ language_code|default:'en'}}">
<head>
Expand Down Expand Up @@ -34,11 +34,7 @@
{% endblock prefetch %}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
{% block head_content %}
{% if LOCAL_DEV %}
<script type="module" src="http://localhost:5173/static/src/main.js"></script>
{% else %}
<script type="module" src="{% static 'js/main.js' %}"></script>
{% endif %}
{% vite_hmr_client %}
{% endblock head_content %}
{% block extra_scripts %}{% endblock %}
{% comment %}
Expand Down Expand Up @@ -295,6 +291,8 @@ <h2 class="h3 fw-normal text-center text-lg-start">Follow
window.STATIC_URL = "{% get_static_prefix %}";
</script>

{% vite_asset 'src/main.js' %}

{% block body_scripts %}{% endblock body_scripts %}

<script type="text/javascript">
Expand Down
9 changes: 2 additions & 7 deletions concordia/templates/static-page.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
{% extends "base.html" %}
{% load staticfiles %}
{% load staticfiles django_vite %}

{% block title %}{{ title }}{% endblock title %}

{% block extra_scripts %}
{% if about_page %}
{% if LOCAL_DEV %}
<script type="module" src="http://localhost:5173/static/src/js/visualizations/asset-status-overview.js"></script>
<script type="module" src="http://localhost:5173/static/src/js/about-page.js"></script>
{% else %}
<script type="module" src="{% static 'js/about.js' %}"></script>
{% endif %}
{% vite_asset 'src/about.js' %}
{% endif %}
{% endblock %}

Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ services:
app:
restart: unless-stopped
build: .
env_file:
- .env
environment: &django-environment
WAIT_HOSTS: db:5432, redis:6379
POSTGRESQL_HOST: db
Expand Down
3 changes: 0 additions & 3 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,5 @@ if [ -v SENTRY_BACKEND_DSN ]; then
echo "from sentry_sdk import capture_message;capture_message('This is a test event');" | ./manage.py shell
fi

echo "Running collectstatic"
./manage.py collectstatic --clear --noinput -v0

echo "Running Django ASGI server"
daphne -b 0.0.0.0 -p 80 concordia.asgi:application
10 changes: 9 additions & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,16 @@ function scripts() {
);
}

function vendor() {
return gulp
.src('node_modules/openseadragon/build/openseadragon/images/**/*')
.pipe(gulp.dest('static/openseadragon/images/'));
}

function watch() {
gulp.watch(paths.scripts, scripts);
gulp.watch(paths.styles, styles);
gulp.watch(paths.styles, vendor);
}

function clean() {
Expand All @@ -85,11 +92,12 @@ function clean() {
);
}

var build = gulp.parallel(styles, scripts);
var build = gulp.parallel(styles, scripts, vendor);

exports.build = build;
exports.clean = clean;
exports.default = gulp.series(build, watch);
exports.vendor = vendor;
exports.scripts = scripts;
exports.styles = styles;
exports.watch = watch;
64 changes: 63 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"@axe-core/cli": "^4.11.0",
"@puppeteer/browsers": "^2.10.13",
"child_process": "^1.0.2",
"stylelint-value-no-unknown-custom-properties": "^6.1.1"
"stylelint-value-no-unknown-custom-properties": "^6.1.1",
"vite-plugin-compression2": "^2.4.0"
},
"dependencies": {
"@duetds/date-picker": "^1.4.0",
Expand Down
Loading
Loading