Changed cache-busting implementation for static files

Since 3.2.1 django CMS has used the ``GET`` parameter to reset the cache of its
static files. This doesn't play well with proxies, CDNs and so on.

This patch invalidates caching by changing the paths of static files instead.

The django CMS release process now requires additional steps to account for the
change (documented).
This commit is contained in:
Vadim Sikora
2016-06-29 16:56:55 +02:00
parent 9485daf76f
commit 6c41c31634
32 changed files with 53 additions and 62 deletions
+2
View File
@@ -5,6 +5,8 @@
tags and JavaScript is used to add event handlers and plugin data directly to
the plugin markup. This fixes most of the rendering issues that were present
because of the extra markup.
* Changed cache-busting implementation, it is now handled by a path change,
not by GET parameter.
=== 3.3.1 (unreleased) ===
+4 -2
View File
@@ -5,8 +5,10 @@
- Build newest english JS translations (django-admin.py makemessages -l en -d djangojs)
- Pull translations (tx pull -f -a)
- Compile translations (django-admin.py compilemessages)
- Make sure css files are compiled from latest sass source (gulp sass)
- Make sure js files are bundled and minified propery from latest source (gulp bundle)
- Make sure icons are recreated in the new place (gulp icons)
- Make sure CSS files are compiled from latest sass source (gulp sass)
- Make sure JS files are bundled and minified propery from latest source (gulp bundle)
- Make sure to remove JS, CSS and font files from the older version of CMS
- Check CHANGELOG that all closed PRs are present.
- Prepare blog post, including "Release" tag
- update AUTHORS file (python develop.py authors)
-3
View File
@@ -21,7 +21,6 @@ from cms.plugin_pool import plugin_pool
from cms.utils import permissions
from cms.utils.compat.dj import is_installed
from cms.utils.conf import get_cms_setting
from cms.utils.urlutils import static_with_version
try:
# djangocms_text_ckeditor is not guaranteed to be available
@@ -86,8 +85,6 @@ class PageTypeSelect(forms.widgets.Select):
'cms/js/widgets/wizard.pagetypeselect.js',
)
js = tuple(map(static_with_version, js))
class BaseCMSPageForm(forms.Form):
page = None
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
/*!
* @copyright: https://github.com/divio/django-cms
*/@font-face{font-family:django-cms-iconfont;src:url(../../fonts/3.3.0/django-cms-iconfont.eot);src:url(../../fonts/3.3.0/django-cms-iconfont.eot#iefix) format("eot"),url(../../fonts/3.3.0/django-cms-iconfont.woff2) format("woff2"),url(../../fonts/3.3.0/django-cms-iconfont.woff) format("woff"),url(../../fonts/3.3.0/django-cms-iconfont.ttf) format("truetype"),url(../../fonts/3.3.0/django-cms-iconfont.svg#django-cms-iconfont) format("svg");font-weight:400;font-style:normal}.cms-icon,.cms-welcome .cms-welcome-logo,.cms-welcome .cms-welcome-logo:hover{display:inline-block;font:normal normal normal 16px/1 django-cms-iconfont;text-rendering:auto;-webkit-transform:translate(0,0);transform:translate(0,0);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.cms-icon-alias:before{content:"\E001"}.cms-icon-arrow-right:before{content:"\E002"}.cms-icon-arrow-wide:before{content:"\E003"}.cms-icon-arrow:before{content:"\E004"}.cms-icon-bin:before{content:"\E005"}.cms-icon-check-o:before{content:"\E006"}.cms-icon-check-square:before{content:"\E007"}.cms-icon-check:before{content:"\E008"}.cms-icon-close:before{content:"\E009"}.cms-icon-cogs:before{content:"\E00A"}.cms-icon-copy:before{content:"\E00B"}.cms-icon-eye:before{content:"\E00C"}.cms-icon-forbidden:before{content:"\E00D"}.cms-icon-handler:before{content:"\E00E"}.cms-icon-home:before{content:"\E00F"}.cms-icon-info:before{content:"\E010"}.cms-icon-loader:before{content:"\E011"}.cms-icon-lock:before{content:"\E012"}.cms-icon-logo:before{content:"\E013"}.cms-icon-menu:before{content:"\E014"}.cms-icon-minimize:before{content:"\E015"}.cms-icon-minus-square-o:before{content:"\E016"}.cms-icon-minus-square:before{content:"\E017"}.cms-icon-minus:before{content:"\E018"}.cms-icon-paste:before{content:"\E019"}.cms-icon-pencil:before{content:"\E01A"}.cms-icon-pin:before{content:"\E01B"}.cms-icon-plus-square-o:before{content:"\E01C"}.cms-icon-plus:before{content:"\E01D"}.cms-icon-puzzle:before{content:"\E01E"}.cms-icon-scissors:before{content:"\E01F"}.cms-icon-search:before{content:"\E020"}.cms-icon-sitemap:before{content:"\E021"}.cms-icon-squares:before{content:"\E022"}.cms-icon-window:before{content:"\E023"}.cms-welcome-bg{background:#f2f2f2}.cms-welcome{color:#454545;width:60%;min-width:320px;margin:0 auto}.cms-welcome a{color:#0bf}.cms-welcome a:active,.cms-welcome a:focus,.cms-welcome a:hover{text-decoration:underline}.cms-welcome .cms-hidden{display:none}.cms-welcome .cms-welcome-footer,.cms-welcome .cms-welcome-section{box-sizing:border-box;width:60%;min-width:320px;margin:0 auto}.cms-welcome .cms-welcome-header{text-align:center}.cms-welcome .cms-welcome-heading{color:#999;font-size:22px;font-weight:200;text-align:center;padding:40px 0 15px;border-bottom:1px solid #ddd}.cms-welcome .cms-welcome-heading .cms-icon{color:#693}.cms-welcome .cms-welcome-logo,.cms-welcome .cms-welcome-logo:hover{font-size:35px;text-decoration:none;margin:50px auto 30px;color:#666}.cms-welcome .cms-welcome-logo:before,.cms-welcome .cms-welcome-logo:hover:before{content:"\E013";color:#000;-webkit-transition:color .2s;transition:color .2s}.cms-welcome .cms-welcome-logo:hover:before,.cms-welcome .cms-welcome-logo:hover:hover:before{color:#0bf}.cms-welcome .cms-welcome-section{box-shadow:0 0 5px #ddd;padding:20px;margin-bottom:5px;background:#fff}.cms-welcome .cms-welcome-section h2{font-size:16px;font-weight:700;margin:0 0 15px}.cms-welcome .cms-welcome-section p{padding:5px 0}.cms-welcome .cms-welcome-links{padding:10px 5px;margin:0 0 15px;border-bottom:1px solid #ddd}.cms-welcome .cms-welcome-links a{padding:0 5px}.cms-welcome .cms-welcome-notes{font-size:12px;line-height:16px;color:#999;padding:5px 10px}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-3
View File
@@ -1,3 +0,0 @@
/*!
* @copyright: https://github.com/divio/django-cms
*/@font-face{font-family:django-cms-iconfont;src:url(../fonts/django-cms-iconfont.eot?v=3.3.0);src:url(../fonts/django-cms-iconfont.eot?v=3.3.0#iefix) format("eot"),url(../fonts/django-cms-iconfont.woff2?v=3.3.0) format("woff2"),url(../fonts/django-cms-iconfont.woff?v=3.3.0) format("woff"),url(../fonts/django-cms-iconfont.ttf?v=3.3.0) format("truetype"),url(../fonts/django-cms-iconfont.svg?v=3.3.0#django-cms-iconfont) format("svg");font-weight:400;font-style:normal}.cms-icon,.cms-welcome .cms-welcome-logo,.cms-welcome .cms-welcome-logo:hover{display:inline-block;font:normal normal normal 16px/1 django-cms-iconfont;text-rendering:auto;-webkit-transform:translate(0,0);transform:translate(0,0);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.cms-icon-alias:before{content:"\E001"}.cms-icon-arrow-right:before{content:"\E002"}.cms-icon-arrow-wide:before{content:"\E003"}.cms-icon-arrow:before{content:"\E004"}.cms-icon-bin:before{content:"\E005"}.cms-icon-check-o:before{content:"\E006"}.cms-icon-check-square:before{content:"\E007"}.cms-icon-check:before{content:"\E008"}.cms-icon-close:before{content:"\E009"}.cms-icon-cogs:before{content:"\E00A"}.cms-icon-copy:before{content:"\E00B"}.cms-icon-eye:before{content:"\E00C"}.cms-icon-forbidden:before{content:"\E00D"}.cms-icon-handler:before{content:"\E00E"}.cms-icon-home:before{content:"\E00F"}.cms-icon-info:before{content:"\E010"}.cms-icon-loader:before{content:"\E011"}.cms-icon-lock:before{content:"\E012"}.cms-icon-logo:before{content:"\E013"}.cms-icon-menu:before{content:"\E014"}.cms-icon-minimize:before{content:"\E015"}.cms-icon-minus-square-o:before{content:"\E016"}.cms-icon-minus-square:before{content:"\E017"}.cms-icon-minus:before{content:"\E018"}.cms-icon-paste:before{content:"\E019"}.cms-icon-pencil:before{content:"\E01A"}.cms-icon-pin:before{content:"\E01B"}.cms-icon-plus-square-o:before{content:"\E01C"}.cms-icon-plus:before{content:"\E01D"}.cms-icon-puzzle:before{content:"\E01E"}.cms-icon-scissors:before{content:"\E01F"}.cms-icon-search:before{content:"\E020"}.cms-icon-sitemap:before{content:"\E021"}.cms-icon-squares:before{content:"\E022"}.cms-icon-window:before{content:"\E023"}.cms-welcome-bg{background:#f2f2f2}.cms-welcome{color:#454545;width:60%;min-width:320px;margin:0 auto}.cms-welcome a{color:#0bf}.cms-welcome a:active,.cms-welcome a:focus,.cms-welcome a:hover{text-decoration:underline}.cms-welcome .cms-hidden{display:none}.cms-welcome .cms-welcome-footer,.cms-welcome .cms-welcome-section{box-sizing:border-box;width:60%;min-width:320px;margin:0 auto}.cms-welcome .cms-welcome-header{text-align:center}.cms-welcome .cms-welcome-heading{color:#999;font-size:22px;font-weight:200;text-align:center;padding:40px 0 15px;border-bottom:1px solid #ddd}.cms-welcome .cms-welcome-heading .cms-icon{color:#693}.cms-welcome .cms-welcome-logo,.cms-welcome .cms-welcome-logo:hover{font-size:35px;text-decoration:none;margin:50px auto 30px;color:#666}.cms-welcome .cms-welcome-logo:before,.cms-welcome .cms-welcome-logo:hover:before{content:"\E013";color:#000;-webkit-transition:color .2s;transition:color .2s}.cms-welcome .cms-welcome-logo:hover:before,.cms-welcome .cms-welcome-logo:hover:hover:before{color:#0bf}.cms-welcome .cms-welcome-section{box-shadow:0 0 5px #ddd;padding:20px;margin-bottom:5px;background:#fff}.cms-welcome .cms-welcome-section h2{font-size:16px;font-weight:700;margin:0 0 15px}.cms-welcome .cms-welcome-section p{padding:5px 0}.cms-welcome .cms-welcome-links{padding:10px 5px;margin:0 0 15px;border-bottom:1px solid #ddd}.cms-welcome .cms-welcome-links a{padding:0 5px}.cms-welcome .cms-welcome-notes{font-size:12px;line-height:16px;color:#999;padding:5px 10px}

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -24,7 +24,7 @@ cms-plugin.cms-plugin-text-node {
max-width: none;
margin: 0 !important;
padding: 0 !important;
background: url("../img/toolbar/render_model_icon.png") no-repeat;
background: url("../../img/toolbar/render_model_icon.png") no-repeat;
}
}
@@ -41,6 +41,6 @@ cms-plugin.cms-plugin-text-node {
max-width: none;
margin: 0 !important;
padding: 0 !important;
background: url("../img/toolbar/render_model_add.png") no-repeat;
background: url("../../img/toolbar/render_model_add.png") no-repeat;
}
}
@@ -4,12 +4,12 @@
// default font file generated by gulp
@font-face {
font-family: "django-cms-iconfont";
src: url("../fonts/django-cms-iconfont.eot?v=__VERSION__");
src: url("../fonts/django-cms-iconfont.eot?v=__VERSION__#iefix") format("eot"),
url("../fonts/django-cms-iconfont.woff2?v=__VERSION__") format("woff2"),
url("../fonts/django-cms-iconfont.woff?v=__VERSION__") format("woff"),
url("../fonts/django-cms-iconfont.ttf?v=__VERSION__") format("truetype"),
url("../fonts/django-cms-iconfont.svg?v=__VERSION__#django-cms-iconfont") format("svg");
src: url("../../fonts/3.3.0/django-cms-iconfont.eot");
src: url("../../fonts/3.3.0/django-cms-iconfont.eot#iefix") format("eot"),
url("../../fonts/3.3.0/django-cms-iconfont.woff2") format("woff2"),
url("../../fonts/3.3.0/django-cms-iconfont.woff") format("woff"),
url("../../fonts/3.3.0/django-cms-iconfont.ttf") format("truetype"),
url("../../fonts/3.3.0/django-cms-iconfont.svg#django-cms-iconfont") format("svg");
font-weight: normal;
font-style: normal;
}
+2 -2
View File
@@ -2,9 +2,9 @@
// LOADER
.cms-loader {
background: $loader-bgcolor url("../img/loader.gif?uf5b664wnc") no-repeat center center !important;
background: $loader-bgcolor url("../../img/loader.gif?uf5b664wnc") no-repeat center center !important;
@include print-and-retina() {
background-image: url("../img/loader@2x.gif?uf5b664wnc") !important;
background-image: url("../../img/loader@2x.gif?uf5b664wnc") !important;
background-size: 32px !important;
}
}
@@ -798,7 +798,7 @@
margin-top: -1px;
border: 1px solid $gray-lighter;
border-right: none;
background: $white url('../img/pagetree/tree-li-drag.gif') no-repeat -1px center;
background: $white url('../../img/pagetree/tree-li-drag.gif') no-repeat -1px center;
image-rendering: pixelated;
&:hover {
@@ -906,7 +906,7 @@
height: $pagetree-cell-height;
padding: $pagetree-anchor-padding !important;
margin-left: -$pagetree-marker-size + 1;
background: $color-primary url('../img/pagetree/tree-li-drag.gif') no-repeat -1px center;
background: $color-primary url('../../img/pagetree/tree-li-drag.gif') no-repeat -1px center;
color: $white;
// copy icon triggered when pressing `CMD`
.jstree-copy {
+6 -6
View File
@@ -4,12 +4,12 @@
// default font file generated by gulp
@font-face {
font-family: "<%= fontName %>";
src: url("<%= fontPath %><%= fontName %>.eot?v=__VERSION__");
src: url("<%= fontPath %><%= fontName %>.eot?v=__VERSION__#iefix") format("eot"),
url("<%= fontPath %><%= fontName %>.woff2?v=__VERSION__") format("woff2"),
url("<%= fontPath %><%= fontName %>.woff?v=__VERSION__") format("woff"),
url("<%= fontPath %><%= fontName %>.ttf?v=__VERSION__") format("truetype"),
url("<%= fontPath %><%= fontName %>.svg?v=__VERSION__#<%= fontName %>") format("svg");
src: url("<%= fontPath %><%= fontName %>.eot");
src: url("<%= fontPath %><%= fontName %>.eot#iefix") format("eot"),
url("<%= fontPath %><%= fontName %>.woff2") format("woff2"),
url("<%= fontPath %><%= fontName %>.woff") format("woff"),
url("<%= fontPath %><%= fontName %>.ttf") format("truetype"),
url("<%= fontPath %><%= fontName %>.svg#<%= fontName %>") format("svg");
font-weight: normal;
font-style: normal;
}
@@ -13,7 +13,7 @@
{% endblock %}
{% block extrahead %}
<script src="{% static_with_version "admin/js/urlify.js" %}" type="text/javascript"></script>
<script src="{% static "admin/js/urlify.js" %}" type="text/javascript"></script>
<script src="{% static_with_version "cms/js/dist/bundle.admin.base.min.js" %}" type="text/javascript"></script>
<script src="{% static_with_version "cms/js/dist/bundle.admin.changeform.min.js" %}" type="text/javascript"></script>
<script type="text/javascript">
+5 -1
View File
@@ -8,6 +8,7 @@
var baseConf = require('./base.conf');
var path = require('path');
var fs = require('fs');
var argv = require('minimist')(process.argv.slice(2));
var webpack = require('webpack');
var webpackConfig = require('../../../webpack.config.js')({
@@ -42,6 +43,9 @@ webpackConfig.plugins = [
})
];
var CMS_VERSION = fs.readFileSync('cms/__init__.py', { encoding: 'utf-8' })
.match(/__version__ = '(.*?)'/)[1];
module.exports = function (config) {
var useSauceLabs = function () {
var val = process.env.USE_SAUCE_LABS;
@@ -62,7 +66,7 @@ module.exports = function (config) {
// list of files / patterns to load in the browser
files: [
'cms/static/cms/css/cms.base.css',
'cms/static/cms/css/' + CMS_VERSION + '/cms.base.css',
// fixtures
'cms/tests/frontend/unit/fixtures/**/*.html',
+1 -1
View File
@@ -82,7 +82,7 @@ class TemplatetagTests(CMSTestCase):
self.assertEqual('"%s"' % today.isoformat()[:-3], json_filter(today))
def test_static_with_version(self):
expected = '<script src="/static/cms/css/cms.base.css?%(version)s" type="text/javascript"></script>'
expected = '<script src="/static/cms/css/%(version)s/cms.base.css" type="text/javascript"></script>'
expected = expected % {'version': cms.__version__}
template = (
+6 -1
View File
@@ -61,7 +61,12 @@ def is_media_request(request):
def static_with_version(path):
return '%s?%s' % (path, cms.__version__)
"""
Changes provided path from `path/to/filename.ext` to `path/to/$CMS_VERSION/filename.ext`
"""
path_re = re.compile('(.*)/([^/]*$)')
return re.sub(path_re, r'\1/%s/\2' % (cms.__version__), path)
def add_url_parameters(url, *args, **params):
-2
View File
@@ -56,8 +56,6 @@ class WizardStep1Form(BaseFormMixin, forms.Form):
'cms/js/modules/cms.wizards.js',
)
js = tuple(map(static_with_version, js))
page = forms.ModelChoiceField(
queryset=Page.objects.all(),
required=False,
+5 -23
View File
@@ -107,22 +107,6 @@ var CMS_VERSION = fs.readFileSync('cms/__init__.py', { encoding: 'utf-8' })
// #####################################################################################################################
// #TASKS#
/**
* @function cacheBuster
* @param {Object} opts
* @param {String} [opts.version]
* @returns {Function}
*/
var cacheBuster = function (opts) {
var version = opts && opts.version ? opts.version : Math.random();
return function (css) {
css.replaceValues(/__VERSION__/g, { fast: '__VERSION__' }, function () {
return version;
});
};
};
gulp.task('sass', function () {
gulp.src(PROJECT_PATTERNS.sass)
.pipe(gulpif(options.debug, sourcemaps.init()))
@@ -133,25 +117,22 @@ gulp.task('sass', function () {
.pipe(postcss([
autoprefixer({
cascade: false
}),
cacheBuster({
version: CMS_VERSION
})
]))
.pipe(minifyCss({
rebase: false
}))
.pipe(gulpif(options.debug, sourcemaps.write()))
.pipe(gulp.dest(PROJECT_PATH.css));
.pipe(gulp.dest(PROJECT_PATH.css + '/' + CMS_VERSION + '/'));
});
gulp.task('icons', function () {
gulp.src(PROJECT_PATTERNS.icons)
.pipe(iconfontCss({
fontName: 'django-cms-iconfont',
fontPath: '../fonts/',
fontPath: '../../fonts/' + CMS_VERSION + '/',
path: PROJECT_PATH.sass + '/libs/_iconfont.scss',
targetPath: '../sass/components/_iconography.scss'
targetPath: '../../sass/components/_iconography.scss'
}))
.pipe(iconfont({
fontName: 'django-cms-iconfont',
@@ -160,7 +141,7 @@ gulp.task('icons', function () {
.on('glyphs', function (glyphs, opts) {
gutil.log.bind(glyphs, opts);
})
.pipe(gulp.dest(PROJECT_PATH.icons));
.pipe(gulp.dest(PROJECT_PATH.icons + '/' + CMS_VERSION + '/'));
});
gulp.task('lint', ['lint:javascript']);
@@ -207,6 +188,7 @@ var webpackBundle = function (opts) {
webpackOptions.PROJECT_PATH = PROJECT_PATH;
webpackOptions.debug = options.debug;
webpackOptions.CMS_VERSION = CMS_VERSION;
return function (done) {
var config = require('./webpack.config')(webpackOptions);
+2 -1
View File
@@ -4,6 +4,7 @@ module.exports = function (opts) {
'use strict';
var PROJECT_PATH = opts.PROJECT_PATH;
var CMS_VERSION = opts.CMS_VERSION;
var debug = opts.debug;
var baseConfig = {
@@ -16,7 +17,7 @@ module.exports = function (opts) {
'admin.changeform': PROJECT_PATH.js + '/admin.changeform.js'
},
output: {
path: PROJECT_PATH.js + '/dist/',
path: PROJECT_PATH.js + '/dist/' + CMS_VERSION + '/',
filename: 'bundle.[name].min.js',
jsonpFunction: 'cmsWebpackJsonp'
},