mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-02-18 04:20:51 +03:00
Introduce static asset build infrastructure
This commit is contained in:
parent
e365c39f2a
commit
a8c109898e
1
{{cookiecutter.project_slug}}/.gitignore
vendored
1
{{cookiecutter.project_slug}}/.gitignore
vendored
|
@ -79,3 +79,4 @@ staticfiles/
|
|||
|
||||
.cache/
|
||||
|
||||
{{ cookiecutter.project_slug }}/static/build/
|
||||
|
|
|
@ -187,9 +187,10 @@ STATIC_ROOT = str(ROOT_DIR('staticfiles'))
|
|||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
_STATIC_BUILD_ROOT_DIR_NAME = 'build'
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
|
||||
STATICFILES_DIRS = [
|
||||
str(APPS_DIR.path('static')),
|
||||
(_STATIC_BUILD_ROOT_DIR_NAME, str(APPS_DIR.path('static').path(_STATIC_BUILD_ROOT_DIR_NAME))),
|
||||
]
|
||||
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
|
||||
|
|
|
@ -1,104 +1,161 @@
|
|||
const gulp = require('gulp')
|
||||
const pump = require('pump')
|
||||
const sass = require('gulp-sass')
|
||||
const pjson = require('./package.json')
|
||||
const autoprefixer = require('gulp-autoprefixer')
|
||||
const cleanCSS = require('gulp-clean-css')
|
||||
const rename = require('gulp-rename')
|
||||
const pixrem = require('gulp-pixrem')
|
||||
const concat = require('gulp-concat')
|
||||
const uglify = require('gulp-uglify')
|
||||
const imagemin = require('gulp-imagemin')
|
||||
const clean = require('gulp-clean')
|
||||
const spawn = require('child_process').spawn
|
||||
const runSequence = require('run-sequence')
|
||||
const browserSync = require('browser-sync').create()
|
||||
const reload = browserSync.reload
|
||||
|
||||
////////////////////////////////
|
||||
//Setup//
|
||||
////////////////////////////////
|
||||
const pathsConfig = function (appName) {
|
||||
this.paths = {}
|
||||
|
||||
// Plugins
|
||||
var gulp = require('gulp'),
|
||||
pjson = require('./package.json'),
|
||||
gutil = require('gulp-util'),
|
||||
sass = require('gulp-sass'),
|
||||
autoprefixer = require('gulp-autoprefixer'),
|
||||
cssnano = require('gulp-cssnano'),
|
||||
rename = require('gulp-rename'),
|
||||
del = require('del'),
|
||||
plumber = require('gulp-plumber'),
|
||||
pixrem = require('gulp-pixrem'),
|
||||
uglify = require('gulp-uglify'),
|
||||
imagemin = require('gulp-imagemin'),
|
||||
exec = require('child_process').exec,
|
||||
runSequence = require('run-sequence'),
|
||||
browserSync = require('browser-sync').create(),
|
||||
reload = browserSync.reload;
|
||||
this.paths['app'] = './' + (appName || pjson.name)
|
||||
|
||||
this.paths['static'] = this.paths['app'] + '/static'
|
||||
|
||||
// Relative paths function
|
||||
var pathsConfig = function (appName) {
|
||||
this.app = "./" + (appName || pjson.name);
|
||||
this.paths['build'] = this.paths['static'] + '/build'
|
||||
|
||||
return {
|
||||
app: this.app,
|
||||
templates: this.app + '/templates',
|
||||
css: this.app + '/static/css',
|
||||
sass: this.app + '/static/sass',
|
||||
fonts: this.app + '/static/fonts',
|
||||
images: this.app + '/static/images',
|
||||
js: this.app + '/static/js',
|
||||
}
|
||||
};
|
||||
this.paths['buildImages'] = this.paths['build'] + '/images'
|
||||
this.paths['images'] = this.paths['static'] + '/images'
|
||||
this.paths['images_files'] = this.paths['images'] + '/*'
|
||||
this.paths['buildImagesFavicons'] = this.paths['buildImages'] + '/favicons'
|
||||
this.paths['imagesFavicons'] = this.paths['images'] + '/favicons'
|
||||
this.paths['imagesFavicons_files'] = this.paths['imagesFavicons'] + '/*'
|
||||
|
||||
var paths = pathsConfig();
|
||||
this.paths['build_scriptsFileName'] = 'scripts.js'
|
||||
this.paths['scripts'] = this.paths['static'] + '/scripts'
|
||||
this.paths['scriptsJs'] = this.paths['scripts'] + '/js'
|
||||
this.paths['scriptsJs_files'] = this.paths['scriptsJs'] + '/*.js'
|
||||
|
||||
////////////////////////////////
|
||||
//Tasks//
|
||||
////////////////////////////////
|
||||
this.paths['build_stylesFileName'] = 'styles.css'
|
||||
this.paths['styles'] = this.paths['static'] + '/styles'
|
||||
this.paths['stylesSass'] = this.paths['styles'] + '/sass'
|
||||
this.paths['stylesSass_files'] = this.paths['stylesSass'] + '/*.scss'
|
||||
this.paths['stylesCss'] = this.paths['styles'] + '/css'
|
||||
this.paths['stylesCss_files'] = this.paths['stylesCss'] + '/*.css'
|
||||
|
||||
// Styles autoprefixing and minification
|
||||
gulp.task('styles', function() {
|
||||
return gulp.src(paths.sass + '/project.scss')
|
||||
.pipe(sass().on('error', sass.logError))
|
||||
.pipe(plumber()) // Checks for errors
|
||||
.pipe(autoprefixer({browsers: ['last 2 versions']})) // Adds vendor prefixes
|
||||
.pipe(pixrem()) // add fallbacks for rem units
|
||||
.pipe(gulp.dest(paths.css))
|
||||
.pipe(rename({ suffix: '.min' }))
|
||||
.pipe(cssnano()) // Minifies the result
|
||||
.pipe(gulp.dest(paths.css));
|
||||
});
|
||||
this.paths['templates'] = this.paths['app'] + '/templates'
|
||||
this.paths['templates_files'] = this.paths['templates'] + '/*.html'
|
||||
|
||||
// Javascript minification
|
||||
gulp.task('scripts', function() {
|
||||
return gulp.src(paths.js + '/project.js')
|
||||
.pipe(plumber()) // Checks for errors
|
||||
.pipe(uglify()) // Minifies the js
|
||||
.pipe(rename({ suffix: '.min' }))
|
||||
.pipe(gulp.dest(paths.js));
|
||||
});
|
||||
return this.paths
|
||||
}
|
||||
const paths = pathsConfig()
|
||||
|
||||
// Image compression
|
||||
gulp.task('imgCompression', function(){
|
||||
return gulp.src(paths.images + '/*')
|
||||
.pipe(imagemin()) // Compresses PNG, JPEG, GIF and SVG images
|
||||
.pipe(gulp.dest(paths.images))
|
||||
});
|
||||
// region scripts
|
||||
gulp.task('favicons-images', function (cb) {
|
||||
pump([gulp.src(paths.imagesFavicons_files),
|
||||
gulp.dest(paths.buildImagesFavicons)],
|
||||
cb)
|
||||
})
|
||||
|
||||
// Run django server
|
||||
gulp.task('runServer', function() {
|
||||
exec('python manage.py runserver', function (err, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
console.log(stderr);
|
||||
});
|
||||
});
|
||||
gulp.task('nonfavicons-images', function (cb) {
|
||||
pump([gulp.src(paths.images_files),
|
||||
imagemin(),
|
||||
gulp.dest(paths.buildImages)],
|
||||
cb)
|
||||
})
|
||||
|
||||
// Browser sync server for live reload
|
||||
gulp.task('browserSync', function() {
|
||||
browserSync.init(
|
||||
[paths.css + "/*.css", paths.js + "*.js", paths.templates + '*.html'], {
|
||||
proxy: "localhost:8000"
|
||||
});
|
||||
});
|
||||
gulp.task('images', function () {
|
||||
runSequence(['favicons-images', 'nonfavicons-images'])
|
||||
})
|
||||
// endregion
|
||||
|
||||
// Watch
|
||||
gulp.task('watch', function() {
|
||||
// region scripts
|
||||
gulp.task('js-scripts', function (cb) {
|
||||
pump([gulp.src(paths.scriptsJs_files),
|
||||
concat(paths.build_scriptsFileName),
|
||||
uglify(),
|
||||
rename({suffix: '.min'}),
|
||||
gulp.dest(paths.build)],
|
||||
cb)
|
||||
})
|
||||
|
||||
gulp.watch(paths.sass + '/*.scss', ['styles']);
|
||||
gulp.watch(paths.js + '/*.js', ['scripts']).on("change", reload);
|
||||
gulp.watch(paths.images + '/*', ['imgCompression']);
|
||||
gulp.watch(paths.templates + '/**/*.html').on("change", reload);
|
||||
gulp.task('scripts', function () {
|
||||
runSequence('js-scripts')
|
||||
})
|
||||
// endregion
|
||||
|
||||
});
|
||||
// region styles
|
||||
gulp.task('sass-styles', function (cb) {
|
||||
pump([gulp.src(paths.stylesSass_files),
|
||||
sass(),
|
||||
gulp.dest(paths.stylesCss)],
|
||||
cb
|
||||
)
|
||||
})
|
||||
|
||||
// Default task
|
||||
gulp.task('default', function() {
|
||||
runSequence(['styles', 'scripts', 'imgCompression'], 'runServer', 'browserSync', 'watch');
|
||||
});
|
||||
gulp.task('css-styles', function (cb) {
|
||||
pump([gulp.src(paths.stylesCss_files),
|
||||
concat(paths.build_stylesFileName),
|
||||
autoprefixer({browsers: ['last 2 versions']}),
|
||||
pixrem(),
|
||||
cleanCSS({rebaseTo: '../../'}),
|
||||
rename({suffix: '.min'}),
|
||||
gulp.dest(paths.build)],
|
||||
cb)
|
||||
})
|
||||
|
||||
gulp.task('styles', function () {
|
||||
runSequence('sass-styles', 'css-styles')
|
||||
})
|
||||
// endregion
|
||||
|
||||
// region manage.py
|
||||
gulp.task('migrate', function (cb) {
|
||||
const cmd = spawn('python', ['manage.py', 'migrate'], {stdio: 'inherit'})
|
||||
cmd.on(close, function (code) {
|
||||
console.log('runServerPlus exited with code ' + code)
|
||||
cb(code)
|
||||
})
|
||||
})
|
||||
|
||||
gulp.task('runServerPlus', function (cb) {
|
||||
const cmd = spawn('python', ['manage.py', 'runserver_plus'], {stdio: 'inherit'})
|
||||
cmd.on(close, function (code) {
|
||||
console.log('runServerPlus exited with code ' + code)
|
||||
cb(code)
|
||||
})
|
||||
})
|
||||
// endregion
|
||||
|
||||
gulp.task('browserSync', function () {
|
||||
browserSync.init(
|
||||
[paths.images_files, paths.scriptsJs_files, paths.stylesCss_files, paths.templates_files], {
|
||||
proxy: 'localhost:8000'
|
||||
})
|
||||
})
|
||||
|
||||
gulp.task('build', function () {
|
||||
runSequence(['images', 'scripts', 'styles'])
|
||||
})
|
||||
|
||||
gulp.task('clean-build', function (cb) {
|
||||
pump([gulp.src(paths.build),
|
||||
clean()],
|
||||
cb)
|
||||
})
|
||||
|
||||
gulp.task('default', function () {
|
||||
runSequence('build', 'runServerPlus', 'browserSync')
|
||||
})
|
||||
|
||||
gulp.task('default-migrate', function () {
|
||||
runSequence('build', 'migrate', 'runServerPlus', 'browserSync')
|
||||
})
|
||||
|
||||
gulp.task('watch', ['default'], function () {
|
||||
gulp.watch(paths.images_files, ['images'])
|
||||
gulp.watch(paths.scriptsJs_files, ['js-scripts']).on('change', reload)
|
||||
gulp.watch(paths.stylesSass_files, ['sass-styles'])
|
||||
gulp.watch(paths.stylesCss_files, ['css-styles'])
|
||||
gulp.watch(paths.templates_files).on('change', reload)
|
||||
})
|
||||
|
|
|
@ -16,22 +16,28 @@
|
|||
"pixrem": "~1.3.1",
|
||||
"time-grunt": "~1.2.1"
|
||||
{% elif cookiecutter.js_task_runner == 'Gulp' %}
|
||||
"browser-sync": "^2.14.0",
|
||||
"del": "^2.2.2",
|
||||
"browser-sync": "^2.18.8",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^3.1.1",
|
||||
"gulp-cssnano": "^2.1.2",
|
||||
"gulp-imagemin": "^3.0.3",
|
||||
"gulp-clean": "^0.3.2",
|
||||
"gulp-clean-css": "^3.0.4",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-imagemin": "^3.1.1",
|
||||
"gulp-pixrem": "^1.0.0",
|
||||
"gulp-plumber": "^1.1.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sass": "^2.3.2",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-util": "^3.0.7",
|
||||
"run-sequence": "^1.2.2"
|
||||
"gulp-sass": "^3.1.0",
|
||||
"gulp-uglify": "^2.1.2",
|
||||
"npm-check-updates": "^2.10.3",
|
||||
"pump": "^1.0.2",
|
||||
"run-sequence": "^1.2.2",
|
||||
"standard": "^9.0.2",
|
||||
"npm-check": "^5.4.0"
|
||||
{% endif %}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/* These styles are generated from project.scss. */
|
||||
|
||||
.alert-debug {
|
||||
color: black;
|
||||
background-color: white;
|
||||
border-color: #d6e9c6;
|
||||
}
|
||||
|
||||
.alert-error {
|
||||
color: #b94a48;
|
||||
background-color: #f2dede;
|
||||
border-color: #eed3d7;
|
||||
}
|
||||
|
||||
/* This is a fix for the bootstrap4 alpha release */
|
||||
@media (max-width: 47.9em) {
|
||||
.navbar-nav .nav-item {
|
||||
float: none;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.navbar-nav .nav-item + .nav-item {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.nav.navbar-nav.pull-xs-right {
|
||||
float: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Display django-debug-toolbar.
|
||||
See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742
|
||||
and https://github.com/pydanny/cookiecutter-django/issues/317
|
||||
*/
|
||||
[hidden][style="display: block;"] {
|
||||
display: block !important;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/* Project specific Javascript goes here. */
|
||||
|
||||
/*
|
||||
Formatting hack to get around crispy-forms unfortunate hardcoding
|
||||
in helpers.FormHelper:
|
||||
|
||||
if template_pack == 'bootstrap4':
|
||||
grid_colum_matcher = re.compile('\w*col-(xs|sm|md|lg|xl)-\d+\w*')
|
||||
using_grid_layout = (grid_colum_matcher.match(self.label_class) or
|
||||
grid_colum_matcher.match(self.field_class))
|
||||
if using_grid_layout:
|
||||
items['using_grid_layout'] = True
|
||||
|
||||
Issues with the above approach:
|
||||
|
||||
1. Fragile: Assumes Bootstrap 4's API doesn't change (it does)
|
||||
2. Unforgiving: Doesn't allow for any variation in template design
|
||||
3. Really Unforgiving: No way to override this behavior
|
||||
4. Undocumented: No mention in the documentation, or it's too hard for me to find
|
||||
*/
|
||||
$('.form-group').removeClass('row');
|
|
@ -0,0 +1,21 @@
|
|||
/* Project specific Javascript goes here. */
|
||||
|
||||
/*
|
||||
Formatting hack to get around crispy-forms unfortunate hardcoding
|
||||
in helpers.FormHelper:
|
||||
|
||||
if template_pack == 'bootstrap4':
|
||||
grid_colum_matcher = re.compile('\w*col-(xs|sm|md|lg|xl)-\d+\w*')
|
||||
using_grid_layout = (grid_colum_matcher.match(self.label_class) or
|
||||
grid_colum_matcher.match(self.field_class))
|
||||
if using_grid_layout:
|
||||
items['using_grid_layout'] = True
|
||||
|
||||
Issues with the above approach:
|
||||
|
||||
1. Fragile: Assumes Bootstrap 4's API doesn't change (it does)
|
||||
2. Unforgiving: Doesn't allow for any variation in template design
|
||||
3. Really Unforgiving: No way to override this behavior
|
||||
4. Undocumented: No mention in the documentation, or it's too hard for me to find
|
||||
*/
|
||||
$('.form-group').removeClass('row')
|
|
@ -0,0 +1,26 @@
|
|||
.alert-debug {
|
||||
background-color: #fff;
|
||||
border-color: #d6e9c6;
|
||||
color: #000; }
|
||||
|
||||
.alert-error {
|
||||
background-color: #f2dede;
|
||||
border-color: #eed3d7;
|
||||
color: #b94a48; }
|
||||
|
||||
.navbar {
|
||||
border-radius: 0px; }
|
||||
|
||||
@media (max-width: 47.9em) {
|
||||
.navbar-nav .nav-item {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
width: 100%; }
|
||||
.navbar-nav .nav-item + .nav-item {
|
||||
margin-left: 0; }
|
||||
.nav.navbar-nav.pull-xs-right {
|
||||
float: none !important; } }
|
||||
|
||||
[hidden][style="display: block;"] {
|
||||
display: block !important; }
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
// project specific CSS goes here
|
||||
|
||||
////////////////////////////////
|
||||
//Variables//
|
||||
//Variables//
|
||||
////////////////////////////////
|
||||
|
||||
// Alert colors
|
||||
|
@ -15,7 +14,7 @@ $dark-pink: #eed3d7;
|
|||
$red: #b94a48;
|
||||
|
||||
////////////////////////////////
|
||||
//Alerts//
|
||||
//Alerts//
|
||||
////////////////////////////////
|
||||
|
||||
// bootstrap alert CSS, translated to the django-standard levels of
|
||||
|
@ -34,7 +33,7 @@ $red: #b94a48;
|
|||
}
|
||||
|
||||
////////////////////////////////
|
||||
//Navbar//
|
||||
//Navbar//
|
||||
////////////////////////////////
|
||||
|
||||
// This is a fix for the bootstrap4 alpha release
|
||||
|
@ -60,7 +59,7 @@ $red: #b94a48;
|
|||
}
|
||||
|
||||
////////////////////////////////
|
||||
//Django Toolbar//
|
||||
//Django Toolbar//
|
||||
////////////////////////////////
|
||||
|
||||
// Display django-debug-toolbar.
|
|
@ -20,7 +20,7 @@
|
|||
<!-- Your stuff: Third-party CSS libraries go here -->
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %}
|
||||
<!-- This file stores project-specific CSS -->
|
||||
<link href="{% static 'css/project.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'build/styles.min.css' %}" rel="stylesheet"/>
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -98,7 +98,7 @@
|
|||
|
||||
<!-- place project specific Javascript in this file -->
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %}
|
||||
<script src="{% static 'js/project.js' %}"></script>
|
||||
<script src="{% static 'build/scripts.min.js' %}"></script>
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}
|
||||
|
||||
{% endblock javascript %}
|
||||
|
|
Loading…
Reference in New Issue
Block a user