Skip to content
This repository has been archived by the owner on Sep 15, 2023. It is now read-only.

Releases: eneajaho/ngx-isr

v0.5.6

03 Jun 14:38
Compare
Choose a tag to compare
v0.5.6 Pre-release
Pre-release

Added support for Angular v16 and Node v18

v.0.5.5

04 May 18:58
Compare
Choose a tag to compare
v.0.5.5 Pre-release
Pre-release

Features

  • feat: allow NgxIsrService to be used in application code without bringing the whole library in the browser bundle
  • feat: separate the library into secondary entry points for server and browser
  • [#37] fix: allow caching pages on different desk partitions (thanks to @alethyst)

BREAKING CHANGES:

Imports now should be done from ngx-isr/server and ngx-isr/browser instead of ngx-isr;

// Before
import { NgxIsrModule } from 'ngx-isr';

// After
import { NgxIsrModule } from 'ngx-isr/server';

// Before
import { provideISR } from 'ngx-isr';

// After
import { provideISR } from 'ngx-isr/server';

Things exported from ngx-isr/server:

  • NgxIsrModule
  • provideISR
  • ISRHandler
  • FileSystemCacheHandler and FileSystemCacheOptions

Things exported from ngx-isr/browser:

  • NgxIsrService

Things exported from ngx-isr/models:

  • CacheHandler
  • CacheISRConfig (renamed from ISROptions)
  • CacheData
  • INgxIsrService and NgxIsrState
  • ISRHandlerConfig
  • InvalidateConfig
  • RenderConfig
  • ServeFromCacheConfig
  • RouteISRConfig

v0.5.4

18 Apr 22:19
Compare
Choose a tag to compare
v0.5.4 Pre-release
Pre-release

Features

  • feat: refactor FileSystem cache handler from scratch (fixes: #35)
  • fix: buildId can be null but also undefined, added a check for it

v0.5.3

18 Apr 17:01
Compare
Choose a tag to compare
v0.5.3 Pre-release
Pre-release

Features

  • feat: Introduce RouteISRConfig interface for better type safety in route data

    How to use it?

    const routes: Rotues = [{
      path: 'home',
      component: HomeComponent,
      data: { revalidate: 0 } as RouteISRConfig // 👈 Add type to route data
    }];
  • feat: Added build id support

    What is it and why do we need it?

    The build id is a unique identifier that is generated for each build. It is used to invalidate the cache when a new build is deployed. So, when a new build is deployed, every page that will be requested will be server-rendered again and not served from the cache. This way, the users will always get the latest version of the application.

    Useful when you have an external cache handler like Redis.

    How to use it?

    To use it, you need to pass the build id to the ISRHandler constructor.
    Angular itself doesn't generate a build id. But we can generate it using the environment file.
    What we can do is to set field in the environment file called buildId and set it to: new Date().getTime(),.

    Ex. environment.ts:

    export const environment = {
      production: false,
      buildId: new Date().getTime() + '', // We need to convert it to string because the buildId is a string
    };

    This way we will have a unique build id for each build because the buildId will evaluated at build time.
    Then, we pass the build id to the ISRHandler constructor.

    Ex. server.ts:

    import { environment } from './src/environments/environment';
    
    const isr = new ISRHandler({
      .. other options
      buildId: environment.buildTimestamp // Pass the build id
    });
  • fix: Fixed a bug where the cache was not invalidated when the build id changed

Breaking changes:

  • ISROptions is being deprecated. Use CacheISRConfig instead.

v0.5.2

15 Apr 19:39
Compare
Choose a tag to compare
v0.5.2 Pre-release
Pre-release

Changes:

  • feat: Migrate repository to nx workspace
  • feat: Added provideISR provider function
  • chore: Update example RedisCacheHandler to use a prefix
  • feat: new docs page (link)

v0.5.1

18 Feb 12:59
Compare
Choose a tag to compare
v0.5.1 Pre-release
Pre-release

Changes:

  • feat: Added extra field to isrService in order to save extra data if needed

How to use the extra field:

Example: Measure api calls timings

  1. Create an interceptor: UrlTimingsInterceptor
import { HttpHandler, HttpInterceptor, HttpRequest, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Injectable, Provider } from '@angular/core';
import { NgxIsrService } from 'ngx-isr';
import { tap } from 'rxjs';

@Injectable()
export class UrlTimingsInterceptor implements HttpInterceptor {

  constructor(private ngxIsrService: NgxIsrService) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler) {
    let timing1 = performance.now();
    return next.handle(request).pipe(
      tap(() => {
        let timing2 = performance.now();

        const currentExtra = this.ngxIsrService.getExtra();

        const currentRequestsTimings = currentExtra['requestsTimings'] || [];

        const currentUrlTiming = { url: request.url, timing: (timing2 - timing1).toFixed(2) + 'ms' };

        if (currentRequestsTimings.find(t => t.url === request.url)) {
            this.ngxIsrService.addExtra({
                requestsTimings: currentRequestsTimings.map(t => t.url === request.url ? currentUrlTiming : t)
            });
        } else {
            this.ngxIsrService.addExtra({ requestsTimings: [ ...currentRequestsTimings, currentUrlTiming ] });
        }
      })
    );
  }
}

export const HTTP_URL_TIMINGS_INTERCEPTOR_ISR: Provider = {
  provide: HTTP_INTERCEPTORS,
  useClass: UrlTimingsInterceptor,
  multi: true,
}
  1. Import in AppServerModule providers
import { HTTP_URL_TIMINGS_INTERCEPTOR_ISR } from './url-timings.interceptor';

@NgModule({
  ...
  providers: [HTTP_URL_TIMINGS_INTERCEPTOR_ISR] // --> Add provider here for the interceptor
})
export class AppServerModule {}
  1. Run the app and see that the timings for api calls will be included in the isr-state tag in the generated html.

Generated html with extra data included

Note: The code will be run only on server side, so it's code won't be bundled in the client side code 🎉

v0.5.0

08 Feb 23:53
Compare
Choose a tag to compare
v0.5.0 Pre-release
Pre-release

Breaking Changes:

The invalidate method of IsrHandler now is converted to be a POST request.

server.post('/api/invalidate', async (req, res) => 
  await isr.invalidate(req, res)
);

It accepts a body with the following structure:

{
  token: string; // The secren token 
  urlsToInvalidate: string[]; // The urls to invalidate ex. ['/one', '/two']
}

Now you also need to add server.use(express.json()); in your server.ts file in order to parse the body of the request.

Changes:

* feat: added modifyCachedHtml and modifyGeneratedHtml callbacks to provide a mechanism to change html on the fly
* feat: Invalidate/regenerate multiple urls with one request

Thanks to @renatoaraujoc for contributing on the modifyCache feature!

v0.4.0

05 Jan 23:56
Compare
Choose a tag to compare
v0.4.0 Pre-release
Pre-release

Now ngx-isr will support only projects in v15 and above. If you want to use it in older versions of Angular, please use v0.3.1.

The reason for this is because now we use ɵSERVER_CONTEXT token in order to set the rendering context that now will be shown as: ng-server-context="ngx-isr". And this token is only available in v15 and above.

  • Changes:
    • chore: Updated the project to v15
    • feat: Added server context provider
    • feat: Added RedisCacheHandler class usage in the demo app (experimental)
    • chore: Started to convert the demo app in a documentation page for the library

v0.3.1

31 Jul 08:23
Compare
Choose a tag to compare
v0.3.1 Pre-release
Pre-release

Changes

  • Added FileSystem CacheHandler
  • Added "@types/node": "^14.15.0" to peerDeps required by FileSystemCacheHandler

Details:

Before v.0.3.1 we had the possibility to add custom cache handler to the ISR handler, and the default one was the InMemoryCacheHandler. So, every time the application booted it would save all the new cached pages in the memory, but this doesn't scale well, because the memory usage would increase a lot.

In v.0.3.1 we introduced a new cache handler called FileSystemCacheHandler, that enables us to store the cached pages on server filesystem. But now, because we have access to the filesystem, we could have the possibility to prerender pages at build time, but also revalidate them on runtime, giving us the best of both worlds (static and dynamic).

How to configure FileSystemCacheHandler?

  1. Import it in server.ts
import { FileSystemCacheHandler } from 'ngx-isr';
  1. Create an instance of FileSystemCacheHandler
const fsCacheHandler = new FileSystemCacheHandler({
  cacheFolderPath: join(distFolder, '/cache'),
  prerenderedPagesPath: distFolder,
  addPrerendedPagesToCache: true, // set this to true in order to add prerendered pages with `prerenderer` to the cache
});
  1. Use the instance of the fsCacheHandler in the ISRHandler
const isr = new ISRHandler({
  ...
  cache: fsCacheHandler // here we override the default cache handler that is the InMemoryCacheHandler
});
  1. How to prerender at build time?
    The same way we use the default prerenderer, nothing else. Everything is supposed to work the same.

How this works?

FileSystemCacheHandler reads the prerenderedPagesPath that you provide and reads all the folders in the browser folder, and checks if they have an index.html inside (as this is the behavior when we generate static files with the prerenderer).
If the index.html exists in that folder, we add the folder name to the cache handler as the url and the index.html content as the html.
Then we remove the found files in the folder because we don't want to have the default behavior of the angular universal (that serves the static files), because we want to override that behavior with the one of the ISR.
Then we add those files that we found to the cache, so in a different place in the filesystem (to the path you provided in cacheFolderPath).
Now, when a request is made, ISR will check if the cache has the url in it, if yes, it will serve it, otherwise it will server-side render it and if it has the revalidate key provided, it will save it to cache.

v0.3.0

15 Jun 18:57
Compare
Choose a tag to compare
v0.3.0 Pre-release
Pre-release

Features:

  • Added support for Angular v14