Installation
Requirements
You need to have:
- Node.js LTS (with npm)
- Angular CLI
Initialize
The initialization of this library is inspired by The Best Way To Architect Your Angular Libraries from Thomas Trajan
Init library
Init Angular
ng new ng-base --createApplication false --prefix lt
ng g library ng-base --prefix lt
Change package name in projects/ng-base/src
"name": "@lenne.tech/ng-base"
Replace path configuration in tsconfig.json:
{
"paths": {
"@lenne.tech/ng-base/*": ["projects/ng-base/*", "projects/ng-base"],
"@lenne.tech/ng-base": ["dist/ng-base/*", "dist/ng-base"]
}
}
Delete the content of the projects/some-lib/src/lib/folder and remove content of the root public-api.ts file so that it's empty.
Install ng-samurai to extend the Angular CLI for creating Sub-entries:
npm i -D ng-samurai
Create new Sub-entry (without component --gc falseand module --gm false):
ng g ng-samurai:generate-subentry core --gc false --gm false
Linting
Migration from TSLint (depracted since 2019) to ESLint (see Migrationsanleitung):
ng add @angular-eslint/schematics
ng g @angular-eslint/schematics:convert-tslint-to-eslint ng-base
rm tslint.json
npm uninstall tslint
npm uninstall codelyzer
Additional rules in .eslintrc.json:
{
"overrides": [
{
"rules": {
"no-underscore-dangle": "off"
}
}
]
}
Install Prettier and prettier-quick:
npm install --save-dev --save-exact prettier
npm install --save-dev pretty-quick
Add file .prettierrc:
{
"arrowParens": "always",
"plugins": ["./extras/prettier-imports"],
"printWidth": 120,
"singleQuote": true
}
Add file extras/prettier-imports.js:
const { parsers: typescriptParsers } = require('prettier/parser-typescript');
const ts = require('typescript');
// =============================================================================
// Prettier plugin to optimize and sort imports
// see https://github.com/prettier/prettier/issues/6260
// =============================================================================
class SingleLanguageServiceHost {
constructor(name, content) {
this.name = name;
this.content = content;
this.getCompilationSettings = ts.getDefaultCompilerOptions;
this.getDefaultLibFileName = ts.getDefaultLibFilePath;
}
getScriptFileNames() {
return [this.name];
}
getScriptVersion() {
return ts.version;
}
getScriptSnapshot() {
return ts.ScriptSnapshot.fromString(this.content);
}
getCurrentDirectory() {
return '';
}
}
function applyChanges(text, changes) {
return changes.reduceRight((text, change) => {
const head = text.slice(0, change.span.start);
const tail = text.slice(change.span.start + change.span.length);
return `${head}${change.newText}${tail}`;
}, text);
}
function organizeImports(text) {
const fileName = 'file.ts';
const host = new SingleLanguageServiceHost(fileName, text);
const languageService = ts.createLanguageService(host);
const formatOptions = ts.getDefaultFormatCodeSettings();
const fileChanges = languageService.organizeImports({ type: 'file', fileName }, formatOptions, {});
const textChanges = [...fileChanges.map((change) => change.textChanges)];
return applyChanges(text, textChanges);
}
const parsers = {
typescript: {
...typescriptParsers.typescript,
preprocess(text) {
text = organizeImports(text);
return text;
},
},
};
// Uses module.export because of 'Unexpected token export' error
module.exports = parsers;
Add scripts in package.json:
"scripts": {
...
"format:check": "prettier --config ./.prettierrc --list-different \"src/{app,environments,assets}/**/*{.ts,.js,.json,.scss}\"",
"format:fix": "pretty-quick --staged",
"format:fixAll": "prettier --write src",
...
}
format:check: Check only
format:fix: Optimize stage files
format:fixAll: Optimize all files
Automatic optimizations and checks
Install husky:
npm install --save-dev husky
Add scripts in package.json:
"scripts": {
"check": "npm run format:fix && npm run lint",
"postinstall": "husky install .husky",
}
Add pre-commit hook:
mkdir .husky
npx husky add .husky/pre-commit "cd $(dirname "$0") && npm run check"
Init husky via npm i.
Optimize TypeScript config
To get a little more leeway in dealing with TypeScript's strict typing, the following rules should be disabled in compilerOptions of tsconfig.json:
{
"compilerOptions": {
"strictNullChecks": false,
"strictPropertyInitialization": false,
"noImplicitAny": false
}
}
Thanks
Many thanks to the developers of Angular, Apollo Angular and all the developers whose packages are use here.