
Research
Security News
Malicious PyPI Package Exploits Deezer API for Coordinated Music Piracy
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
simple-nunjucks-loader
Advanced tools
This Webpack loader compiles Nunjucks templates.
html-webpack-plugin
compatible.
npm install --save-dev simple-nunjucks-loader
If you don't use dynamic assets in your code, then you could
save a bit on optional glob
dependency:
npm install --no-optional --save-dev simple-nunjucks-loader
By default Nunjucks wrap templates to global window.nunjucksPrecompiled
.
Loader didn't expose window.nunjucksPrecompiled
. If your code relied on
this object, it will definitely break. Use imports of required template
or adopt expose-loader
to your build pipeline.
This loader will precompile Nunjucks templates. It also includes Nunjunks (slim) runtime for browser.
Add loader to your webpack
config as follows:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [
{
loader: 'simple-nunjucks-loader',
options: {}
}
]
}
]
}
};
template-example.njk
<p>Hello, {{ username }}!</p>
app.js
import template from './template-example.njk'
document.body.innerHTML = template({
username: 'Mike'
})
Bundling of app.js
above will render paragraph with text "Hello, Mike!" to
the page.
html-webpack-plugin
For using with html-webpack-plugin
just add it to plugins
array, all options
from it would be available as htmlWebpackPlugin.options
in Nunjucks template.
webpack.config.js
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [
{
loader: 'simple-nunjucks-loader',
options: {}
}
]
}
]
},
plugins: [
new HTMLWebpackPlugin({
template: 'src/page.njk',
templateParameters: {
username: 'Joe'
}
})
]
};
src/page.njk
<p>Hello, {{ username }}!</p>
Refer to html-webpack-plugin
page for all
available options.
To load static assets (like images, for example), this loader inserts own
static
global function. It works like static
from Django/Jinja2 integration,
but resolves paths via Webpack loaders. It just replace calls
static('foo.jpeg')
with static(importedViaWebpackSymbol)
. static
itself
just returns loaded module or default
export of it.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [
{
loader: 'simple-nunjucks-loader',
options: {
assetsPaths: [
'app_example_a/static',
'app_example_b/static',
]
}
}
]
},
{
test: /\.png$/,
use: [{
loader: 'file-loader'
}]
}
]
}
};
template.njk
<img
src="{{ static('./image.png') }}"
alt=""
/>
The code above will replace {{ static('./image.png') }}
with hash, that
file-loader
returns.
Loader has limited support for dynamic assets. It was tested with expressions like:
{{ static('foo/' + bar) }}
{{ static('foo/' + bar + '.ext') }}
:warning: I advocate against using dynamic assets, because:
- I have to support hacky regular expressions :smile:
- It's hard to find usages of asset, because there is no import of it
- Final bundle could be bigger without proper maintaining
From my experience it's better to have some kind of map, that will match some variable to import:
{% set examplesMap = { 'example-1': static('foo/bar/dynamic-example-1.md'), 'example-2': static('foo/bar/dynamic-example-2.md') } %} {% for item in [1, 2] %} <p>{{ examplesMap['example-' + item] }}</p> {% endfor %}
By default Nunjunks bundle all precompiled templates to
window.nunjucksPrecompiled
, then loads them via custom loader from this
global object. If precompiled template reference some other template file,
it is loaded from disk (in NodeJS environment), or fetched via XMLHttpRequest
from internet.
Both are not webpack-way for projects bundling.
This loader workaround this behaviour by precompiling templates and dependant
templates as separate bundle chunks. It also use custom wrapper for precompiled
code to avoid creating window.nunjucksPrecompiled
.
It also adds each found template as dependency for template that need it, so bundle get rebuild in watch mode only when required.
When loader found async filter in template dependencies, it returns Promise
,
instead of render result.
Loader supports limited number of Nunjuncks options.
It's doesn't support watch
(we use webpack
own dependencies watch),
noCache
, web
settings and express
.
All other options get passed to Nunjunks Environment
during files loading.
Name | Type | Default | Description |
---|---|---|---|
jinjaCompat | {Boolean} | false | Install Jinja syntax support in bundle |
searchPaths | {String} or {Array.<string>} | . | One or more paths to resolve templates paths |
assetsPaths | {String} or {Array.<string>} | . | Paths to resolve static assets. Works like STATICFILES_DIRS . |
globals | Object.<string, string> | {} | Map global function to corresponding module |
extensions | Object.<string, string> | {} | Map extension to corresponding module |
filters | Object.<string, string> | {} | Map filters to corresponding module |
autoescape | {Boolean} | true | See Nunjuncks options for description of options below |
throwOnUndefined | {Boolean} | false | |
trimBlocks | {Boolean} | false | |
lstripBlocks | {Boolean} | false | |
tags | {Object.<string, string>} | Default Jinja tags config | Override tags syntax |
tags
default to:
{
blockStart: '{%',
blockEnd: '%}',
variableStart: '{{',
variableEnd: '}}',
commentStart: '{#',
commentEnd: '#}'
}
Installs Jinja syntax. This option install it for whole bundle.
Loader is searching for full template relative to given string(s) from
searchPath
option (or project root, if no paths given).
Path to file couldn't be outside of folders above.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [{
loader: 'simple-nunjucks-loader',
options: {
searchPaths: [
'django_app_a/templates',
'django_app_b/templates'
]
}
}]
}
]
}
};
List of paths where loader should search for assets.
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [{
loader: 'simple-nunjucks-loader',
options: {
assetsPaths: [
'django_app_a/static',
'django_app_b/static'
]
}
}]
}
]
}
};
Set global function and import path, that should return function to use.
It the same function that env.addGlobal
using.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [{
loader: 'simple-nunjucks-loader',
options: {
globals: {
_: 'lodash',
globalEnv: path.join(__dirname, 'app/global-env.js')
}
}
}]
}
]
}
};
app/global-env.js
export default function globalFn(foo, bar) {
return `Do anything with ${foo} and ${bar}`;
}
Set map of extensions that would be imported before each template render.
Extension should return instance, that would be added via
env.addExtension
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [{
loader: 'simple-nunjucks-loader',
options: {
extensions: {
CustomExtension: path.join(__dirname, 'lib/extensions/custom-extension.js')
}
}
}]
}
]
}
};
lib/extensions/custom-extension.js
// You should use slim bundle to make it work in browser
import nunjucks from 'nunjucks/browser/nunjucks-slim';
// See example in docs
// https://mozilla.github.io/nunjucks/api.html#custom-tags
class CustomExtension {}
export default new CustomExtension();
Loader trying to guess which extensions are really used, and keep only required imports.
Map of filters, that would be imported before each template render.
Filter should return instance, that would be added via
env.addFilter
.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [{
loader: 'simple-nunjucks-loader',
options: {
filters: {
foo: path.join(__dirname, 'foo.js')
}
}
}]
}
]
}
};
foo.js
export default function filter(val, param) {
return `${val + param}`;
}
template.njk
{{ foo_var | foo(3) }}
To mark filter as async, filter module should export async
flag:
async-filter.js
export default function asyncFilter(val, param, callback) {
setTimeout(function() {
callback(null, val + param);
}, 1000);
}
asyncFilter.async = true;
FAQs
Webpack loader for Nunjucks
The npm package simple-nunjucks-loader receives a total of 4,936 weekly downloads. As such, simple-nunjucks-loader popularity was classified as popular.
We found that simple-nunjucks-loader demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.
Security News
Newly introduced telemetry in devenv 1.4 sparked a backlash over privacy concerns, leading to the removal of its AI-powered feature after strong community pushback.