Maybe we can move to always serving minimized assets with corresponding
source maps? I was under the impression this is the "best practice" these
days.

On Thu, 23 Apr 2020 at 10:09, Jacob Rief <jacob.r...@gmail.com> wrote:

> When specifying paths to assets like JavaScript files, but also CSS, the
> Django documentation states:
>
>> Any links to the file in the codebase should point to the compressed
>> version.
>> <https://docs.djangoproject.com/en/3.0/internals/contributing/writing-code/javascript/#javascript-patches>
>
>
> This statement however does not properly reflect Django's internal
> handling of such assets, for instance in
>
> https://github.com/django/django/blob/master/django/contrib/admin/helpers.py#L83-L84
>
> https://github.com/django/django/blob/master/django/contrib/admin/options.py#L639-L648
>
> https://github.com/django/django/blob/master/django/contrib/admin/options.py#L2026-L2028
>
> https://github.com/django/django/blob/master/django/contrib/admin/widgets.py#L446-L460
> we see, that Django only serves the minimized version of the file, when
> not in DEBUG mode.
>
> This inconsistent handling of assets can cause other problems for third
> party apps, if they follow the documentation as show in the first link.
> If in their Media definition they refer to the minimized version of a
> Django asset, say 'admin/js/vendor/jquery/jquery.min.js', then
> the automatic sorting does not work anymore in DEBUG mode. If on the other
> side they refer to 'admin/js/vendor/jquery/jquery.js',
> then automatic sorting fails in production.
>
> There are two solutions to this problem.
>
> *Either*
>
> The documentation explicitly states that when a Media definition refers to
> internal Django assets, one *must* distinguish between the
> minimized and unminimized version, just as Django's internal Media
> definitions do (see code examples above).
> This however can easily be forgotten and errors therefore become visible
> only after deployment.
>
> *Or*
>
> We rewrite the FileSystemFinder and AppDirectoriesFinder so that in DEBUG
> mode, Django looks if an unminimized version
> of the same asset exists, and if so it then serves that. Doing that
> automatically is easy, because the general convention is, that the .min
> infix is always placed immediately before the .js- or .css file extension.
>
> In many of my projects I therefore use these two alternative finders,
> which do exactly that:
>
> import os
> from django.conf import settings
> from django.contrib.staticfiles.finders import (FileSystemFinder as 
> FileSystemFinderBase, AppDirectoriesFinder as AppDirectoriesFinderBase)
>
>
> class FileSystemFinder(FileSystemFinderBase):
>     """
>     In debug mode, serve /static/any/asset.min.ext as /static/any/asset.ext
>     """
>     locations = []
>     serve_unminimized = getattr(settings, 'DEBUG', False)
>
>     def find_location(self, root, path, prefix=None):
>         if self.serve_unminimized:
>             # search for the unminimized version, and if it exists, return it
>             base, ext = os.path.splitext(path)
>             base, minext = os.path.splitext(base)
>             if minext == '.min':
>                 unminimized_path = super().find_location(root, base + ext, 
> prefix)
>                 if unminimized_path:
>                     return unminimized_path
>         # otherwise proceed with the given one
>         path = super().find_location(root, path, prefix)
>         return path
>
>
> class AppDirectoriesFinder(AppDirectoriesFinderBase):
>     serve_unminimized = getattr(settings, 'DEBUG', False)
>
>     def find_in_app(self, app, path):
>         matched_path = super().find_in_app(app, path)
>         if matched_path and self.serve_unminimized:
>             base, ext = os.path.splitext(matched_path)
>             base, minext = os.path.splitext(base)
>             if minext == '.min':
>                 storage = self.storages.get(app, None)
>                 path = base + ext
>                 if storage.exists(path):
>                     path = storage.path(path)
>                     if path:
>                         return path
>         return matched_path
>
>
> In my opinion this approach makes Django's internal and 3rd party package
> code more readable, because it removes the clutter of
> case distinction between DEBUG and production mode for each referred
> JavaScript and CSS asset. It also might be less error prone.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to django-developers+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/dd904eeb-a877-48d3-81fa-e72fe71a6735%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/dd904eeb-a877-48d3-81fa-e72fe71a6735%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>


-- 
Adam

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAMyDDM1XnV8Sn3cdup%3D2Sg%2BS8DwMA%2BhM6ApEMfvhbGAtbuk7bQ%40mail.gmail.com.

Reply via email to