# Nunjucks ships three runtime dependencies and forty dev ones

> Nunjucks is Mozilla's Jinja-inspired template engine for JavaScript, with inheritance and asynchronous control. Its runtime dependency list is three packages long, while its development list still includes a PhantomJS test runner and beta-era Babel pins.

**mozilla/nunjucks** — A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)

- Repository: https://github.com/mozilla/nunjucks
- Website: https://mozilla.github.io/nunjucks/
- Stars: 9,001 · Forks: 663
- Language: JavaScript
- License: BSD-2-Clause
- Published: 2026-10-12 · Updated: 2026-10-12 · Language: en
- Canonical page: https://hysenlabs.com/projects/mozilla-nunjucks

## Three runtime dependencies and what each one is for

The dependency list is the fastest way to understand the design. Runtime dependencies are three packages and nothing else: a-sync-waterfall at ^1.0.0, asap at ^2.0.3 and commander at ^5.1.0. No parser generator, no compiler framework, no class of anything that has to be configured, which is consistent with a template engine that interprets at render time rather than building ahead of time. Commander is the argument parser for the command line tool and is the one dependency a browser build never touches, which is part of why the browser entry point can be a standalone bundle. What the engine itself runs on is two small libraries, and what they do is the subject of the next section.

## Two small libraries carry the asynchronous control story

The description in the manifest calls Nunjucks a templating engine with inheritance, asynchronous control and more, and the two non-CLI dependencies are where the asynchronous part lives. a-sync-waterfall is the library that turns a list of asynchronous functions into a chain where each one receives the previous result, which is exactly the shape a template engine needs when a filter can return a promise. asap is the promise scheduler, which lets work be written as a straightforward sequence without relying on native async ordering to behave predictably across environments. The combination is what allows a template to call a filter that performs I/O, such as reading a file or calling a service, and still render deterministically. That capability is the difference between this engine and a synchronous string-substitution one, and it is also the thing that most affects how you structure your templates: an async filter turns rendering into an operation that can wait, so a template that looks like a function call can take time.

## The dev toolchain still carries a PhantomJS runner

The development dependencies tell a different story from the runtime ones, and they are worth reading before you contribute. The test stack includes mocha with a constraint of less than 8.x, expect.js, supertest, and mocha-phantomjs-core alongside phantomjs-prebuilt and mocha-phantomjs-istanbul. That is a headless browser from an era when the browser test runner of choice was a downloadable binary, and it is still the shape of the suite in the manifest. Alongside it sit two uglify packages, uglify-js at ^2.8.29 and terser-webpack-plugin, and a webpack at ^5.99.9, so the build has both a current and a legacy minifier. Babel is pinned to ^7.0.0-beta.38 across @babel/cli, @babel/core, @babel/preset-env and @babel/register, which is a beta-era pin rather than a released version. None of this affects anyone installing the package, and all of it tells you that maintaining this repository is a different task from using it.

## Chokidar is an optional extra for the file watcher

Installation is one command, and there is a second one with a reason:

```bash
npm install nunjucks
```

The file watcher built into Nunjucks requires Chokidar to be installed separately, so using it means npm install nunjucks chokidar. That split is a deliberate choice rather than an oversight: a watcher is only useful in development, and every production deployment that installed it would be carrying a filesystem-watching library for a code path it never runs. The same reasoning applies to the rest of the dependency list, which is why the runtime set is so short. The version history lives in the CHANGELOG, and the README links it to the releases page on GitHub rather than to a file in the tree, which is worth knowing if you are trying to work out when a behavior changed.

## A browser field points at a prebuilt bundle

package.json declares a browser field set to ./browser/nunjucks.js, which tells bundlers to substitute that file when resolving the package in a browser build. That is the older of the two conventions and the one that still works with webpack and its successors without configuration, and it means the browser entry point is a built artifact checked into the package rather than something the consumer builds. The repository carries bower.json as well, which is a second legacy package manifest format, and a .babelrc alongside the babel configuration in the manifest. The effect for a modern consumer is that npm install nunjucks gives you a package that works with a bundler without extra configuration, while the repository itself still carries the scaffolding of several older toolchains. The samples directory holds a single entry, samples/express, which is the reference integration for the case most people actually want.

## Docs are a folder in the repository, published to GitHub Pages

Documentation source lives in /docs and publishes to https://mozilla.github.io/nunjucks/. Keeping it in the repository rather than in a separate site repository means documentation changes go through the same review as code and are versioned with the branch, which for a template engine matters because syntax documentation and behavior documentation drift apart quickly. The site is the project's canonical documentation link, and it is where the engine's feature set is described in full: inheritance, asynchronous control, and the Jinja2 lineage that the project states as its inspiration. Browser support is stated simply as all modern browsers, with IE8 supported through es5-shim rather than by the engine itself. That is the whole compatibility story in one sentence, and it is a meaningful constraint for anyone still targeting older browsers.

## Where Nunjucks is the wrong choice

Four cases. The first is a project that wants compile-time templates. Nunjucks interprets templates at render time, which is the right trade for a server rendering HTML and the wrong one for a build step that would rather produce static files once. The second is a browser-first project that already has a framework template layer. If your application is built around a component framework's own templating, adding a second engine means two rendering models, two escaping conventions and two places to look when output is wrong. The third is anyone who wants to contribute a change to the test infrastructure. The manifest still describes a PhantomJS-based runner, so modernizing the suite is a project in itself rather than a pull request. The fourth is a long-lived dependency with no appetite for that work. The newest published build is v3.2.4 from 2023-04-19, following v3.2.3 in June 2022 and v3.2.2 in July 2020, while the last push to master was on 2026-10-03, so commits are landing well after the last published version and you should decide deliberately whether to pin a published version or track the branch.

## Conclusion

Nunjucks suits a Node project that wants Jinja-style templates with inheritance and asynchronous filters, and wants a template engine with no transpiler in the request path. It does not suit a browser-first project that has already standardized on a framework template layer, nor anyone planning to modernize the test runner for them. Before adopting, run npm install nunjucks, install chokidar separately if you want the file watcher, and read samples/express to see the server-side integration shape in one directory.

## FAQ

### How do I install Nunjucks?

Run npm install nunjucks. If you want the file watcher, install Chokidar separately with npm install nunjucks chokidar, since the watcher is not a runtime dependency.

### What are Nunjucks' runtime dependencies?

Three: a-sync-waterfall at ^1.0.0, asap at ^2.0.3 and commander at ^5.1.0. Commander is for the command line tool, while the waterfall library is how asynchronous filters are chained.

### Does Nunjucks work in the browser?

The package.json browser field points to ./browser/nunjucks.js, so bundlers substitute a prebuilt browser bundle automatically. Browser support is stated as all modern browsers, with IE8 supported through es5-shim.

### Which JavaScript engines does Nunjucks target?

The README says all modern browsers, and the dev dependencies include a browserify-era node-libs-browser and Babel 7 beta pins. The shipped package needs no transpiler at request time because it ships a built browser bundle.

### How do I run the Nunjucks tests?

Run npm test. The dev dependencies show mocha constrained to less than 8.x, expect.js, supertest, and a PhantomJS-based runner, with coverage through nyc and babel-plugin-istanbul.

## Sources

- [License: BSD-2-Clause](https://github.com/mozilla/nunjucks/blob/master/LICENSE)
- [mozilla/nunjucks on GitHub](https://github.com/mozilla/nunjucks)
- [Project website](https://mozilla.github.io/nunjucks/)
- [README](https://github.com/mozilla/nunjucks/blob/master/README.md)
- [Releases](https://github.com/mozilla/nunjucks/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mozilla-nunjucks
