From 4b06fe3958ddae837100bcdcab001b6405a202fd Mon Sep 17 00:00:00 2001 From: Shupeyko Nikita Date: Tue, 20 Jun 2017 22:48:17 +0300 Subject: [PATCH] =?UTF-8?q?Node.JS=20+=20docker-compose=20=3D=20=E2=99=A5?= =?UTF-8?q?=20(#1128)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Introduce static asset build infrastructure * Enhance gulpfile.js * Introduce node service * BrowserSync debug-only support * Remove newline before BrowserSync debug-only support section * FIx node Dockerfile package.json COPY * Try fiixing node Dockerfile package.json COPY ones again * Switch to `node:7-slim` * Try switching to node:6 To account for possible node:7 docker-compose incompatibiltiy * Revert "Try switching to node:6" This reverts commit 62cc02df1a24d1f25c8b48b5c4126d17f2049144. * Try switcging workdir to /app * Try utilizing relative package.json path * Resetting to the last version working locally with docker-compose 1.11.x * Build upon the latest node:7.9-slim * Stop dockerignoring package.json * Fix typo * Try a different package.json path * Revert "Try a different package.json path" This reverts commit f29f8500b8fde04ae5e8e46256b86ab910cedcca. * Revert "Fix typo" This reverts commit 02033729b51a3fbc9839dac5e9731bf4b541a60c. * Revert "Stop dockerignoring package.json" This reverts commit 63c5491546d3694bfb659b2a17d7cee6365227c6. * Upgrade docker-engine and docker-compose used by Travis CI * Fix .travis.yml comments * Inline docker-engine and docker-compose versions * DEBUG: pwd * Revert "DEBUG: pwd " This reverts commit 6c2ed4321a346a384289c4a0a54576e0010c98f1. * Try copying package.json to the same dir as node Dockerfile's * Revert "Try copying package.json to the same dir as node Dockerfile's" This reverts commit 24340a0783143108cabbb508f1b0d1202fc0d76d. * Try out node:7.9 * Revert "Try out node:7.9" This reverts commit 32286d33c2dc535fe7e20cd6342b1627f1ebf58f. * Revert "Upgrade docker-engine and docker-compose used by Travis CI" * Get rid of npm-check-updates Reason: Reserved for the upcoming PR * Get rid of npm-check Reason: Reserved for the upcoming PR * Get rid of 'standard' npm package Reason: Reserved for the upcoming PR * Clean up package.json * Preserve package.json uncoditionally Since we now have *unconditional* node.js integration, `package.json` must be out there whenever `node` service gets built * Upgrade node service image to 7.10 * Document Node.js-Docker integration * Fix gulpfile.js images region name * Get rid of Gulp migrate task * Document Gulp-Docker integration * Introduce static asset build infrastructure * Enhance gulpfile.js * Introduce node service * BrowserSync debug-only support * Remove newline before BrowserSync debug-only support section * FIx node Dockerfile package.json COPY * Try fiixing node Dockerfile package.json COPY ones again * Switch to `node:7-slim` * Try switching to node:6 To account for possible node:7 docker-compose incompatibiltiy * Revert "Try switching to node:6" This reverts commit 62cc02df1a24d1f25c8b48b5c4126d17f2049144. * Try switcging workdir to /app * Try utilizing relative package.json path * Resetting to the last version working locally with docker-compose 1.11.x * Build upon the latest node:7.9-slim * Stop dockerignoring package.json * Revert "Stop dockerignoring package.json" This reverts commit 63c5491546d3694bfb659b2a17d7cee6365227c6. * Fix typo * Revert "Fix typo" This reverts commit 02033729b51a3fbc9839dac5e9731bf4b541a60c. * Try a different package.json path * Revert "Try a different package.json path" This reverts commit f29f8500b8fde04ae5e8e46256b86ab910cedcca. * Upgrade docker-engine and docker-compose used by Travis CI * Fix .travis.yml comments * Inline docker-engine and docker-compose versions * DEBUG: pwd * Revert "DEBUG: pwd " This reverts commit 6c2ed4321a346a384289c4a0a54576e0010c98f1. * Try copying package.json to the same dir as node Dockerfile's * Revert "Try copying package.json to the same dir as node Dockerfile's" This reverts commit 24340a0783143108cabbb508f1b0d1202fc0d76d. * Try out node:7.9 * Revert "Try out node:7.9" This reverts commit 32286d33c2dc535fe7e20cd6342b1627f1ebf58f. * Revert "Upgrade docker-engine and docker-compose used by Travis CI" * Get rid of npm-check-updates Reason: Reserved for the upcoming PR * Get rid of npm-check Reason: Reserved for the upcoming PR * Get rid of 'standard' npm package Reason: Reserved for the upcoming PR * Clean up package.json * Preserve package.json uncoditionally Since we now have *unconditional* node.js integration, `package.json` must be out there whenever `node` service gets built * Upgrade node service image to 7.10 * Document Node.js-Docker integration * Fix gulpfile.js images region name * Get rid of Gulp migrate task * Document Gulp-Docker integration * Remove Gulp-Docker integraton not supported initialization message --- docs/developing-locally-docker.rst | 8 + docs/gulp-with-docker.rst | 76 +++++++ docs/index.rst | 2 + docs/nodejs-with-docker.rst | 45 ++++ hooks/post_gen_project.py | 8 +- {{cookiecutter.project_slug}}/.gitignore | 1 + .../compose/node/Dockerfile-dev | 11 + .../config/settings/base.py | 3 +- {{cookiecutter.project_slug}}/dev.yml | 17 ++ {{cookiecutter.project_slug}}/gulpfile.js | 212 ++++++++++-------- {{cookiecutter.project_slug}}/package.json | 16 +- .../static/.gitkeep | 0 .../static/css/project.css | 38 ---- .../static/images/.gitkeep | 0 .../static/js/project.js | 21 -- .../static/scripts/.gitkeep | 0 .../static/scripts/js/project.js | 21 ++ .../static/styles/.gitkeep | 0 .../static/styles/css/project.css | 26 +++ .../static/styles/sass/project.scss | 71 ++++++ .../templates/base.html | 11 +- 21 files changed, 423 insertions(+), 164 deletions(-) create mode 100644 docs/gulp-with-docker.rst create mode 100644 docs/nodejs-with-docker.rst create mode 100644 {{cookiecutter.project_slug}}/compose/node/Dockerfile-dev create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/.gitkeep delete mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/css/project.css create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/images/.gitkeep delete mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/scripts/.gitkeep create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/scripts/js/project.js create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/.gitkeep create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/css/project.css create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/sass/project.scss diff --git a/docs/developing-locally-docker.rst b/docs/developing-locally-docker.rst index 140f9950..46ee887a 100644 --- a/docs/developing-locally-docker.rst +++ b/docs/developing-locally-docker.rst @@ -6,6 +6,8 @@ Getting Up and Running Locally With Docker The steps below will get you up and running with a local development environment. All of these commands assume you are in the root of your generated project. +.. _devlocdocker-prereq: + Prerequisites ------------- @@ -30,6 +32,9 @@ Currently PostgreSQL (``psycopg2`` python package) is not installed inside Docke Doing this will prevent the project from being installed in an Windows-only environment (thus without usage of Docker). If you want to use this project without Docker, make sure to remove ``psycopg2`` from the requirements again. + +.. _devlocdocker-build-the-stack: + Build the Stack --------------- @@ -40,6 +45,9 @@ on your development system:: If you want to build the production environment you don't have to pass an argument -f, it will automatically use docker-compose.yml. + +.. _devlocdocker-boot-the-system: + Boot the System --------------- diff --git a/docs/gulp-with-docker.rst b/docs/gulp-with-docker.rst new file mode 100644 index 00000000..1e9b2a18 --- /dev/null +++ b/docs/gulp-with-docker.rst @@ -0,0 +1,76 @@ +Gulp with Docker +================ + +.. index:: gulp, gulpjs, gulpfile, gulpfilejs, docker, docker-compose + +`Gulp`_ support is provided out-of-the-box, ready for use as-is, or with any kind of customizations suiting the specific needs of the project. + +.. _`Gulp`: http://gulpjs.com/ + +*All paths are relative to the generated project's root.* + + +Prerequisites +------------- + +- These :ref:`nodewithdocker-prereq` are satisfied. + + +Overview +-------- + +:ref:`nodewithdocker-overview` Node.js integration details first to get the whole picture. + +Essential aspects of Gulp integration are + +- :code:`./gulpfile.js` with Gulp tasks defined; +- :code:`./{{ cookiecutter.project_slug }}/static/build/` (build directory) with static assets built via Gulp. + +Let us take a closer look at :code:`./gulpfile.js`: + +- paths to static assets are provided by :code:`pathsConfig()`; +- for clarity, related tasks are grouped by :code:`region`: + - :code:`images`: + - :code:`images`: run image-related tasks in parallel, namely: + - :code:`favicons-images`: process favicon images only; + - :code:`nonfavicons-images`: process all images except for favicons. + - :code:`scripts`: + - :code:`scripts`: run script-related tasks in sequence, namely: + - :code:`js-scripts`: process js scripts. + - :code:`styles`: + - :code:`styles`: run script-related tasks in sequence, namely: + - :code:`sass-styles`: process SCSS styles; + - :code:`css-styles`: process CSS styles. + - :code:`build`: + - :code:`build`: run :code:`images`, :code:`scripts`, and :code:`styles` in parallel; + - :code:`clean-build`: clean up build directory: +- the :code:`default` task runs the following ones in sequence: + - :code:`build`; + - :code:`init-browserSync`: initialize `BrowserSync`_; + - :code:`watch`: watch static asset files/directories changes, running BrowserSync on any changes. + +.. _`BrowserSync`: https://www.browsersync.io/ + + +Workflow +-------- + +#. [*skip if done*] :ref:`devlocdocker-build-the-stack`; +#. :ref:`devlocdocker-boot-the-system`. + +By default, :code:`gulp` command gets executed immediately after :code:`node` +container startup (see :code:`./dev.yml` for details) which in turn invokes +the :code:`default` task, so generally one would not need to run any +of the aforementioned tasks manually. However, should the need arise, +oftentimes just a few of the tasks listed above will be used to, for instance, +straightforwardly :code:`build` all assets + +.. code-block:: bash + + $ docker-compose -f dev.yml exec node gulp build + +or build :code:`scripts` selectively + +.. code-block:: bash + + $ docker-compose -f dev.yml exec node gulp scripts diff --git a/docs/index.rst b/docs/index.rst index bfa88f18..e707365b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,6 +17,8 @@ Contents: developing-locally-docker settings linters + nodejs-with-docker + gulp-with-docker live-reloading-and-sass-compilation deployment-on-pythonanywhere deployment-on-heroku diff --git a/docs/nodejs-with-docker.rst b/docs/nodejs-with-docker.rst new file mode 100644 index 00000000..468c5408 --- /dev/null +++ b/docs/nodejs-with-docker.rst @@ -0,0 +1,45 @@ +Node.js with Docker +=================== + +.. index:: node, nodejs, docker, docker-compose + +`Node.js`_ support is provided out-of-the-box, ready for use as-is, or with any kind of customizations suiting the specific needs of the project. + +.. _`Node.js`: https://nodejs.org/en/ + +*All paths are relative to the generated project's root.* + + +.. _nodewithdocker-prereq: + +Prerequisites +------------- + +- The project was generated with :code:`use_docker` set to :code:`y`. +- These :ref:`devlocdocker-prereq` are met as well. + + +.. _nodewithdocker-overview: + +Overview +-------- + +Essential aspects of Node.js integration are + +- node docker-compose service (:code:`node`) definition in :code:`./dev.yml`; +- :code:`./compose/node/Dockerfile-dev` defining the :code:`node` image; +- :code:`./node_modules/` 'overlayed' with :code:`/app/node_modules/`, its counterpart from the running instance of :code:`node`. + + +Workflow +-------- + +#. [*skip if done*] :ref:`devlocdocker-build-the-stack`: + - when building :code:`node` image from scratch, dependencies from :code:`package.json` are installed. +#. :ref:`devlocdocker-boot-the-system`. + +To log the running :code:`node` container's activity, + +.. code-block:: bash + + $ docker-compose -f dev.yml logs node diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 5e1eff9b..c005d9e7 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -256,7 +256,6 @@ elif '{{ cookiecutter.js_task_runner}}'.lower() == 'grunt': else: remove_gulp_files() remove_grunt_files() - remove_packageJSON_file() # 7. Removes all certbot/letsencrypt files if it isn't going to be used if '{{ cookiecutter.use_lets_encrypt }}'.lower() != 'y': @@ -264,11 +263,10 @@ if '{{ cookiecutter.use_lets_encrypt }}'.lower() != 'y': # 8. Display a warning if use_docker and use_grunt are selected. Grunt isn't # supported by our docker config atm. -if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cookiecutter.use_docker }}'.lower() == 'y': +if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt'] and '{{ cookiecutter.use_docker }}'.lower() == 'y': print( - "You selected to use docker and a JS task runner. This is NOT supported out of the box for now. You " - "can continue to use the project like you normally would, but you will need to add a " - "js task runner service to your docker configuration manually." + "You selected to use Docker and Grunt task runner. This is NOT supported out of the box for now. You " + "can continue to use the project like you normally would, but you will need to setup Grunt manually." ) # 9. Removes the certbot/letsencrypt files and display a warning if use_lets_encrypt is selected and use_docker isn't. diff --git a/{{cookiecutter.project_slug}}/.gitignore b/{{cookiecutter.project_slug}}/.gitignore index 6a0a3029..710ba625 100644 --- a/{{cookiecutter.project_slug}}/.gitignore +++ b/{{cookiecutter.project_slug}}/.gitignore @@ -79,3 +79,4 @@ staticfiles/ .cache/ +{{ cookiecutter.project_slug }}/static/build/ diff --git a/{{cookiecutter.project_slug}}/compose/node/Dockerfile-dev b/{{cookiecutter.project_slug}}/compose/node/Dockerfile-dev new file mode 100644 index 00000000..e53fb504 --- /dev/null +++ b/{{cookiecutter.project_slug}}/compose/node/Dockerfile-dev @@ -0,0 +1,11 @@ +FROM node:7.10-slim + +RUN mkdir -p /app + +COPY ./package.json /app + +WORKDIR /app + +RUN npm install && npm cache clean + +ENV PATH ./node_modules/.bin/:$PATH diff --git a/{{cookiecutter.project_slug}}/config/settings/base.py b/{{cookiecutter.project_slug}}/config/settings/base.py index 274e2806..5b07086d 100644 --- a/{{cookiecutter.project_slug}}/config/settings/base.py +++ b/{{cookiecutter.project_slug}}/config/settings/base.py @@ -184,9 +184,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 diff --git a/{{cookiecutter.project_slug}}/dev.yml b/{{cookiecutter.project_slug}}/dev.yml index 122dea44..7a2d06eb 100644 --- a/{{cookiecutter.project_slug}}/dev.yml +++ b/{{cookiecutter.project_slug}}/dev.yml @@ -21,6 +21,7 @@ services: depends_on: - postgres{% if cookiecutter.use_mailhog == 'y' %} - mailhog{% endif %} + - node environment: - POSTGRES_USER={{cookiecutter.project_slug}} - USE_DOCKER=yes @@ -48,3 +49,19 @@ services: ports: - "8025:8025" {% endif %} + + node: + build: + context: . + dockerfile: ./compose/node/Dockerfile-dev + volumes: + - .:/app + # http://jdlm.info/articles/2016/03/06/lessons-building-node-app-docker.html + - /app/node_modules + command: "gulp" + ports: + # BrowserSync port. + - "3000:3000" + # BrowserSync UI port. + - "3001:3001" + diff --git a/{{cookiecutter.project_slug}}/gulpfile.js b/{{cookiecutter.project_slug}}/gulpfile.js index b67a7bee..f3278afe 100644 --- a/{{cookiecutter.project_slug}}/gulpfile.js +++ b/{{cookiecutter.project_slug}}/gulpfile.js @@ -1,105 +1,139 @@ +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 pathsConfig = function (appName) { + this.paths = {} -//////////////////////////////// - //Setup// -//////////////////////////////// + this.paths['app'] = './' + (appName || pjson.name) -// 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'), - spawn = require('child_process').spawn, - runSequence = require('run-sequence'), - browserSync = require('browser-sync').create(), - reload = browserSync.reload; + this.paths['static'] = this.paths['app'] + '/static' + this.paths['build'] = this.paths['static'] + '/build' -// Relative paths function -var pathsConfig = function (appName) { - this.app = "./" + (appName || pjson.name); + 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'] + '/*' - 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['build_scriptsFileName'] = 'scripts.js' + this.paths['scripts'] = this.paths['static'] + '/scripts' + this.paths['scripts_files'] = this.paths['scripts'] + '/**/*' + this.paths['scriptsJs'] = this.paths['scripts'] + '/js' + this.paths['scriptsJs_files'] = this.paths['scriptsJs'] + '/*.js' -var paths = pathsConfig(); + this.paths['build_stylesFileName'] = 'styles.css' + this.paths['styles'] = this.paths['static'] + '/styles' + this.paths['styles_files'] = this.paths['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' -//////////////////////////////// - //Tasks// -//////////////////////////////// + this.paths['templates'] = this.paths['app'] + '/templates' + this.paths['templates_files'] = this.paths['templates'] + '/**/*.html' -// 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)); -}); + return this.paths +} +const paths = pathsConfig() -// 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)); -}); +// region images +gulp.task('favicons-images', function (cb) { + pump([gulp.src(paths.imagesFavicons_files), + gulp.dest(paths.buildImagesFavicons)], + cb) +}) -// 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)) -}); +gulp.task('nonfavicons-images', function (cb) { + pump([gulp.src(paths.images_files), + imagemin(), + gulp.dest(paths.buildImages)], + cb) +}) -// Run django server -gulp.task('runServer', function(cb) { - var cmd = spawn('python', ['manage.py', 'runserver'], {stdio: 'inherit'}); - cmd.on('close', function(code) { - console.log('runServer exited with code ' + code); - cb(code); - }); -}); +gulp.task('images', function () { + runSequence(['favicons-images', 'nonfavicons-images']) +}) +// endregion -// Browser sync server for live reload -gulp.task('browserSync', function() { - browserSync.init( - [paths.css + "/*.css", paths.js + "*.js", paths.templates + '*.html'], { - proxy: "localhost:8000" - }); -}); +// 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) +}) -// Watch -gulp.task('watch', function() { +gulp.task('scripts', function () { + runSequence('js-scripts') +}) +// endregion - 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); +// region styles +gulp.task('sass-styles', function (cb) { + pump([gulp.src(paths.stylesSass_files), + sass(), + gulp.dest(paths.stylesCss)], + cb + ) +}) -}); +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) +}) -// Default task -gulp.task('default', function() { - runSequence(['styles', 'scripts', 'imgCompression'], 'runServer', 'browserSync', 'watch'); -}); +gulp.task('styles', function () { + runSequence('sass-styles', 'css-styles') +}) +// endregion + +// region build +gulp.task('build', function () { + runSequence(['images', 'scripts', 'styles']) +}) + +gulp.task('clean-build', function (cb) { + pump([gulp.src(paths.build), + clean()], + cb) +}) +// endregion + +gulp.task('init-browserSync', function () { + browserSync.init({ + host: 'localhost:8000' + }) +}) + +gulp.task('watch', function () { + gulp.watch(paths.images_files, ['images']).on('change', browserSync.reload) + gulp.watch(paths.scripts_files, ['scripts']).on('change', browserSync.reload) + gulp.watch(paths.styles_files, ['styles']).on('change', browserSync.reload) + gulp.watch(paths.templates_files).on('change', browserSync.reload) +}) + +gulp.task('default', function () { + runSequence('build', 'init-browserSync', 'watch') +}) diff --git a/{{cookiecutter.project_slug}}/package.json b/{{cookiecutter.project_slug}}/package.json index 0c8af427..5a15270d 100644 --- a/{{cookiecutter.project_slug}}/package.json +++ b/{{cookiecutter.project_slug}}/package.json @@ -16,18 +16,18 @@ "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", + "gulp-sass": "^3.1.0", + "gulp-uglify": "^2.1.2", + "pump": "^1.0.2", "run-sequence": "^1.2.2" {% endif %} }, diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/.gitkeep b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/css/project.css b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/css/project.css deleted file mode 100644 index 5f23c427..00000000 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/css/project.css +++ /dev/null @@ -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; -} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/images/.gitkeep b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/images/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js deleted file mode 100644 index 91ab9e2d..00000000 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js +++ /dev/null @@ -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'); diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/scripts/.gitkeep b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/scripts/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/scripts/js/project.js b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/scripts/js/project.js new file mode 100644 index 00000000..36017799 --- /dev/null +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/scripts/js/project.js @@ -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') diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/.gitkeep b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/css/project.css b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/css/project.css new file mode 100644 index 00000000..6b20fb3d --- /dev/null +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/css/project.css @@ -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; } + diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/sass/project.scss b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/sass/project.scss new file mode 100644 index 00000000..cc30bfcb --- /dev/null +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/styles/sass/project.scss @@ -0,0 +1,71 @@ +// project specific CSS goes here + +//////////////////////////////// +//Variables// +//////////////////////////////// + +// Alert colors + +$white: #fff; +$mint-green: #d6e9c6; +$black: #000; +$pink: #f2dede; +$dark-pink: #eed3d7; +$red: #b94a48; + +//////////////////////////////// +//Alerts// +//////////////////////////////// + +// bootstrap alert CSS, translated to the django-standard levels of +// debug, info, success, warning, error + +.alert-debug { + background-color: $white; + border-color: $mint-green; + color: $black; +} + +.alert-error { + background-color: $pink; + border-color: $dark-pink; + color: $red; +} + +//////////////////////////////// +//Navbar// +//////////////////////////////// + +// This is a fix for the bootstrap4 alpha release + +.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; + } +} + +//////////////////////////////// +//Django Toolbar// +//////////////////////////////// + +// 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; +} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html index e947da5b..e49aaa21 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html @@ -20,7 +20,7 @@ {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %} - + {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %} {% endblock %} @@ -88,6 +88,13 @@ ================================================== --> {% block javascript %} + + {% if debug %} + + {% endif %} + @@ -97,7 +104,7 @@ {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %} - + {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %} {% endblock javascript %}