Security News
The Risks of Misguided Research in Supply Chain Security
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
pug-plugin
Advanced tools
Pug plugin to extract HTML, CSS and JS from Pug files defined in webpack entry. Replaces asset's source filename with hashed output filename. Replaces SVG images with inline SVG in generated HTML.
Pug Plugin Philosophy:
💡 See the demo site Hello World and its sources.
Define Pug files in webpack entry, so easy:
const PugPlugin = require('pug-plugin');
module.exports = {
entry: {
index: './src/views/index.pug', // output index.html
about: './src/views/about/index.pug' // output about.html
// ..
},
plugins: [
// enable using Pug files in webpack entry
new PugPlugin({
// options
}),
],
// ...
};
Use source scripts and styles directly in pug:
link(href=require('./styles.scss') rel='stylesheet')
script(src=require('./main.js'))
Generated HTML contains hashed CSS and JS output filenames:
<link href="/assets/css/styles.05e4dd86.css" rel="stylesheet">
<script src="/assets/js/main.f4b855d8.js"></script>
Just one Pug plugin replaces the functionality of many plugins and loaders:
Package | Features |
---|---|
html-webpack-plugin | extract HTML and save in a file |
mini-css-extract-plugin | extract CSS and save in a file |
webpack-remove-empty-scripts | remove empty js files generated by the mini-css-extract-plugin |
resolve-url-loader | resolve url in CSS |
svg-url-loader | encode SVG data-URL as utf8 |
posthtml-inline-svg | inline SVG icons in HTML |
pug-loader | the Pug loader is already included in the Pug plugin |
⚠️ Not recommended to use the
pug-plugin
together withhtml-webpack-plugin
andmini-css-extract-plugin
.The
pug-plugin
is designed to replace these plugins.
Thepug-plugin
does the same, but much easier and faster.
The fundamental difference between PugPlugin.extractCss
and mini-css-extract-plugin
:
mini-css-extract-plugin
extracts CSS from imported styles in JS and inject <style>
tag somewhere in HTMLPugPlugin.extractCss
extracts CSS from the source styles used in Pug and replaces the original filename with the hashed output namenode_module
pretty
formatting of generated HTMLasset/resource
asset/inline
asset
to automatically choose between resource
and inline
inline SVG
in HTMLinline SVG
as data-URL in CSS
background: url('./icons/iphone.svg') // CSS: url("data:image/svg+xml,<svg>...</svg>")
post process
for modules to handle the extracted contentInstall the pug-plugin
:
npm install pug-plugin --save-dev
Install additional packages for styles:
npm install css-loader sass sass-loader --save-dev
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, 'dist/'),
publicPath: '/', // must be defined any path, `auto` is not supported
// output filename for JS files
filename: 'assets/js/[name].[contenthash:8].js'
},
entry: {
// all scripts and styles can be used in Pug,
// do not need to define JS and SCSS in the webpack entry
// define Pug files in entry:
index: './src/views/index.pug', // output index.html
about: './src/views/about/index.pug' // output about.html
// ...
},
plugins: [
// enable using Pug files in entry
new PugPlugin({
modules: [
// module extracts CSS from style source files required in Pug
PugPlugin.extractCss({
// output filename of CSS files
filename: 'assets/css/[name].[contenthash:8].css'
})
]
})
],
module: {
rules: [
{
test: /\.pug$/,
loader: PugPlugin.loader, // pug-plugin already contain the pug-loader
options: {
method: 'render', // fast method to generate static HTML files
}
},
{
test: /\.(css|sass|scss)$/,
use: ['css-loader', 'sass-loader']
},
],
},
};
Pug template src/views/index.pug
:
html
head
//- add styles in head
link(href=require('./styles.scss') rel='stylesheet')
body
h1 Hello Pug!
//- add scripts at last position in body
script(src=require('./main.js'))
Generated HTML:
<html>
<head>
<link href="/assets/css/styles.f57966f4.css" rel="stylesheet">
</head>
<body>
<h1>Hello Pug!</h1>
<script src="/assets/js/main.b855d8f4.js"></script>
</body>
</html>
⚠️ Attention
- Don't define styles and JS files in entry. You can use
require()
for source files of JS and SCSS in Pug.- Don't import styles in JS. Use
require()
for style files in Pug.- Don't use
html-webpack-plugin
to render Pug files in HTML. The Pug plugin processes files from webpack entry.- Don't use
mini-css-extract-plugin
to extract CSS from styles. The Pug plugin extract CSS from styles required in Pug.
The plugin options are default options for self plugin and all plugin modules
.
In a defined module
any option can be overridden.
enabled
Type: boolean
Default: true
Enable/disable the plugin.
verbose
Type: boolean
Default: false
Show the file information at processing of entry.
pretty
Type: boolean
Default: false
Pretty formatting the resulting HTML. Use this option for debugging only. For production build should be disabled.
This option only works for Pug files defined in the webpack entry.
⚠️ The
pretty
option of thepug-loader
is deprecated, therefore use thispretty
option inpug-plugin
.
const PugPlugin = require('pug-plugin');
module.exports = {
plugins: [
new PugPlugin({
pretty: true, // formatting of HTML
}),
],
module: {
rules: [
{
test: /\.pug$/,
loader: PugPlugin.loader,
options: {
pretty: false, // deprecated, is always false, don't use it
}
},
],
},
};
test
Type: RegExp
Default: /\.pug$/
Use the test
to match module options by source filename of a resource.
For example, save all extracted svg
files from fonts/
to the separate output directory:
const PugPlugin = require('pug-plugin');
module.exports = {
plugins: [
new PugPlugin({
modules: [
{
test: /fonts\/.+\.svg$/,
outputPath: path.join(__dirname, 'dist/some/other/path/'),
},
],
}),
],
};
sourcePath
Type: string
Default: webpack.options.context
The absolute path to sources.
outputPath
Type: string
Default: webpack.options.output.path
The output directory for processed entries. This directory can be relative by webpack.options.output.path
or absolute.
filename
Type: string | Function
Default: webpack.output.filename || '[name].html'
The name of output file.
string
then following substitutions (see output.filename for chunk-level) are available in template string:
[id]
The ID of the chunk.[name]
Only filename without extension or path.[contenthash]
The hash of the content.[contenthash:nn]
The nn
is the length of hashes (defaults to 20).Function
then following parameters are available in the function:
@param {webpack PathData} pathData
See the description of this type here@param {webpack AssetInfo} assetInfo
@return {string}
The name or template string of output file.postprocess
Type: Function
Default: null
The post process for extracted content from compiled entry.
The following parameters are available in the function:
@param {string} content
The content of compiled entry.@param {ResourceInfo} info
The info of current asset.@param {webpack Compilation} compilation
The webpack compilation object.@return {string | null}
Return string content to save to output directory.null
then the compiled content of the entry will be ignored, and will be saved original content compiled as JS module.
Returning null
can be useful for debugging to see the source of the compilation of the webpack loader./**
* @typedef {Object} ResourceInfo
* @property {boolean} [verbose = false] Whether information should be displayed.
* @property {boolean} isEntry True if is the asset from entry, false if asset is required from pug.
* @property {string} outputFile The absolute path to generated output file (issuer of asset).
* @property {string | (function(PathData, AssetInfo): string)} filename The filename template or function.
* @property {string} sourceFile The absolute path to source file.
* @property {string} assetFile The output asset file relative by `output.publicPath`.
*/
modules
Type: PluginOptions[]
Default: []
The array of objects of type PluginOptions
to separately handles of files of different types.
The description of @property
of the type PluginOptions
see above, by Plugin options.
/**
* @typedef {Object} PluginOptions
* @property {boolean} enabled
* @property {boolean} verbose
* @property {RegExp} test
* @property {string} sourcePath
* @property {string} outputPath
* @property {string | function(PathData, AssetInfo): string} filename
* @property {function(string, ResourceInfo, Compilation): string | null} postprocess
*/
The simple example of resolving the asset resources via require() in Pug and via url() in scss.
The webpack config:
const PugPlugin = require('pug-plugin');
module.exports = {
entry: {
index: './src/pages/home/index.pug', // one entry point for all assets
// ... here can be defined many Pug templates
},
output: {
path: path.join(__dirname, 'dist/'),
publicPath: '/',
// output filename for JS files
filename: 'assets/js/[name].[contenthash:8].js'
},
resolve: {
alias: {
// use alias to avoid relative paths like `./../../images/`
Images: path.join(__dirname, './src/images/'),
Fonts: path.join(__dirname, './src/fonts/')
}
},
plugins: [
new PugPlugin({
modules: [
PugPlugin.extractCss({
// output filename for CSS files
filename: 'assets/css/[name].[contenthash:8].css'
})
]
})
],
module: {
rules: [
{
test: /\.pug$/,
loader: PugPlugin.loader,
options: {
method: 'render',
}
},
{
test: /\.(css|sass|scss)$/,
use: ['css-loader', 'sass-loader']
},
{
test: /\.(png|jpg|jpeg|ico)/,
type: 'asset/resource',
generator: {
// output filename for images
filename: 'assets/img/[name].[hash:8][ext]',
},
},
{
test: /\.(woff|woff2|eot|ttf|otf|svg)$/i,
type: 'asset/resource',
generator: {
// output filename for fonts
filename: 'assets/fonts/[name][ext][query]',
},
},
],
},
};
The Pug template ./src/pages/home/index.pug
:
html
head
link(rel="icon" type="image/png" href=require('~Images/favicon.png'))
link(href=require('./styles.scss') rel='stylesheet')
body
.header Here is the header with background image
h1 Hello Pug!
img(src=require('~Images/pug-logo.jpg') alt="pug logo")
script(src=require('./main.js'))
The source script ./src/pages/home/main.js
console.log('Hello Pug!');
The source styles ./src/pages/home/styles.scss
// Pug plugin can resolve styles in node_modules.
// The package 'material-icons' must be installed in packages.json.
@use 'material-icons';
// Resolve the font in the directory using the webpack alias.
@font-face {
font-family: 'Montserrat';
src: url('~Fonts/Montserrat/Montserrat-Regular.woff2'); // pug-plugin can resolve url
...
}
body {
font-family: 'Montserrat', serif;
}
.header {
background-image: url('~Images/header.png'); // pug-plugin can resolve url
...
}
💡The Pug plugin can resolve an url (as relative path, with alias, from node_modules) without requiring
source-maps
. Do not need additional loader such asresolve-url-loader
.
The generated CSS dist/assets/css/styles.f57966f4.css
:
/*
* All styles of npm package 'material-icons' are included here.
* The imported fonts from `node_modules` will be coped in output directory.
*/
@font-face {
font-family: "Material Icons";
src:
url(/assets/fonts/material-icons.woff2) format("woff2"),
url(/assets/fonts/material-icons.woff) format("woff");
...
}
.material-icons {
font-family: "Material Icons";
...
}
/*
* Fonts from local directory.
*/
@font-face {
font-family: 'Montserrat';
src: url(/assets/fonts/Montserrat-Regular.woff2);
...
}
body {
font-family: 'Montserrat', serif;
}
.header {
background-image: url(/assets/img/header.4fe56ae8.png);
...
}
💡All resolved files will be coped to the output directory, so no additional plugin is required, such as
copy-webpack-plugin
.
The generated HTML dist/index.html
contains the hashed output filenames of the required assets:
<html>
<head>
<link rel="stylesheet" href="/assets/css/styles.f57966f4.css">
</head>
<body>
<div class="header">Here is the header with background image</div>
<h1>Hello Pug!</h1>
<img src="/assets/img/pug-logo.85e6bf55.jpg" alt="pug logo">
<script src="/assets/js/main.b855d8f4.js"></script>
</body>
</html>
All this is done by one Pug plugin, without additional plugins and loaders. To save build time, to keep your webpack config clear and clean, just use this plugin.
.html
file in separate fileDependency: html-loader
This loader is need to handle the .html
file type.
Install: npm install html-loader --save-dev
webpack.config.js
const path = require('path');
const PugPlugin = require('pug-plugin');
module.exports = {
output: {
path: path.join(__dirname, 'public/'),
publicPath: '/',
},
entry: {
'example': './vendor/pages/example.html', // output to /static/example.html
},
plugins: [
new PugPlugin({
modules: [
// add the module to match `.html` files in webpack entry
{
test: /\.html$/,
filename: '[name].html', // output filename
outputPath: 'static/', // output path for all .html files defined in entry
},
],
}),
],
module: {
rules: [
// add the loader to handle `.html` files
{
test: /\.html$/,
loader: 'html-loader',
options: {
sources: false, // disable processing of resources in static HTML, leave as is
esModule: false, // webpack use CommonJS module
},
},
],
},
};
To enable live reload by changes any file add in the webpack config following options:
devServer: {
static: {
directory: path.join(__dirname, 'dist'),
},
watchFiles: {
paths: ['src/**/*.*'],
options: {
usePolling: true,
},
},
},
Note: Live reload works only if in Pug used a JS file. If your Pug template has not a JS, then create one empty JS file and add it in Pug:
script(src=require('./dummy.js'))
Don't forget disable this dummy script for production build:
//- script(src=require('./dummy.js'))
Pug plugin can resolve styles in node_modules
.
💡 Pug plugin resolves styles much fasted than the resolve-url-loader and don't require to use the source map in
sass-loader
.
@use 'MODULE_NAME/path/to/style';
Important: the file extension, e.g. .scss, .css, must be omitted.
Example how to import styles of material-icons:
// import styles from installed module `material-icons`
@use 'material-icons';
// define short class name
.mat-icon {
@extend .material-icons-outlined;
}
Usage of the icon home
in Pug:
.mat-icon home
Example how to import the style theme tomorrow
of the prismjs module:
// import default prismjs styles from installed module `prismjs`
@use 'prismjs/themes/prism-tomorrow.min';
Note: use the
@use
instead of@import
, because it is deprecated.
npm run test
will run the unit and integration tests.
npm run test:coverage
will run the tests with coverage.
2.7.8 (2022-06-27)
FAQs
Pug plugin for webpack handles a template as an entry point, extracts CSS and JS from their sources referenced in Pug.
The npm package pug-plugin receives a total of 3,187 weekly downloads. As such, pug-plugin popularity was classified as popular.
We found that pug-plugin demonstrated a healthy version release cadence and project activity because the last version was released less than 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.
Security News
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
Research
Security News
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.