So the question is pretty basic but I can\'t find it.
I created a new app through ng new my-project
, followed by a ng g library my-library
.
Currently there is no supported way to do this out of the box. As suggested by @oklymenk you should for now go with a custom script which will chain all these build commands.
Also the link shared by @Eutrepe, you can see that they are planning to get rid of this re build thing everytime you make changes to your library.
Running ng build my-lib every time you change a file is bothersome and takes time.
Some similar setups instead add the path to the source code directly inside tsconfig. This makes seeing changes in your app faster.
But doing that is risky. When you do that, the build system for your app is building the library as well. But your library is built using a different build system than your app.
Those two build systems can build things slightly different, or support completely different features.
This leads to subtle bugs where your published library behaves differently from the one in your development setup.
For this reason we decided to err on the side of caution, and make the recommended usage the safe one.
In the future we want to add watch support to building libraries so it is faster to see changes.
We are also planning to add internal dependency support to Angular CLI. This means that Angular CLI would know your app depends on your library, and automatically rebuilds the library when the app needs it.
Why do I need to build the library everytime I make changes?
As much as I know, there is no build-in way to do this in the current version (Angular 8).
It might be possible to use the new builders
but I don't know much about them yet.
So what I did instead was to create a script, which reads in the angular.json
file and determines all application
projects and all configuration
s.
Then it executes ng build
for every project and configuration.
Also, it will collect all the failed builds and log them to the console at the end.
This script looks like this:
import { ProjectType, WorkspaceSchema } from "@schematics/angular/utility/workspace-models";
import { execSync } from "child_process";
import { readFileSync } from "fs";
interface ExecParams {
project: string;
config: string;
}
interface ExecError extends ExecParams {
message: string;
}
function buildAll() {
const json: WorkspaceSchema = JSON.parse(readFileSync("./angular.json").toString());
const errors: ExecError[] = Object.keys(json.projects)
// Filter application-projects
.filter(name => json.projects[name].projectType === ProjectType.Application)
// Determine parameters needed for the build command
.reduce<ExecParams[]>((arr, project) => {
const proj = json.projects[project];
let build = proj.architect && proj.architect.build;
if (build) {
arr = arr.concat(...Object.keys(build.configurations || {})
.map(config => ({ project, config }))
);
}
return arr;
}, [])
// Execute `ng build` and collect errors.
.reduce<ExecError[]>((err, exec) => {
try {
console.log(`Building ${exec.project} (${exec.config}):`);
execSync(`ng build --prod --project ${exec.project} --configuration ${exec.config}`, {stdio: "inherit"});
}
catch (error) {
err.push({
project: exec.project,
config: exec.config,
message: error.message
});
}
console.log("\n");
return err;
}, []);
// Conditionally log errors
if (errors.length === 0)
console.log("Completed");
else {
console.log("\n");
errors.forEach(error => {
console.error(`Building ${error.project} (${error.config}) failed:\n\t${error.message}`);
});
}
}
buildAll();
You can compile it using tsc
and then run it with NodeJs
.
"build-all": "for PROJ in lib1 lib ''; do ng build $PROJ --prod || break; done"
''
provides an empty string to the loop, building the top-level project|| break
stops the for
loop once a library build failsOR the follow works if
angular.json
jq
always returns @
prefixed keys first in the array to loop over"build-all": "for PROJ in $(cat angular.json | jq -r '.projects | keys[]'); do ng build $PROJ --prod; done"
At some point I want to look into building up a dependency tree based on the package.json
(s) found in each project and sort the projects to build based on that. Just not a high priority over up-keeping a hard-coded list from the first suggestion :)
I just added a script to package.json to do that, could not find a better way.
"scripts": {
"build-all": "ng build lib1 && ng build lib2 && ng build",
"build-all-prod": "ng build lib1 --prod && ng build lib2 --prod && ng build --prod"
},
and then
yarn run build-all
ng-build already includes your libraries in the main.js bundle. No need to separately build each library.
Maybe this works for you:
Build the library with ng build --prod --project=your-library
, then in your package.json dependencies:
"example-ng6-lib": "file:../example-ng6-lib/dist/example-ng6-lib/example-ng6-lib-0.0.1.tgz",
Then ng build --prod
your root project.
Example taken from here: https://blog.angularindepth.com/creating-a-library-in-angular-6-part-2-6e2bc1e14121