Repository navigation
Develop & Deploy a Progressive Web Application
This is a comprehensive guide to setup the foundation for a progressive web application. For now, it is based on boilerplate generated using ngX-Rocket. This guide not only covers development but also setting up a convenient CI/CD workflow, error reporting, analytics etc.
Personally, I find the following to be the deciding factors in why I choose Angular as a framework
- Speed of development
- Opinionated and proven practices
- Great tooling
- Higher scalability than any other framework
- CI/CD setup using GitHub Actions
- Hosting using Firebase Hosting
- Unit testing using Jest
- E2E testing using Puppeteer
- Code linting and formatting using ESLint, Prettier & Stylelint
- Commit linting using commitlint
- Semantic versioning & changelogs using Standard Version
- npm scripts for productivity (package.json)
- [Optional] State management using NgRx
- [Optional] Database, backend & more using AngularFire and its integration with NgRx
- [Optional] WebStorm environment setup
Let's begin with generating the boilerplate, making some preliminary adjustments and setting up our environment.
- Install ngX-Rocket
npm install -g generator-ngx-rocket- Generate the app
ngx newWhen asked, select configuration only as per the application's needs (also make sure you choose Jest & Puppeteer). Try not to select extra boilerplate code that you may never use.
Make sure you remove tslint.json in case it comes with the boilerplate as we will be using ESLint only.
Check my PR generator-ngx-rocket/#610
- Install
ts-jestas a dev dependency
npm install ts-jest --save-dev- To make sure jest auto generates module paths from
tsconfig.json, replace themoduleNameMapperkey inmodule.exportsofjest.config.jswith the one shown below and also add the require imports at the top of the file. Make sure the path to yourtsconfig.jsonis correct.
// https://github.com/thymikee/jest-preset-angular#brief-explanation-of-config
const { pathsToModuleNameMapper } = require('ts-jest/utils');
// In the following statement, replace `./tsconfig` with the path to your `tsconfig` file
// which contains the path mapping (ie the `compilerOptions.paths` option):
const { compilerOptions } = require('./tsconfig');
module.exports = {
...
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
...
};Running tests via ng test should work well as the boilerplate code is configured to work with @angular-builders/jest:run. Though, if you try running npx jest directly, you might encounter errors. This is because we need to import 'jest-preset-angular/setup-jest' in in our setup-jest.ts but when you try adding this, ng test starts failing on the other hand because @angular-builders/jest:run is already configured to run the script. So if you want to run npx jest without disrupting any config files & ng test, just add some options
npx jest --setupFilesAfterEnv='jest-preset-angular/setup-jest' '<rootDir>/src/setup-jest.ts'You can use the above CLI command, if you are configuring tests to be run in an IDE, for e.g. WebStorm, as it is more interactive; while ng test will still be functional if you're using it elsewhere, for e.g. in the CI.
I personally prefer this as it makes prettier issues detectable as linting errors/warnings.
- Prettier comes packaged with the boilerplate generated by ngX-Rocket. Referring to the recommended configuration in the official readme
npm install -D eslint-plugin-prettier eslint-config-prettier- Then you need to add
plugin:prettier/recommendedas the last extension in your.eslintrc
{
"extends": ["plugin:prettier/recommended"]
}- Create a new file
.prettierrcif not already present in the root directory and set the following rules. Make sure you set the correct extension for the CSS preprocessor (if any) for your app, if it's not*.scss
{
"singleQuote": true,
"cursorOffset": -1,
"trailingComma": "none",
"overrides": [
{
"files": "*.scss",
"options": {
"singleQuote": false
}
},
{
"files": "*.component.html",
"options": {
"parser": "angular"
}
},
{
"files": "*.html",
"options": {
"parser": "html"
}
}
]
}- Remove the Prettier configuration from
package.json(if present) as we want to use.prettierrcinstead.
- Referring to the recommended configuration in the official readme
npm install -D stylelint-prettier- Replace the
extendskey in your.stylelintrcwith the following
"extends": [
"stylelint-prettier/recommended"
]- Install
postcss-scss
npm install -D postcss-scss- Replace the
lintscript inpackage.jsonwith the following
"lint": "ng lint && stylelint \"src/**/*.scss\" --custom-syntax postcss-scss",We will be setting up git hooks using husky which comes installed with the boilerplate.
- Install commitlint as a dev dependency
npm install -D @commitlint/config-conventional @commitlint/cli- Configure commitlint to use conventional config
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js- Add the commit message hook
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'If you're a small team/individual developer, the setup may help you configure some simple CI/CD workflows. Alternatively, if you're a bigger team, you might want to configure a more robust & accommodating workflow.
Keeping ease of configuration in mind, we will be using Firebase Hosting as it allows for greater flexibility in terms of deployments than GitHub pages.
- Create a project on Firebase.
- Run
firebase initand complete the questionnaire.
