Skip to content

wandri/angular-chrome-extension

Repository files navigation

Angular Chrome Extension

Creating a Chrome extension using Angular and SCSS involves several steps. Here's a detailed tutorial to guide you through the process:

Our example is focused on a side panel extension.

Configuration

  1. Create the file manifest.json in ./src
{
  "manifest_version": 3,
  "name": "<NAME>",
  "short_name": "<SHORT NAME>",
  "version": "0.0.0",
  "description": "<DESCRIPTION>",
  "permissions": [
    "sidePanel"
  ],
  "content_security_policy": { // OPTIONAL if login with Auth0
    "extension_pages": "script-src 'self'; object-src 'self'; frame-src https://<AUTH_NAME>.auth0.com;"
  },
  "background": {
    "service_worker": "background.js"
  },
  "side_panel": {
    "default_path": "index.html"
  },
  "action": {
    "default_title": "<TITLE>"
  },
  "icons": { // OPTIONAL
    "16": "assets/icon/icon16.png",
    "32": "assets/icon/icon32.png",
    "48": "assets/icon/icon48.png",
    "128": "assets/icon/icon128.png"
  },
  "key": "<Extension Key>" // OPTIONAL
}
  1. Create the file background.ts in ./src
chrome.tabs.onUpdated.addListener((tabId) => {
  chrome.sidePanel
    .setOptions({ tabId, path: 'index.html', enabled: true })
    .catch(console.error);
});

chrome.sidePanel
  .setPanelBehavior({ openPanelOnActionClick: true })
  .catch(console.error);

Install the typing for chrome

npm i --save-dev @types/chrome

Add chrome in tsconfig.app.json

  "compilerOptions": {
    ...
    "types": [
      "chrome"
    ]
  },
  1. Update angular.json with the following
{
   ...
  "targets": {
    "build": {
      ...
      "options": {
        ...
        "assets": [
          ...
          "./src/manifest.json"
        ],
        "optimization": {
          "scripts": true,
          "styles": {
            "minify": true,
            "inlineCritical": false
          },
          "fonts": false
        }
      },
      "configurations": {
        "production": {
          ...
          ...
          "outputHashing": "none"
        },

Be aware that the file names include a hash, a feature that enhances cache management for web applications. However this feature could add unnecessary complexity to our build process. This is because we must declare the names of background and content scripts in the manifest.json file, and having consistent, unchanging file names simplifies this task. outputHashing is set to none to let the file names as they are.

  1. Create the file build-chrome-extension.ts in ./scripts to build the package with background.js inside
const esbuild = require('esbuild');
const {exec} = require('child_process');

// Function to buildChromeExtension the Angular app
async function buildAngularApp(): Promise<void> {
  return new Promise((resolve, reject) => {
    exec('ng build', (error: string, stderr: string) => {
      if (error) {
        console.error(`Angular build error: ${error}`);
        return reject(error);
      }
      console.error(stderr);
      resolve();
    });
  });
}

async function buildBackgroundScript(): Promise<void> {
  return esbuild.build({
    entryPoints: ['src/background.ts'],
    bundle: true,
    write: true,
    outdir: 'dist/angular-chrome-extension/browser/'
  });
}

// Build process
async function buildChromeExtension(): Promise<void> {
  try {
    await buildAngularApp();
    await buildBackgroundScript();
    console.info('Build completed successfully.');
  } catch (error) {
    console.error('Build failed:', error);
  }
}

buildChromeExtension();
  1. Update package.json to include the build script
{
  ...
  "scripts": {
    ...
    "chrome-extension:build": "npx ts-node scripts/build-chrome-extension.ts"
  }
}

Test the extension

  1. Run npm run chrome-extension:build to build the package

  2. Load your unpacked folder /dist/.../browser/

  1. Test your extension

About

Chrome extension with Angular and EsBuild

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published