I love Pug. Pug allow me to write cleaner HTML.
From HTML like this:-
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>my portal</title></head>
<body>
<app-root>
<div class="root-spinner">
<img class="loading" src="assets/images/logo.png">
</div>
</app-root>
</body>
</html>
To Pug, so much cleaner.
doctype html
htmlheadmeta(charset="utf-8")title my portal
bodyapp-rootdiv.root-spinnerimg.loading(src="assets/images/logo.png")
However, if you are using Angular (version 2 or 4) & the de-facto Angular-CLI, the pug option is not out of the box, probably yet. There is a discussion here: https://github.com/angular/angular-cli/issues/1886.
We can use pug-cli now. Pug CLI allows you to compile pug with command like pug [dir,file]
` and watch the changes.
npm install pug-cli --save-dev
After installation, we create two scripts in package.json
`:
"pug-it": "pug src","pug-it:w": "pug src -P -w"
The first command `pug-it` will compile all the .pug files under `src` directory to .html file in same directory.
The second command did exactly the same thing with additional file watching. We use this command during development to watch the file changes and recompile automatically.
Here are some other scripts we have.
"ng": "ng","start": "run-p pug-it:w server","server": "ng serve --port 4210","prebuild": "yarn run pug-it","build": "ng build",
Please notes that:-
npm start
, we will start the dev server and and the pug watch tasks concurrently.prebuild`
).If you want to run multiple tasks concurrently cross platforms (mac, windows, etc), 3rd party packages like concurrently and npm-run-all are helpful. We use npm-run-all
. The run-p
command is provided by the package. You can install it:
npm install npm-run-all --save-dev
However, if all your developers are on Linux or Mac, then you don’t need any 3rd party packages, just replace start
command withnpm run pug-it:w & npm run server
will do.
If you are using pug, you might not want to check in the generated HTML files. Exclude them in your git. Add this line to your .gitignore
file.
#pug/src/**/*.html
Please notes that in your component typescript, you still refer to .html
, there’s no need to change this.
@Component({selector: 'my-root',templateUrl: './app.component.html',styleUrls: ['./app.component.scss']})export class AppComponent {}
Woala, everything up and running.
There are a few tradeoffs using this approach.
When adding any new pug file after npm start
, the new file is not watched. You need to restart dev server (stop and rerun npm start
).
Since we start pug watch and dev-server concurrently, when there’s pug syntax error happens during development, you will see errors in terminal, but not on screen or browser console. Please beware of this, sometimes you got syntax error without knowing it, and spend hours to debug other area (you know what I mean).
ng generate
By default, angular-cli ng generate
will generate HTML file for component. You need to rename or delete/create the HTML to pug file.
Let’s be honest, Angular template syntax looks different from normal HTML. When using it with Pug, you need to surround all attribute with single quote.
my-top-bar('[(ngModel)]'="myModel"'[propA]'="myPropA"'(actionA)'="handle($event)")
This will generate the following HTML.
<my-top-bar[(ngModel)]="myModel"[propA]="myPropA"(actionA)="handle($event)"></my-top-bar>
If you somehow forgot to put single quote on the attributes, congratulation. No error will be notify in terminal. The HTML generated will be
<my-top-bar></my-top-bar>
All fields will be omitted. If you realise about that after an hour of debugging, please don’t cry. Heh.
Please note that
There are some other alternatives.
ng eject
to eject the angular-cli. You’ll get back all your webpack config that angular-cli generated for you. Then add your pug-loader.Our team found the option we chose and the tradeoffs bearable. We’ve use this in our v2 project now upgrade to v4.
Let me know if you have better way of doing this.
That’s it. Hopefully you find this helpful. Happy coding!