Using PUG (or Jade) templates with the Angular-CLI
Note: For Angular 6+ you can simply run ng add ng-cli-pug-loader to automatically run & add the scripts below to your project.
Note: The original article was for Angular 5 (and lower / older versions of the Angular CLI) It was more of a temporary/hacky solution until there is more formal support within the Angular-CLI or with Schematics.
[Update 5/29] Angular CLI 6+ PUG Schematics
This is only for the latest CLI 6.0 or higher, but you can run the script ng add ng-cli-pug-loader
and it will automatically run and create all the scripts & code that are found below in this article.
ng add ng-cli-pug-loader
Angular <5 (and older Angular-CLI versions <6)
Remember if you’re using the latest CLI you can use the ng add script above, which utilizes the code & scripts below and runs them automatically for you.
If you’ve ever tried to get pug
or jade
templates working with the Angular CLI, you might have ran into a few random solutions out there, each with their own pros and cons, but nothing super simple.
@Component({
selector: 'my-thing',
templateUrl: './my-thing.pug' // <-- how can we get this to work?
})
Some things -not- to do
- Don’t try to use require, since it won’t be statically analyzable by the Ahead-of-time compiler (AoT).
template: require('pug-loader!./app.component.pug')()
I’ve seen a lot of projects do this, and avoiding AoT withng build --aot=false
but by doing that you’re including the compiler in your prod builds, and increasing package size. - You could use gulp to turn all of your
.pug
files into.html
files (referencing the html file in your components templateUrl), and set up agulp watch
to check pug files into html, but it’s 2017 — it’s… illegal to use Gulp now isn’t it? (kidding of course). All of your templates now have to point to the compiled html file as well. - There are also some packages around that transform your pug files into strings within a
.pug.ts
TypeScript file string, and you import that result. That works great with AoT, but you’ll findng serve
doesn’t work anymore. So that’s a no-go.
What about ng eject?
So another option is that you could ng eject
your Webpack configuration from the CLI, and simply add the pug rule yourself. But for a lot of users, people want to stay within the comforts of the CLI.
After ejecting, just look for rules: [
within the ejected webpack.config file, and add this in the rules array.
{ test: /.(pug|jade)$/, loader: "apply-loader!pug-loader?self" },// make sure you install the loaders for your project!
npm i -D apply-loader pug-loader
This would be the most elegant solution if you’re comfortable handling Webpack yourself, and leaving the bounds of the CLI itself.
But if you want keep the CLI, what else can you do?
If you want to stay within the comforts of the Angular CLI, the easiest solution I’ve come up with, and this is one that works with normal JIT compilation as well as AoT, is editing the underlying webpack config from inside the CLI itself (that’s inside your node_modules).
Like I said, this is a bit hacky :)
It’s as easy as adding a new rule within rules: []
(just like above but deep within node_modules ), but who wants to do all that manually!
Script time
Before we get started with that, just install two quick loaders that we’re going to need:
npm i -D apply-loader pug-loader// ^ shortcut for "npm install --save-dev" here
Now, let’s make a little javascript file, calling it pug-rule-insert.js
, and make sure you put it at the Root level of your entire project.
Here we’re just going to be looking for that common.js webpack file within node_modules/@angular/cli, and inserting a little pug test.
Now we can fire this up just by doing a quick node pug-rule-insert.js
Taking it one step further, let’s add a little postinstall
hook to our package.json scripts… now we’re real fancy.
Now we get to use our .pug
files directly for our templateUrl, and all is right with the world!
@Component({
selector: 'my-component',
templateUrl: './my-component.pug' // <-- ta-da!
})
Hack-tastic.
One thing to note, currently include ./my-other-pug
isn’t fully working yet, but there’s a super easy work-around for that!
!=require('./my-other-pug.pug')
Piece of cake.
The best part?
ng serve
&& ng build --prod
all work, and you even have live-reload / HMR when your doing your local development and updating your pug files.
It works with Universal+CLI projects as well https://github.com/angular/universal-starter/tree/master/cli
Enjoy!
Find me Online !
Twitter: @MarkPieszak
Github: @MarkPieszak
Trilon — Next-level Application Consulting
Trilon.io is a software consulting firm aimed to help get teams & applications up to speed by working with some of the leading industry experts in JavaScript, NodeJS, NestJS Framework & ASP.NET.
Contact us:
hello@trilon.io
Website:
Trilon.io