Skip to content

Latest commit

 

History

History
191 lines (149 loc) · 4.65 KB

nunjucks.md

File metadata and controls

191 lines (149 loc) · 4.65 KB

Setting up Nunjucks

This recipe shows how to set up Nunjucks to compile your templates, including LiveReload integration.

We assume your directory structure will look something like this:

webapp
└── app
    ├── about.njk
    ├── contact.njk
    ├── index.njk
    ├── includes
    │   ├── footer.njk
    │   └── header.njk
    └── layouts
        └── default.njk

If you had something different in mind, modify paths accordingly.

Steps

1. Install dependencies

Install gulp-nunjucks-render to render Nunjucks template language to HTML:

$ npm install --save-dev gulp-nunjucks-render

2. Modify app/index.html to create as app/layouts/default.njk layouts template

In app/index.html replace <div class="container"> and its content (cut, so you can paste later) with the following:

{% block content %}{% endblock %}

Now make it the default layout template:

$ mv app/index.html app/layouts/default.njk

3. Create new Nunjucks app/index.njk page to extend from app/layouts/default.njk

Create app/index.njk, where you can paste the <div class="container"> part from app/index.html:

{% extends "layouts/default.njk" %}

{% block content %}
  <div class="container">
    <!-- ... -->
  </div>
{% endblock %}

4. Create a views task

gulp.task('views', () => {
  return gulp.src('app/*.njk')
    .pipe($.nunjucksRender({
      path: 'app'
    }))
    .pipe(gulp.dest('.tmp'))
    .pipe(reload({stream: true}));
});

This compiles app/*.njk files into static .html files in the .tmp directory.

5. Create a 'views:reload' task

gulp.task('views:reload', ['views'], () => {
  reload();
});

This triggers Browsersync after views task is completed

6. Add views as a dependency of both html and serve

gulp.task('html', ['views', 'styles', 'scripts'], () => {
  // ...
});
gulp.task('serve', () => {
  runSequence(['clean', 'wiredep'], ['views', 'styles', 'scripts', 'fonts'], () => {
    // ...
  });
});

7. Configure html task to include files from .tmp

 gulp.task('html', ['styles', 'views', 'scripts'], () => {
-  return gulp.src('app/*.html')
+  return gulp.src(['app/*.html', '.tmp/*.html'])
     .pipe($.useref({searchPath: ['.tmp', 'app', '.']}))
     .pipe($.if('*.js', $.uglify()))
     .pipe($.if('*.css', $.cssnano({safe: true, autoprefixer: false})))
     .pipe($.if('*.html', $.htmlmin({collapseWhitespace: true})))
     .pipe(gulp.dest('dist'));
 });

8. Update extras

We don't want to copy over .njk files in the build process:

 gulp.task('extras', () => {
   return gulp.src([
     'app/*.*',
-    '!app/*.html'
+    '!app/*.html',
+    '!app/*.njk'
   ], {
     dot: true
   }).pipe(gulp.dest('dist'));
 });

9. Configure wiredep task to wire Bower components on layout templates only

Wiredep does not support .njk (yet), so also add in the file type definition.

  gulp.task('wiredep', () => {
    ...

-   gulp.src('app/*.html')
+   gulp.src('app/layouts/*.njk')
      .pipe(wiredep({
        exclude: ['bootstrap-sass'],
-       ignorePath: /^(\.\.\/)*\.\./
+       ignorePath: /^(\.\.\/)*\.\./,
+       fileTypes: {
+         njk: {
+           block: /(([ \t]*)<!--\s*bower:*(\S*)\s*-->)(\n|\r|.)*?(<!--\s*endbower\s*-->)/gi,
+           detect: {
+             js: /<script.*src=['"]([^'"]+)/gi,
+             css: /<link.*href=['"]([^'"]+)/gi
+           },
+           replace: {
+             js: '<script src="{{filePath}}"></script>',
+             css: '<link rel="stylesheet" href="{{filePath}}" />'
+           }
+         }
+       }
+     }))
-     .pipe(gulp.dest('app'));
+     .pipe(gulp.dest('app/layouts'));
  });

10. Edit your serve task

Edit your serve task so that editing .html and .njk files triggers the views:reload task:

  gulp.task('serve', ['views', 'styles', 'fonts'], () => {
    runSequence(['clean', 'wiredep'], ['views', 'styles', 'scripts', 'fonts'], () => {
      ...

    gulp.watch([
-     'app/*.html',
      'app/scripts/**/*.js',
      'app/images/**/*',
      '.tmp/fonts/**/*'
    ]).on('change', reload);
     
+     gulp.watch('app/**/*.{html,njk}', ['views:reload']);
      gulp.watch('app/styles/**/*.scss', ['styles']);
      gulp.watch('app/scripts/**/*.js', ['scripts']);
      gulp.watch('app/fonts/**/*', ['fonts']);
      gulp.watch('bower.json', ['wiredep', 'fonts']);
    });
  });

Notice we are still watching .html files in app because our templates have a different extension.