/nestjs-puppeteer

nestjs-puppeteer — Puppeteer module for Nest framework (node.js)

Primary LanguageTypeScriptMIT LicenseMIT

nestjs-puppeteer

Puppeteer module for Nest framework (node.js)

npm npm GitHub semantic-release: angular
Puppeter Peer Dep NestJS Peer Dep

Headless Chrome provider for NestJS, enabling easy integration of Puppeteer into your application.

Important

Chrome introduces the "New Headless" mode in version 112. Most of puppeteer-extra plugins are NOT COMPATIBLE with this mode. If you want to use puppeteer-extra plugins, you need to define headless: true in the module configuration.

You can read more about the new headless mode here.

Installation

To begin using it, we first install the required dependencies.

$ npm install --save nestjs-puppeteer puppeteer-extra puppeteer

Usage

Once the installation process is complete we can import the PuppeteerModule into the root AppModule

import { Module } from '@nestjs/common';
import { PuppeteerModule } from 'nestjs-puppeteer';

@Module({
  imports: [
    PuppeteerModule.forRoot({ headless: 'new' }),
  ],
})
export class AppModule {}

The forRoot() method supports all the configuration properties exposed by the PuppeteerNodeLaunchOptions object used by the puppeteer.launch() method. There are several extra configuration properties described below.

Property Description
name Browser name
plugins An array of puppeteer-extra plugins
isGlobal Should the module be registered in the global context
headless new for the New Headless mode, or true/false

Once this is done, the Puppeteer Browser instance will be available for injection in any of the providers in the application.

import { Browser } from 'puppeteer';

@Module({
  imports: [
    PuppeteerModule.forRoot({ headless: 'new' }),
  ],
})
export class AppModule {
  constructor(@InjectBrowser() private readonly browser: Browser) {}
}

If you used the name option when registering the module, you can inject the browser by name.

ForFeature

After module registration, we can register specific pages for injection.

import { Module } from '@nestjs/common';
import { PuppeteerModule } from 'nestjs-puppeteer';

@Module({
  imports: [
    PuppeteerModule.forRoot({ headless: 'new' }),
    PuppeteerModule.forFeature(['page1', 'page2']),
  ],
})
export class AppModule {}

Once this is done the Page instance will be available for injection in any of the providers in the module.

import { Page } from 'puppeteer';

@Module({
  imports: [
    PuppeteerModule.forRoot({ headless: 'new' }),
    PuppeteerModule.forFeature(['page1', 'page2']),
  ],
})
export class AppModule {
  constructor(@InjectPage('page1') private readonly page1: Page) {}
}

Async configuration

You may want to pass your repository module options asynchronously instead of statically. In this case, use the forRootAsync() method, which provides several ways to deal with async configuration.

One approach is to use a factory function:

PuppeteerModule.forRootAsync({
  useFactory: () => ({
    headless: false,
  }),
})

Our factory behaves like any other asynchronous provider (e.g., it can be async and it's able to inject dependencies through inject).

PuppeteerModule.forRootAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    headless: configService.isHeadless,
  }),
  inject: [ConfigService],
})

Alternatively you can use the useClass syntax:

PuppeteerModule.forRootAsync({
  useClass: PuppeteerConfigService,
})

The construction above will instantiate PuppeteerConfigService inside PuppeteerModule and use it to provide an options object by calling createPuppeteerOptions().
Note that this means that the PuppeteerConfigService has to implement the PuppeteerOptionsFactory interface, as shown below:

@Injectable()
class PuppeteerConfigService implements PuppeteerOptionsFactory {
  createPuppeteerOptions(): PuppeteerNodeLaunchOptions {
    return {
      headless: 'new',
    };
  }
}