Command
serve, build
Description
Angular has great support for its own @angular/pwa today. It works as it should, but does not provide much in form of extensibility. You can configure it to do most things, but you do not have full control over the code. This is why we want to use workbox instead.
We can build workbox into our application from a production build, but this is cumbersome when developing the service-worker and we want to test features and functionality frequently. Then you have a code, compile, wait, test cycle which takes a lot of time. We want to be able to serve our service-worker using the built in vite dev-server in angular, like we can for @angular/pwa service-workers.
Someone suggested using a custom esbuilder for this. I found two alternative builders which allow for esbuild plugins to be injected into the build process: @angular-builders/custom-esbuild:application or @nx/angular:application. But they seem to be executing too soon and do not have access to all files nescessary to build up a proper manifest of all the output files from the build process.
So I disected the build and the serve flow in angular-cli, in order to see how we could extend the build process with our needs:
ng build
When we run ng build, the following code is invoked:
@angular-devkit:application
-> @angular/build:application
-> angular-cli/packages/angular/build/src/builders/application
-> buildApplication
-> buildApplicationInternal
ng serve
@angular-devkit:dev-server
-> angular-cli/packages/angular_devkit/build_angular/src/builders/dev-server
-> angular-cli/packages/angular_devkit/build/src/builders/dev-server/builder.ts
-> @angular/build/private
-> angular-cli/packages/angular/build/src/private.ts
-> buildApplicationInternal
We see that buildApplicationInternal is used in both cases, and this function returns a result.files property containing all the output from the build. Great! Exactly what we need.
Now the result object here is created by running executeBuild which builds the application. And one of the functions it executes, is executePostBundleStep which in turn builds the @angular/pwa service worker using augmentAppwithServiceWorkerEsbuild. This function receives all the outputFiles, assetFiles and the index html file and builds up the service worker.
Describe the solution you'd like
We need to be able to execute a function at the same spot and with the same type of input at you are giving the augmentAppWithServiceWorkerEsbuild function.
My suggestion is this:
Allow a postBundleScript: string in your options, pointing to a file in the project. This will allow devs to add a function which gets a callback before or after the point where you build angular sw today.
Example of such a function:
export default function postBundle(
workspaceRoot,
baseHref,
indexHtmlOutput,
outputFiles,
assetFiles
) {
// Whatever logic users need to perform at this point
}
Describe alternatives you've considered
We've tried to add our own custom builder, but the results from executeBuild is not exposed to other build steps. Exposing those in the results from other builders would of course also be a potential solution.
Today the result from other builders is always only { success: true }.
Command
serve, build
Description
Angular has great support for its own @angular/pwa today. It works as it should, but does not provide much in form of extensibility. You can configure it to do most things, but you do not have full control over the code. This is why we want to use workbox instead.
We can build workbox into our application from a production build, but this is cumbersome when developing the service-worker and we want to test features and functionality frequently. Then you have a code, compile, wait, test cycle which takes a lot of time. We want to be able to serve our service-worker using the built in vite dev-server in angular, like we can for @angular/pwa service-workers.
Someone suggested using a custom esbuilder for this. I found two alternative builders which allow for esbuild plugins to be injected into the build process:
@angular-builders/custom-esbuild:applicationor@nx/angular:application. But they seem to be executing too soon and do not have access to all files nescessary to build up a proper manifest of all the output files from the build process.So I disected the build and the serve flow in angular-cli, in order to see how we could extend the build process with our needs:
ng build
When we run
ng build, the following code is invoked:@angular-devkit:application
-> @angular/build:application
-> angular-cli/packages/angular/build/src/builders/application
-> buildApplication
-> buildApplicationInternal
ng serve
@angular-devkit:dev-server
-> angular-cli/packages/angular_devkit/build_angular/src/builders/dev-server
-> angular-cli/packages/angular_devkit/build/src/builders/dev-server/builder.ts
-> @angular/build/private
-> angular-cli/packages/angular/build/src/private.ts
-> buildApplicationInternal
We see that
buildApplicationInternalis used in both cases, and this function returns aresult.filesproperty containing all the output from the build. Great! Exactly what we need.Now the
resultobject here is created by runningexecuteBuildwhich builds the application. And one of the functions it executes, isexecutePostBundleStepwhich in turn builds the @angular/pwa service worker usingaugmentAppwithServiceWorkerEsbuild. This function receives all the outputFiles, assetFiles and the index html file and builds up the service worker.Describe the solution you'd like
We need to be able to execute a function at the same spot and with the same type of input at you are giving the
augmentAppWithServiceWorkerEsbuildfunction.My suggestion is this:
Allow a
postBundleScript: stringin your options, pointing to a file in the project. This will allow devs to add a function which gets a callback before or after the point where you build angular sw today.Example of such a function:
Describe alternatives you've considered
We've tried to add our own custom builder, but the results from
executeBuildis not exposed to other build steps. Exposing those in the results from other builders would of course also be a potential solution.Today the result from other builders is always only
{ success: true }.