Webpack loader to render pug templates
This pug-loader render pug templates into HTML to save it in a
file or compile pug to template function for usage the pug directly in JavaScript.
The pug loader can resolve paths and webpack aliases for extends
include
require()
.
ā ļø HIGHLY RECOMMENDED to use the pug-plugin.
Pug plugin makes your life a lot easier.
Keep your webpack config clean and clear.
This pug-loader
is already included in the pug-plugin.
The pug-plugin
enable using Pug templates as webpack entry points.
The pug-plugin
resolve and compile source files of scripts and styles included directly in Pug, without to define them in the webpack entry.
You don't need more additional plugins such as html-webpack-plugin
and mini-css-extract-plugin
.
Pug plugin does everything by itself and much faster.
Please see usage examples and the demo app Hello World.
Contents
- Install and Quick start
- Options
- Embedded filters
- Usage method
compile
- Usage method
render
- Usage method
html
- Passing data into pug template
- Usage embedded resources
- Usage with Angular Component
- Recipes
- Example "Hello World!"
- More examples
Features
- rendereing pug into pure
HTML string
to save it in separate file - compiling pug into
template function
for usage in JavaScript - generates a template function with both
CommonJS
and ESM
syntax - resolves alias from webpack
resolve.alias
- resolves alias from
compilerOptions.paths
defined in tsconfig.json
using tsconfig-paths-webpack-plugin
- resolves required images in the attribute
srcset
of img
tag - has embedded filters, e.g
:escape
- resolves required JavaScript modules or JSON in pug
- ignore the prefixes
~
@
for webpack resolve.alias
- passing custom data into pug template
- watching of changes in all dependencies
- integration with
Angular Component
- supports for features and options of original
pugjs/pug-loader
- many time faster than original
pugjs/pug-loader
Install and Quick start
To extract HTML from a pug template and save it to a file, use the pug-plugin
or html-webpack-plugin.
Install the pug-plugin
if you want extract HTML from pug defined in webpack entry.
npm install pug-plugin --save-dev
Note: the pug-plugin
already contain the pug-loader
, not need to install extra any pug-loader
.
Change your webpack.config.js according to the following minimal configuration:
const path = require('path');
const PugPlugin = require('pug-plugin');
module.exports = {
output: {
path: path.join(__dirname, 'public/'),
publicPath: '/',
},
entry: {
index: './src/index.pug',
},
plugins: [
new PugPlugin(),
],
module: {
rules: [
{
test: /\.pug$/,
loader: PugPlugin.loader,
options: {
method: 'render',
}
},
],
},
};
Install the pug-loader
only if you use the html-webpack-plugin
.
npm install @webdiscus/pug-loader --save-dev
Change your webpack.config.js according to the following minimal configuration:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
output: {
path: path.join(__dirname, 'public/'),
publicPath: '/',
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src/index.pug'),
filename: 'index.html',
}),
],
module: {
rules: [
{
test: /\.pug$/,
loader: '@webdiscus/pug-loader',
},
],
},
};
Usage in JavaScript
Install the pug-loader
.
npm install @webdiscus/pug-loader --save-dev
Change your webpack.config.js according to the following minimal configuration:
const path = require('path');
module.exports = {
output: {
path: path.join(__dirname, 'public/'),
publicPath: '/',
},
entry: {
index: './src/index.js',
},
module: {
rules: [
{
test: /\.pug$/,
loader: '@webdiscus/pug-loader',
},
],
},
};
Load a pug template in JavaScript. Optional you can pass any data into generated template function.
./src/index.js
const tmpl = require('template.pug');
const html = tmpl({
myVar: 'value',
});
Original options
See original description of options
basedir
Type: string
Default: /
The root directory of all absolute inclusion.
doctype
Type: string
Default: html
Specifies the type of document. See available doctypes.
self
Type: boolean
Default: false
Use the self
as namespace for the local variables in template. It will speed up the compilation, but for access to variable, e.g. myVariable
, you must write self.myVariable
.
globals
Type: Array<string>
Default: []
Add a list of global names to make accessible in templates.
filters
Type: object
Default: undefined
Hash table of custom filters.
Filters let to use other languages in Pug templates.
plugins
Type: Array<Object>
Default: []
Plugins allow to manipulate pug tags, template content in compile process.
How it works see in source of pug.
compileDebug
Type: boolean
Default: false
Includes the function source in the compiled template to improve error reporting.
pretty
Type: boolean
Default: false
This option is deprecated by pugjs and always is false
. Don't use it.
Additional options
method
Type: string
Default: compile
Values:
compile
the pug template compiles into a template function and in JavaScript can be called with variables to render into HTML at runtime.
The query parameter is ?pug-compile
. Can be used if the method is render
.
Use this method, if the template have variables passed from JavaScript at runtime. see usagerender
the pug template renders into HTML at compile time and exported as a string.
All required resource will be processed by the webpack and separately included as added strings wrapped to a function.
The query parameter is ?pug-render
. Can be used if the method is compile
or is not defined in options.
Use this method, if the template does not have variables passed from JavaScript at runtime. The method generates the most compact and fastest code. see usagehtml
the template renders into a pure HTML string at compile time. The method need an addition loader to handles the HTML.
Use this method if the rendered HTML needs to be processed by additional loader, e.g. by html-loader
see usage
Embedded resources such as img(src=require('./image.jpeg'))
handles at compile time by the webpack using asset/resource.
esModule
Type: Boolean
Default: false
Enable / disable ESM syntax in generated JS modules.
Values:
true
The pug-loader
generates JS modules with the ESM syntax.
For example: import html from 'template.pug';
.
For smaller and faster JS code, it is recommended to use this mode.false
defaults. The pug-loader
generates JS modules with the CommonJS modules syntax.
For example, const html = require('template.pug')
.
The default value is false
for compatibility with the JS modules that is generated by the original pug-loader.
Note: The option esModule
is irrelevant for the html
method, because it returns a pure HTML string.
š” For generates smaller and faster template function, it is recommended to use following options:
{
method: 'render',
esModule: true,
}
data
Type: Object
Default: {}
The custom data will be passed in all pug templates, it can be useful by pass global data.
ā ļø Limitation by the compile
method.
A string representing the source code of the function is limited by the function.toString()
, see examples.
For native work of the function passed via the data
loader option, use the render
method.
embedFilters
Type: Object
Default: undefined
Enable embedded pug filters.
To enable a filter add to pug-loader options following:
{
embedFilters: {
<FILTER_NAME> : <FILTER_OPTIONS> | <TRUE>,
}
}
Where <FILTER_NAME>
is the name of a embedded filter, the available filters see below.
The filter can have options <FILTER_OPTIONS>
as an object.
If the filter has no options, use true
as an option to enable the filter.
Embedded filters
ā ļø Defaults all embedded filters are disabled!
Enable only filters used in your pug templates.
š” We have currently only one embedded filter, but other useful filters will occasionally be added.
The goal of the embedded filters is use fast and lightweight filters without additional dependencies in package.json.
Here we want collect most useful small filters.
It is like custom filters, but already exists in the filter collection, that can be simply via an option enabled.
In issues, you can suggest your own filter, and we can add it.
escape
Pug filter: :escape
Filter options: none
The filter escapes HTML tags to display HTML code in the browser as plain text.
This is useful when using syntax highlighting for code containing HTML tags.
Enable the filter:
{
embedFilters: {
escape: true,
},
}
Using the :escape
filter in pug:
pre: code.language-html
:escape
<!-- HTML -->
<div>
<p>Text</p>
</div>
Generates plain text:
<pre>
<code class="language-html">
<!-- HTML -->
<div>
<p>Text</p>
</div>
</code>
</pre>
Display in browser:
<div>
<p>Text</p>
</div>
Inline syntax:
p
:escape The <strong> element has the closing </strong> tag.
p.
The #[:escape <html>] element is the root element.<br>
Inside the #[:escape <html>] element there is a #[:escape <body>] element.
Generates plain text:
<p>
The <strong> element has the closing </strong> tag.
</p>
<p>
The <html> element is the root element.
<br>
Inside the <html> element there is a <body> element.
</p>
Usage method compile
(default)
In JavaScript the required template will be compiled into template function.
In webpack config add to module.rules
:
{
test: /\.pug$/,
loader: '@webdiscus/pug-loader',
options: {
method: 'compile'
}
}
In JavaScript, the result of require() is a template function. Call the template function with some variables to render it to HTML.
const tmpl = require('template.pug');
const html = tmpl({ key: 'value' });
To render the pug direct into HTML, use the query parameter ?pug-render
.
const tmpl = require('template.pug');
const html = tmpl({ key: 'value' });
const html2 = require('template2.pug?pug-render');
Note: if the query parameter pug-render
is set, then will be used rendering for this template, independent of the loader option method
.
Variables passed in template with method render
will be used at compile time.
Usage method render
This method will render the pug into HTML at compile time.
In webpack config add to module.rules
:
{
test: /\.pug$/,
loader: '@webdiscus/pug-loader',
options: {
method: 'render'
}
}
In JavaScript the result of require() is an HTML string.
const html = require('template.pug');
To generate a template function for passing the data in pug at realtime, use the query parameter ?pug-compile
.
const html = require('template.pug');
const tmpl2 = require('template2.pug?pug-compile');
const html2 = tmpl2({ ... });
Usage method html
This method will render the pug to pure HTML and should be used with an additional loader to handle HTML.
In webpack config add to module.rules
:
{
test: /\.pug$/,
use: [
{
loader: 'html-loader',
options: {
esModule: false,
},
},
{
loader: '@webdiscus/pug-loader',
options: {
method: 'html',
},
},
],
}
In JavaScript the result of require() is an HTML string:
const html = require('template.pug');
Passing data into template
In JavaScript
By default, the pug file is compiled as template function, into which can be passed an object with template variables.
const tmpl = require('template.pug');
const html = tmpl({
myVar: 'value',
foo: 'bar'
});
But how pass variables in template which is rendered into HTML?
Variables can be passed with query parameters.
const html = require('template.pug?myVar=value&foo=bar');
or as a JSON object:
const html = require('template.pug?' + JSON.stringify({ myVar: 'value', foo: 'bar' }));
Use variables myVar
and foo
in pug template.
div The value of "myVar": #{myVar}
div The value of "foo": #{foo}
Usage of query parameters is legal and official documented feature of webpack loader.
In webpack.config.js
Pass myData
object via query.
entry: {
about: './src/pages/about.pug?myData=' + JSON.stringify({ title: 'About', options: { uuid: 'abc123' } })
}
Use the object myData
in pug template.
html
head
title= myData.title
body
div UUID: #{myData.options.uuid}
To pass global data to all pug templates, add the loader options data
as any object.
module.exports = {
module: {
rules: [
{
test: /\.pug$/,
loader: '@webdiscus/pug-loader',
options: {
data: {
htmlLang: 'en-EN',
getKeywords: () => {
const keywords = ['webpack', 'pug', 'loader'];
return keywords.join(',');
}
}
}
},
],
},
};
Use the custom data and function in pug.
html(lang=htmlLang)
head
meta(name="keywords" content=getKeywords())
body
Passing data in HtmlWebpackPlugin
The user data can be passed into pug template with two ways:
- via HtmlWebpackPlugin options
- via query parameters of template file
module.exports = {
plugins: [
new HtmlWebpackPlugin({
title: 'The some page',
template: path.join(__dirname, 'src/index.pug?' + JSON.stringify({ myVar: 'value' })),
filename: 'index.html',
}),
],
module: {
rules: [
{
test: /\.pug$/,
loader: '@webdiscus/pug-loader',
},
],
},
};
Use the passed variables htmlWebpackPlugin.options
and myVar
in pug template:
html
head
title= htmlWebpackPlugin.options.title
body
div= myVar
Load a static data in the pug
You can load data directly in pug.
data.json
[
{ "id": 1, "name": "abc" },
{ "id": 2, "name": "xyz" }
]
Require the JSON file in pug.
- var myData = require('./data.json')
each item in myData
div #{item.id} #{item.name}
Usage embedded resources
To handle resources in pug with webpack use the require()
function:
img(src=require('./path/to/image.jpeg'))
For images, add the following rule to the webpack module:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|svg|ico)/,
type: 'asset/resource',
generator: {
filename: 'assets/images/[name].[hash:8][ext]',
},
},
]
},
};
For fonts, add the following rule to the webpack module:
module.exports = {
module: {
rules: [
{
test: /\.(woff2|woff|ttf|svg|eot)/,
type: 'asset/resource',
generator: {
filename: 'assets/fonts/[name][ext]',
},
},
]
},
};
More information about asset-modules see here.
Example of dynamic interpolation of image src in pug:
- files = ['image1.jpeg', 'image2.jpeg', 'image3.jpeg']
each file in files
img(src=require(`./path/to/${file})`)
š” Resolve resources
The file in the current directory MUST
start with ./
:
img(src=require('./image.jpeg'))
img(src=require('./sub/path/to/image.jpeg'))
The file in the parent directory MUST
start with ../
:
img(src=require('../images/image.jpeg'))
The relative path from loader option basedir
MUST
start with /
:
loader: '@webdiscus/pug-loader',
options: {
basedir: path.resolve(__dirname, './src')
}
img(src=require('/assets/images/image.jpeg')) <-- relative path from the basedir
The file in the directory defined by webpack aliase
MAY
start with ~
or @
, e.g. with the alias Images: path.join(__dirname, 'src/assets/images/')
:
img(src=require('Images/image.jpeg'))
img(src=require('~Images/image.jpeg'))
img(src=require('@Images/image.jpeg'))
ā ļø Using a variable with the compile
method has the limitation - the variable MUST NOT
contain a path, only a filename, because is interpolated at compile time:
- const file = 'image.jpeg'
img(src=require('./path/to/' + file)) // sub directory
img(src=require('../path/to/' + file)) // parent directory
img(src=require('/path/to/' + file)) // option.base directory
img(src=require('~Images/' + file)) // webpack alias
but in current directory, the filename MUST
start with ./
:
- const file = './image.jpeg'
img(src=require(file))
ā ļø Using an alias from the paths
defined in tsconfig.json
with the compile
method has the limitation - the required argument MUST
be a string only, the webpack not supports an expression with alias:
tsconfig.json
{
"compilerOptions": {
"paths": {
"@Images/*": ["assets/images/*"]
}
}
}
- const file = './image.jpeg'
img(src=require('@Images/image.jpeg')) // webpack alias resolved via `resolve.plugiins` from `tsconfig.json`
img(src=require('@Images/' + file)) // ERROR: Can't resolve '@Images' in require expression.
Using a variable with render
and html
methods has no limitation - the variable MAY
contain a path, because is resolved at runtime:
- const file = '../parent/path/to/image.jpeg'
img(src=require(file))
img(src=require('~Images/' + file))
img(src=require('@Images/' + file))
Examples of file resolving
The example of webpack alias used in the table below:
resolve: {
alias: {
Images: path.join(__dirname, 'src/assets/images/'),
},
}
Example in pug template | @webdiscus/ pug-loader
render / html methods | @webdiscus/ pug-loader
compile method | pugjs/ pug-loader |
---|
img(src=require('logo.png')) | ā
but not recomended | ā | ā |
img(src=require('./logo.png')) | ā
| ā
| ā
|
img(src=require('../images/logo.png')) | ā
| ā
| ā
|
img(src=require('~Images/logo.png')) | ā
| ā
| ā
|
- var file = 'logo.png'
img(src=require(`~Images/${file}`)) | ā
| ā
| ā
|
- var file = './logo.png'
img(src=require(file)) | ā
| ā
| ā |
- var file = './images/logo.png'
img(src=require(file)) | ā
| ā
| ā |
- var file = '../images/logo.png'
img(src=require(file)) | ā
| ā | ā |
- var file = 'logo.png'
img(src=require(`./images/${file}`)) | ā
| ā
| ā
|
- var file = 'logo.png'
img(src=require('../images/' + file)) | ā
| ā
| ā
|
pugjs/pug-loader can't resolve a resource when used a mixin and require in same file: include mixins
img(src=require('./logo.png')) | ā
| ā
| ā |
Usage with Angular Component
Install
npm i --saveDev @webdiscus/pug-loader pug-plugin-ng
in pug-loader can be used optional a plugin, e.g. pug-plugin-ng, to allow unquoted syntax of Angular: [(bananabox)]="val"
Create the file webpack.config.js
in root directory of angular project:
module.exports = {
module: {
rules: [
{
test: /\.pug$/,
loader: '@webdiscus/pug-loader',
options: {
method: 'render',
doctype: 'html',
plugins: [require('pug-plugin-ng')],
},
},
],
},
};
Bind the file webpack.config.js
in the Angular config angular.json
:
{
"projects": {
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"aot": true,
"customWebpackConfig": {
"path": "./webpack.config.js"
},
},
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "<app-name>:build"
},
},
}
}
},
}
In a component file, e.g. ./src/app/app.component.ts
set the templateUrl
with pug file:
import { Component } from '@angular/core';
const templateVars = '{"description": "Use pug template with Angular."}';
@Component({
selector: 'app-root',
styleUrls: ['./app.component.css'],
templateUrl: './app.component.pug?' + templateVars,
})
export class AppComponent {
title = 'ng-app';
}
Create a pug template, e.g. ./src/app/app.component.pug
:
h1 Hello Pug!
p Description: #{description}
See the complete source of the example.
Recipes
Resolving the attribute srcset
in img
tag
img(srcset=`${require('./image1.jpeg')} 320w, ${require('./image2.jpeg')} 640w` src=require('./image.jpeg'))
output
<img srcset="/assets/image1.f78b30f4.jpeg 320w, /assets/image2.f78b30f4.jpeg 640w" src="/assets/image.f78b30f4.jpeg">
Usage a JavaScript module in pug
Use the require()
for CommonJS files in pug templates.
The JS module say-hello.js
module.exports = function(name) {
return `Hello ${name}!`;
}
Use the module sayHello
in pug template.
- var sayHello = require('./say-hello')
h1 #{sayHello('pug')}
Testing
npm run test
will run the unit and integration tests.
npm run test:coverage
will run the tests with coverage.
Also See
License
ISC