'Angular library and live reload
I followed several tutorials on how to build and test an angular libary.
E.g. https://www.youtube.com/watch?v=lvjt9rBHWjo
It's working fine except that each time I'm doing a ng build mylibary, it's erasing the mylibrary folder in the dist folder. And before it has finished to build, the server (launched with npm start) detect the change (folder erased) and re compiles. And of course, since the library folder is not present anymore, there is a compilation error with no other thing to do than ctrl-c and again npm start ...
What did I missed ?
Solution 1:[1]
You can use wait-on to await the building of the library, rimraf to clean the dist directory and npm-run-all to run the watch scripts parallel with one command from one command line window.
Therefore install wait-on, rimraf and run-p as development dependency:
npm install wait-on --save-dev
npm install rimraf --save-dev
npm install run-p --save-dev
And update in package.json the scripts consequently based on the example below:
"scripts": {
...
"clean": "rimraf dist",
"start:app": "wait-on dist/your-library-name/fesm5 && ng serve --poll 2000",
"watch:lib": "ng build your-library-name --watch",
"watch:all": "npm run clean && run-p watch:lib start:app",
...
},
The library and the application together can be watched using npm run watch:all command.
This is how the scripts work:
"clean": "rimraf dist"
Removes the dist folder.
"start:app": "wait-on dist/your-library-name/fesm5 && ng serve --poll 2000"
Waits on the fesm5 folder in the dist directory, ng serve --poll 2000 starts the app and extends the file watch polling time to 2000 ms. In my case the last one was necessary because after a library modification the app was able to reload in the browser with the same content as previously, I could only see the new build after pressing F5.
"watch:lib": "ng build your-library-name --watch"
Builds the library in watch mode.
"watch:all": "npm run clean && run-p watch:lib start:app"
Cleans the dist folder, after that it serves the application and watches the library parallel.
Solution 2:[2]
Here is a super handy way to make the app reload automatically whether changes are made to the host app or to the library source code, all while keeping the original structure ready to build and publish (no need to revert any changes made to the code prior building and publishing the lib).
Having a library called my-lib, the following steps are needed:
Go to
projects/my-lib/src/libdirectory and createindex.tsfile which exports lib components that are meant to be publicly availableEdit the
projects/my-lib/src/public-api.tsfile in a way it exports all from the previously createdindex.tsfile, e.g.:export * from './lib/index';Finally, update the generated TS paths for the lib in
tsconfig.jsonfile (the root one) to point to theindex.tsfile created previously (instead of pointing to the dist folder)
Here is the git commit showing the changes described in the steps above.
For a more detailed info visit: Setting up live reload for Angular CLI libraries.
No need for external dependencies.
Solution 3:[3]
As of Angular 12, a single workspace, monolithic repository is not required but is the approach Angular takes and sometimes recommends. I've outlined and tested single and multiple workspace solutions below. The Angular team has recommended against referencing an unbuilt library many times, because the application builds are different than the libraries' [1][2].
Single Workspace
When a library and application are in the same workspace, add the watched library's output directory to the application's tsconfig paths. If the library has multiple entry points, create separate paths for the main and secondaries.
/* tsconfig.app.json */
"compilerOptions": {
"paths": {
"@my-scope/my-lib": ["dist/my-lib"],
"@my-scope/my-lib/*": ["dist/my-lib/*"]
}
}
Run the library's watch command.
ng build my-lib --configuration development --watch
Run the application's serve command.
ng serve app --configuration development
Multiple Workspaces
There are three solutions for developing a library with an application in a different workspace.
TSConfig Paths
Adding the library's output directory to the application's tsconfig paths, as demonstrated in the previous section, is the easiest solution. However, the catch is that additional paths for unwatched libraries may need to be added as well, particularly those with deep imports. These sometimes produce compile errors like the following, although, I've seen other obscure cases.
Module build failed (from .../ivy/index.js)
Error TS2339: Property 'X' does not exist on type 'typeof import("Y")
Error TS2305: Module '"X"' has no exported member 'Y'.
Always include Angular and then any that fail until successful.
/* tsconfig.app.json */
"compilerOptions": {
"paths": {
"@angular/*": ["node_modules/@angular/*"],
"@my-scope/my-lib": ["../MyWorkspace/dist/my-lib"],
"@my-scope/my-lib/*": ["../MyWorkspace/dist/my-lib/*"],
"@third-party-scope/third-party-lib": ["node_modules/@third-party-scope/third-party-lib"]
}
}
VSCode may require the library paths in tsconfig.json.
Directory Reference
Enable the preserveSymlinks build option in angular.json.
Install the library using the output directory path to create a symlink. npm does not install peer dependencies when installing symlinks. Install these with install-peerdeps or manually. The following is a useful npm script.
"link:my-lib": "npm install ../MyWorkspace/dist/my-lib && install-peerdeps --only-peers --silent @my-scope/my-lib",
Run the library's watch and application's serve commands.
npm Link
Use npm link to create a symlink to the output directory. Peer dependencies must be installed manually.
> (cd MyWorkspace/dist/my-lib && npm link)
> (cd AppWorkspace && npm link @my-scope/my-lib)
> npm view @my-scope/my-lib peerDependencies
Install peer dependencies, and run the library's watch and application's serve commands.
Secondary Entry Points
Watching secondary entry points is not currently supported with symlinks. It does work with tsconfig paths. The preferred workaround is to configure webpack to watch node_modules for the application build. Install the custom webpack builder.
npm install -D @angular-builders/custom-webpack
Configure the build architect target. Create "linked" build and serve configurations.
/* angular.json */
"projects": {
"my-app": {
...
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
...
"configurations": {
...
"linked": {
... a development configuration
"customWebpackConfig": {
"path": "./webpack.config.js"
}
}
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"configurations": {
...
"linked": {
"browserTarget": "my-app:build:linked"
}
}
Remove node_modules from the managed paths in the webpack configuration.
/* webpack.config.json */
module.exports = {
snapshot: { managedPaths: [] }
};
Alternatively, disable the build cache.
export NG_BUILD_CACHE=0
What is a workspace?
A workspace is the root directory structure and configuration files, like angular.json and package.json, which contains and manages projects (applications and libraries). A monolithic workspace contains all projects which share a single set of dependencies. Some Angulars prefer to organize projects into separate workspaces so that they can manage dependency versions separately. For more information, check out the documentation.
Solution 4:[4]
Use the following steps If you would like to include the built version of the library.
Build the library in watch mode
ng build my-lib --watchAdd the path to the built library in
tsconfig.jsonunderpaths
"paths": {
"my-lib": [
"dist/my-lib/bundles/my-lib.umd.js"
]
}
Launch your main app from a new terminal window
ng serve --open
The downside of this approach compared to the one recommended by seidme is a slightly longer build time needed to assemble the library.
To avoid opening multiple terminals you can add the following command under scripts in package.json. npm install wait-on before running the command.
"dev": "ng build my-lib --watch & (wait-on ./dist/my-lib/bundles/my-lib.umd.js --delay 2000 && ng serve --open)"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | |
| Solution 4 |
