Django-трубопровод - загрузка страницы очень медленная

Я пытаюсь выполнить django-конвейер, чтобы минимизировать статические ресурсы, использовать кэш для них и упростить мои шаблоны. Мои файлы CSS и JS найдены и загружены моим браузером, но для загрузки моей (очень простой) домашней страницы занимает около 10 секунд.

enter image description here

Я использую Python 2.7.6, Django 1.7.3 и django-pipe 1.4.3. PyCharm запускает сервер разработки с локальным virtualenv.

My settings.py содержит следующее:

DEBUG = True
TEMPLATE_DEBUG = DEBUG

INSTALLED_APPS = (
    'django_admin_bootstrapped', # custom admin
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # pip installed apps
    'pipeline',
    # project apps
    'myapp',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'pipeline.middleware.MinifyHTMLMiddleware',
)

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    'pipeline.finders.FileSystemFinder',
    'pipeline.finders.CachedFileFinder',
    'pipeline.finders.PipelineFinder',
)

STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'myapp/static'),
)

STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
PIPELINE_CSS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor'
PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor'

PIPELINE_CSS = {
    'base': {
        'source_filenames': (
            'myapp/css/base.css',
            'myapp/bower_components/bootstrap/dist/css/bootstrap.css',
            'myapp/bower_components/Hover/css/hover.css',
            'myapp/bower_components/font-awesome/css/font-awesome.css',
        ),
        'output_filename': 'css/myapp.css',
    },
}

PIPELINE_JS = {
    'base': {
        'source_filenames': (
            'myapp/bower_components/jquery/dist/jquery.min.js',
            'myapp/bower_components/bootstrap/dist/js/bootstrap.min.js',
        ),
        'output_filename': 'js/myapp.js',
    },
}

Мой базовый HTML-шаблон содержит следующее:

{% load staticfiles %}
{% load pipeline %}

<!DOCTYPE html>
<html>
    <head>
        [...]
        {% block css %}
            {% stylesheet 'base' %}
        {% endblock css %}

        {% block javascript %}
            {% javascript 'base' %}
        {% endblock javascript %}

    </head>
    <body> [...] </body>
</html>

My home.html расширяет base.html, но не использует теги шаблона конвейера css и javascript.

Просто чтобы убедиться, что yuglify доступен:

$ yuglify --version
0.1.4

Что я здесь делаю неправильно?

Примечание: браузер не находит статические активы (myapp.css и myapp.js), если PIPELINE_ENABLED = True.

Ответ 1

Проблема заключается в том, что код тега шаблона выполняет кучу вещей, включая запуск сборщика для каждого запроса, когда debug is True, что делает dev болезненно медленным. Даже если debug False, templatetag все равно подключится и запросит S3 для нескольких вещей. Когда файлы локальны, это не большая проблема, но при использовании S3 это так. Единственное решение, которое я мог придумать, - это написать мой упрощенный упрощенный шаблон pipelines.py.

Прежде чем вы войдете в это, вам нужно знать две важные вещи, прежде всего, чтобы получить конвейер для работы. У меня есть пустая оболочка S3PipelineStorage, которая объединяет конвейер и boto, вы, вероятно, уже имеете это, если у вас есть работающий с s3 + конвейер, но он важно:

from pipeline.storage import PipelineMixin
from storages.backends.s3boto import S3BotoStorage

class S3PipelineStorage(PipelineMixin, S3BotoStorage):
    pass

Затем в настройках:

STATICFILES_STORAGE = 'path.to.your.file.S3PipelineStorage'

Теперь, если вы посмотрите на templatetag, вы увидите, что я использую staticfiles_storage.url, аналогичный исходному templatetag. Это добавляет путь s3 к относительному пути, но если вы не добавите этот параметр, вы будете запрашивать S3 каждый раз, чтобы сгенерировать URL. Вы можете добавить настройку или просто скопировать свой путь s3 вместо staticfiles_storage.url, но я предлагаю вам добавить этот параметр, потому что он повысит производительность везде, где будет создан URL-адрес для ресурса s3.

AWS_S3_CUSTOM_DOMAIN = 'your_bucket-%s.s3.amazonaws.com' % ENVIRONMENT.lower()

Теперь вы готовы к templatetag. Чтобы использовать его просто {% load pipelines %} вместо {% load pipeline %}.

from django.contrib.staticfiles.storage import staticfiles_storage
from django import template
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from pipeline.conf import settings

register = template.Library()

@register.simple_tag
def stylesheet(group):

    if group not in settings.PIPELINE_CSS:
        return ''

    if settings.DEBUG is False or settings.PIPELINE_ENABLED is True:
        context = {
            'type': 'text/css',
            'url': mark_safe(staticfiles_storage.url(settings.PIPELINE_CSS[group]['output_filename']))
        }
        html = render_to_string("pipeline/css.html", context)
    else:
        html = ''
        for path in settings.PIPELINE_CSS[group]['source_filenames']:
            context = {
                'type': 'text/css',
                'url': mark_safe(staticfiles_storage.url(path))
            }
            html = "%s\n        %s" % (html, render_to_string("pipeline/css.html", context))

    return html

@register.simple_tag
def javascript(group):

    if group not in settings.PIPELINE_JS:
        return ''

    if settings.DEBUG is False or settings.PIPELINE_ENABLED is True:
        context = {
            'type': 'text/javascript',
            'url': mark_safe(staticfiles_storage.url(settings.PIPELINE_JS[group]['output_filename']))
        }
        html = render_to_string("pipeline/js.html", context)
    else:
        html = ''
        for path in settings.PIPELINE_JS[group]['source_filenames']:
            context = {
                'type': 'text/javascript',
                'url': mark_safe(staticfiles_storage.url(path))
            }
            html = "%s\n        %s" % (html, render_to_string("pipeline/js.html", context))

    return html