django-compressor creates javascript with syntax errors - django

A bit of background... I'm setting up my new site's base template and I'm including some popular javascript libraries, such as AngularJS, Bootstrap's javascript files, and Underscore.js. Of course I wrap these files in {% compress js %}. Example code below:
{% compress js %}
<script src="{{ STATIC_URL }}new_js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script>
<script>window.jQuery || document.write('<script src="{{ STATIC_URL }}new_js/vendor/jquery-1.8.3.min.js"><\/script>');</script>
<script src="{{ STATIC_URL }}new_js/vendor/bootstrap.js"></script>
<!-- Angular -->
<script src="{{ STATIC_URL }}new_js/vendor/angular.min.js"></script>
<script src="{{ STATIC_URL }}new_js/angular/directives.js"></script>
<script src="{{ STATIC_URL }}new_js/angular/services.js"></script>
<script src="{{ STATIC_URL }}new_js/vendor/underscore-1.4.3.min.js"></script>
{% block extra_js %}{% endblock %}
{% endcompress %}
I know django-compressor only runs the minification filters, so it's probably the minifiers not generating the correct Javascript output.
Here is the JS error I get with JSMin:
SyntaxError: invalid increment operand
http://localhost:8000/site_media/static/cache/js/0f5eb5fb3b24.js
Line 448
And the error from the file generated by SlimIt:
SyntaxError: missing ; after for-loop initializer
http://localhost:8000/site_media/static/cache/js/7fbdf61f5abb.js
Line 1
I'm not entirely sure what's going on here, it seems hard to believe the minifiers would generate incorrect files on these common js libraries.
Has anyone run into problems with django-compressor's Javascript filters messing up common libraries?

I went on IRC and someone gave me a good tip. They told me to use the non-minified version of Javascript files. That way, you can debug in development environment. That solved most of my problems.
There was still an issue with the latest version of Underscore.js 1.4.3, but it was fixed in their dev branch.
There was also an issue with https://github.com/jonthornton/jquery-timepicker. So I just put it in {% nocompress js %} for now.

Related

Django + React production setup

It looks like a very basic question and I'm confused by the fact that I cannot find any sensible tutorial on that. I'm trying to setup Django + React production build. After running all kinds of transpilation, minification etc. I end up having .js and .css bundles, index.html and several other files like favicon, service-worker.js etc. Now I need to serve this with Django.
All of these files are static files and should probably be served as static files by the http server (nginx in my case). The variant I came up with was to modify index.html to make it a valid Django template: {% load static %} in the beginning, replace all hardcoded links with {% static 'filepath' %} and serve it using TemplateView, other files are served by nginx. This works fine, however, modifying build results looks like a bad idea. Generated bundles contain a unique hash for each build and I would need to replace that hash in the template after each build. I obviously can automate it but it looks weird. I would prefer not to touch build results at all, but how should I serve static files then? nginx is configured to serve static files under /static/ path and cannot serve files like service-worker.js as static files.
So the question is how do I configure Django + React for production so that I don't have to manually modify build results and can serve static files properly using nginx?
The main problem to combine React and Django is that Django wants to render the templates by itself, but React wants also to execute the render, since it has been created for that. That's why there a lot of approximations that use django just as as REST API when working with react.
But, if you want django to Render the templates to avoid having a Single Page Application (as react provides) and to use all the other tools from django, the main flow that we use in our company is:
You create your components, in js files. For example: component.js
You use babel to compile the JSX files to native Javascript, and babels creates, for example, component.build.js. Django will serve this compiled files, so react is going to be used only in develop tasks because all React code will be transformed to JS before moving to production. For django, all the react components will be just JS code already compiled.
You can use Webpack to automatically move component.build.js to a folder where django can serve them, for example your_project/static/your_app/component.buid.js
You create a django template base.html which will be used as the base template that all your templates will extend. Here you put the header and all your common scripts and styles. For example, bootstrap should be here if used. Remember to leave blocks in this base template to use them in the templates that are going to extend the base.html. Here is the base.html that we use:
{% with version="2.0" %}
<!DOCTYPE html>
{% load static %}
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="author" content="">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- base styles goes here -->
<!-- include here bootstrap or styles that are common to all your website -->
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
<!-- custom styles for each app go into this block-->
{% block app_styles %}
<!-- here will go the apps local styles -->
{% endblock %}
</head>
<body>
{% block app %}
<!-- This block will be used by the apps to load their react components -->
{% endblock %}
<!-- base js go here -->
<script src="{% static 'common/pluggins/jquery3.4.1.min.js' %}"></script>
</script>
<script src="{% static 'common/pluggins/fontawesome.js' %}"></script>
<script src="{% static 'common/scripts/base.js' %}?v={{version}}"></script> <!-- File for common utils -->
<!-- custom js for each app go here. You should define your Content() here -->
{% block local_scripts %}
<!-- here will go the app local scripts -->
{% endblock %}
</body>
</html>
{% endwith %}
Create the templates for each of your django apps, by extending the base.html. Remember to include here the <div> that is going to be used by react to render the content. Aslo, remember that this is the place to include the component.build.js compiled JS file that bable created before. Here there is an example that we use to build a dashboard.html in our website:
{% extends 'common/base.html' %}
{% load static %}
{% block app_styles %}
<link rel="stylesheet" href="{% static 'dashboard/styles/dashboard.css' %}?v={{version}}">
{% endblock %}
{% block app %}
<!-- Here is the div used by react -->
<div id="myreact-content"></div>
{% endblock %}
{% block local_scripts %}
<!-- IMPORTANT: Import here the compiled file -->
<script src="{% static 'component.build.js' %}"></script>
{% endblock %}
Set the correct urls.py in your projects and in your app
Set the correct configuration in setting.py to make accesible the static js/css files and the templates
Run your django server and You're done!
In this video you have a small guide on how to configure npm, babel and django. With a correct configuration, everything will be updated automatically when you change some code in your JSX (not compiled) files, so the develop tasks will be more friendly.
https://www.youtube.com/watch?v=Mx3ChaYA0Gw

