Migrate Angular Universal to use Standalone APIs
Angular v16 has been released with a new set of APIs for Angular Universal. This guide will help you migrate your existing Angular Universal application to use the new APIs.
There are two main steps to migrate your application to use the new APIs:
- Migrate your application to use standalone APIs
- Migrate your server to use the new APIs
Migrate your application to use standalone APIs
Angular provides a set of schematics to help you migrate your application to use the new APIs. To run the schematics, run the following command:
ng generate @angular/core:standalone
I don’t want to deep dive a lot here as it’s covered in the docs. You can read more about the migration in the Angular Standalone Migration.
In order to have an easy to follow guide, we will make sure we have the same structure as the one that gets generated by default when you create a new Angular application.
First, we have to make sure that we use bootstrapApplication
in main.ts
.
Second, we have to move the providers from main.ts
to an app.config.ts
file. The app.config.ts
file may look like this:
import { TitleStrategy, provideRouter } from '@angular/router';
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { CustomTitleStrategy } from './custom-title-strategy';
import { routes } from './routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
{ provide: TitleStrategy, useClass: CustomTitleStrategy },
],
};
Our main.ts file will look like this:
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
bootstrapApplication(AppComponent, appConfig)
.catch(err => console.error(err));
Now, let’s create another file for our server configuration. We will call it app.config.server.ts
and it will look like this:
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = {
providers: [provideServerRendering()],
};
export const config = mergeApplicationConfig(appConfig, serverConfig);
As you can see, we are using mergeApplicationConfig
to merge the two configurations. We are also adding provideServerRendering
to the server configuration to enable server rendering. This configuration will replace the AppServerModule
class.
We will use this configuration later when we migrate our server.
Now, we need to update our main.server.ts
file to use the new APIs. It will look like this:
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { config } from './app/app.config.server';
const bootstrap = () => bootstrapApplication(AppComponent, config);
export default bootstrap;
So, we are using bootstrapApplication
to bootstrap our application and we are passing the config
we created earlier with the server configurations. We are also exporting a function called bootstrap
that we will use later in our server.
Migrate your server to use the new APIs
As a last step, we need to update our server.ts
file to use the new file we created.
// import bootstrap that we exported from main.server.ts and remove AppServerModule import
- import { AppServerModule } from './src/main.server';
+ import bootstrap from './src/main.server';
export function app(): express.Express {
const server = express();
// other code here
// Replace AppServerModule with bootstrap function
- server.engine('html', ngExpressEngine({ bootstrap: AppServerModule }));
+ server.engine('html', ngExpressEngine({ bootstrap }));
return server;
}
+export default bootstrap;
Finally, we have migrated our application to use the new APIs 🎉.
NOTES:
- If you are using the
TransferHttpCacheModule
, just remove it because it’s provided by default now.
Lately I migrated one of my projects to use this new api-s, so here’s the commit with the changes: https://github.com/eneajaho/ngx-isr/commit/cee0c64282c2e8965397c2de959ea82b7b9a39ac
Thanks for reading!
If this article was interesting and useful to you, and you want to learn more about Angular, support me by buying me a coffee ☕️ or follow me on X (formerly Twitter) @Enea_Jahollari where I tweet and blog a lot about Angular
latest news, signals, videos, podcasts, updates, RFCs, pull requests and so much more. 💎