Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building chrome extension popup, options and background using @angular/cli

I would like to create a chrome extension with popup, options page and a background process. So basically an angular app with popup.html, options.html and background.html pages. Is this possible with angular cli?

Today i can do this with multiple webpack configs for each page and it works. Now i want to replace it with angular-cli. Can anyone point me to right direction, i.e a seed project or starter example

Thanks

like image 222
surya Avatar asked Nov 21 '25 09:11

surya


2 Answers

After a LOT of struggling, and digging through the hints and tips on surya's answer, I've managed to get my solution working using Angular (9).


manifest.json

{
...
    "browser_action": {
        "default_popup": "/index.html#/popup"
    },
    "options_page": "/index.html#/options",
    "background": {
        "page": "/index.html#/background",
        "persistent": false
    },
...
}

It uses the hash location strategy to load the components via the #.


AppRouting

The routing will use the paths specified, and load the appropriate components (popup, options, and background script respectively)

const routes: Routes = [
    { path: 'popup', component: PopupComponent },
    { path: 'options', component: OptionsComponent },
    { path: 'background', component: BackgroundComponent },
    { path: '**', component: PopupComponent },
];

@NgModule({
    imports: [RouterModule.forRoot(routes, { useHash: true })],
    exports: [RouterModule]
})
export class AppRoutingModule { }

where the AppRoutingModule is referenced in the app.module.ts:

Note: I've created feature modules for my Options and Popup components, but for this answer it's unrelated. You can declare the mentioned components here as well as I've done with the BackgroundComponent.

@NgModule({
    declarations: [
        AppComponent,
        BackgroundComponent
    ],
    imports: [
        BrowserModule,
        AppRoutingModule,
        OptionsModule,
        PopupModule
    ],
    providers: [
         // This is needed because the manifest loads the index.html file, followed by a #, 
        { provide: LocationStrategy, useClass: HashLocationStrategy }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

With the routing set up, we can use that in the app.component (the bootstrapped component) to load the correct component via the route:

index.html

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Your Extension title</title>
    <base href="/index.html#/"> <!-- !!Important!! !-->

    <meta name="viewport"
        content="width=device-width, initial-scale=1">
</head>

<body>
    <app-root></app-root> <!-- Root of your application !-->
</body>

</html>

AppComponent

The app component (for simplicity) only contains the <router-outlet>, and will orchestrate which component to load.

<router-outlet></router-outlet>

Note: The base href in the index.html file must be set to the following: /index.html#/, otherwise consecutive reloads on the options/popup page will not recognise the correct route and throw a File not found response page.


Examples

If you navigate to a URL, you can see the routing working on the different components:

Options

chrome-extension://<Extension ID>/index.html#/options

Popup

chrome-extension://<Extension ID>/index.html#/popup

Background

Even though this component acts just as a background script, you can still use it as a normal Angular component - and still make use of Angular's features - like services, injection, etc.

chrome-extension://<Extension ID>/index.html#/background

like image 97
Johan Aspeling Avatar answered Nov 24 '25 02:11

Johan Aspeling


So after lot of googling, this blog post helped me. TLDR; no need of multiple apps, single app will do using query parameters. for example in my manifest.json i now have this

"browser_action": {
    "default_popup": "index.html?page=popup"
},
"options_page": "index.html?page=options",
"background": {
    "page": "index.html?page=background",
    "persistent": false
},

And then after defining different components (PopupComponent, OptionsComponent and BackgroundComponent) in Routes, navigate based on the 'page' param.

like image 21
surya Avatar answered Nov 24 '25 01:11

surya