django-compressor not working on less files in production

I'm not sure what caused this, it was working earlier. The problem is that I'm not getting any useful debug information in my logs, so I don't know where the failure is occurring.
{% compress css %}
<link rel="stylesheet" type="text/less" href="{{ STATIC_URL }}css/style.less" />
{% block extrastyle %}
{% endblock %}
{% endcompress %}
It's not processing the less file. The output is currently:
<link rel="stylesheet" type="text/less" href="/static/css/style.less" />
It is, however, minifying the javascript I have at the end of the <body> tag, so compress is enabled, but it's just not processing the less block.
My production settings have DEBUG=False. I got into a shell using manage.py shell --settings=settings.production, and checked my django settings:
from django.conf import settings
>>> settings.COMPRESS_ENABLED
True
>>> settings.COMPRESS_PRECOMPILERS
(('text/less', 'lessc {infile} {outfile}'),)
lessc seems to work fine from commandline:
$ lessc test.css /tmp/out.css
How can I find out what's causing this to happen?
Try ./manage.py compress --force and that will force compress your assets and show which line, if any, is tripping it up. My project had small #import reference problems and that broke it in production.
This turned out to be an issue with my less path. The lessc binary that was being run was a different version than the one that needed to be run.

Conditionally loading development or production static files in Django template

I am using Yeoman (http://yeoman.io/) as a front-end build process which concat/minifies css and javascript.
In a development environment I want separate, un-minified source to be loaded for easy debugging without having to setup Chrome Source Maps (http://code.google.com/p/closure-compiler/wiki/SourceMaps). In production the concatenated, minified source is loaded for performance.
My initial approach is to use a conditional inside my template as follows:
{% if DEVELOPEMENT %}
<!-- library -->
<script src="{{ STATIC_URL }}lib/jquery.js"></script>
<script src="{{ STATIC_URL }}lib/some_library.js"></script>
<!-- app -->
<script src="{{ STATIC_URL }}scripts/main.js"></script>
<script src="{{ STATIC_URL }}scripts/app_model.js"></script>
<script src="{{ STATIC_URL }}scripts/app_view.js"></script>
{% else %}
<script src="{{ STATIC_URL }}min/lib.min.js"></script>
<script src="{{ STATIC_URL }}min/app.min.js"></script>
{% endif %}
DEVELOPMENT is exposed to the template context using a context processor:
from django.conf import settings # import the settings file
def development(context):
return {'DEVELOPEMENT': settings.DEVELOPEMENT}
Are there any drawbacks to this method and is there a cleaner way to accomplish this in Django?
I would use your DEBUG setting which is already included in django.core.context_processors.debug.
{% if debug %}
<!-- scripts -->
{% else %}
<!-- other scripts -->
{% endif %}

Error with static template block tag in Django 1.3

I'm trying to use the static template block tag in one of my template but I get an exception I don't understand.
Here is the template code:
<img src="{{STATIC_URL}}closed.png" alt="Closed message" />
<br/>
{% load static %}
<img src="{% get_static_prefix %}closed.png" %}" alt="Closed message"/>
<br/>
<img src="{% static "closed.png" %}" alt="Closed message"/>
The two first image display instructions work if I comment out the last one.
When the last one is uncommented I get an exception:
Invalid block tag: 'static'
The code is based on this django documentation section.
If someone is on > 1.3 and gets this issue, check your INSTALLED_APPS and make sure that 'django.contrib.staticfiles', is present. In your template include: {% load staticfiles %} and then use it as such:
//ensure the your syntax is correct
<link rel="shortcut icon" type="image/x-icon" href="{% static "assets/favicon.ico" %}?v=2" />
I ran into this problem because I had a syntax error and verified my setup as per django projects docs.
I had the same problem, and the problem turned out to be that I forgot to
{% load staticfiles %}
More about it at Django Documentation here
Are you using the development version? Most likely, you're using version 1.3, in which case you should be looking at this documentation instead.

including css in Django

I'm new to Django, and i'm having hard time including css styles in a template.
I read this and tried to do the same but it's not working for me.
my Template:
{% load static %}<html><head><link href="{% get_static_prefix %}/style.css" rel='stylesheet' type='text/css' /></head><body>
the HTML i get:
<head><link href="C:/Users/Nayish/workspace/am/src/am/static/style.css"rel='stylesheet'type='text/css' /></head>
Note that this is the folder containing my css.
Thanks, Boris.
Make sure you haven't mixed up the STATIC_ROOT and STATIC_URL settings.
STATIC_ROOT defines where the files are on the storage system (usually your local hard disc for local development), while STATIC_URL defines the URL from where the server serves them. The second one is usually referred to in templates, and it is also the value that the {% get_static_prefix %} template tag returns.
I am guessing you aren't using static css sheets. I always just do:
<html>
<head>
{%block stylesheet %}
<style type="text/css" title="currentStyle">
#import "{{MEDIA_URL}}css/style.css";
</style>
{% endblock stylesheet%}
....
I then set my Media root, and store the files as
MEDIA_ROOT=<fullyquallified patyh>/Media/css/<css files>
MEDIA_URL=http://localhost/mysite/
It should be noted that STATIC_URL defaults to MEDIA_URL if its not defined.