Creating Chrome Extensions With TypeScript

Change the background color of a page

Enis Erbek
Better Programming
Published in
6 min readJan 27, 2022

--

In this article

I will cover, what are extensions, the importance of TypeScript, and how to create a simple chrome extension using TypeScript showing the required procedures step by step.

What Are Extensions?

Extensions are small software programs that customize the browsing experience. They let users tailor Chrome functionality and behavior in many ways.

Almost everyone is using extensions on their browsers, especially for blocking those annoying ads.

Some examples of chrome extensions are:

  • Password managers
  • Ad blockers
  • To-do list creators

and many more can be found at the Chrome Web Store.

What Are Extensions Consists Of?

Extensions are built on web technologies such as HTML, JavaScript, and CSS. They run in a separate, sandboxed execution environment and interact with the Chrome browser. Extensions let you “extend” the browser by using APIs to modify browser behavior and access web content.

Why TypeScript?

For starters, TypeScript is a superset of JavaScript meaning that it extends JavaScript. Hence, it solves some problems that JavaScript can’t.

Many JavaScript apps are made up of hundreds of thousands of files. A single change to one individual file can affect the behavior of any number of other files, like throwing a pebble into a pond and causing ripples to spread out to the bank.

It does not mean TypeScript must be used for only large applications. If you like to code type safely this is a great way to go.

TypeScript achieves its goals in three ways:

  • Support for modern JavaScript features
  • Advanced type system
  • Developer tooling support

With the help of TypeScript, your application can suddenly be type-safe, easy to develop, easy to debug, object-oriented, and well structured.

Enough with the chatter, lets jump into code

Prerequisites

To be able to complete this tutorial you need to have Node and npm installed.

Note

During the demonstration, you will be creating some folders and files. The final folder structure will be like below.

If you are willing to change the folder structure, you will have to adjust the configurations accordingly.

Folder structure

1. Create the project

  • Create an empty directory and initialize a project via npm.
~$ mkdir medium-extension
~$ cd medium-extension
~$ npm init -y
  • Install the required dependencies.
~$ npm install --save-dev webpack webpack-cli
~$ npm install --save-dev copy-webpack-plugin
~$ npm install --save-dev typescript ts-loader
~$ npm install --save-dev @types/chrome
  • Create tsconfig.json folder. The tsconfig.json file specifies the root files and the compiler options required to compile the project. Feel free to dig deep into configuring TypeScript projects from here.

tsconfig.json

{
"compilerOptions": {
"strict": true,
"module": "commonjs",
"target": "es6",
"esModuleInterop": true,
"sourceMap": true,
"rootDir": "src",
"outDir": "dist/js",
"noEmitOnError": true,
"typeRoots": [ "node_modules/@types" ]
}
}
  • Create directories named src and webpack and public inside the project folder.

Create a webpack.config.js file inside the webpack folder and background.ts file inside the src folder.

webpack.config.js

const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
mode: "production",
entry: {
background: path.resolve(__dirname, "..", "src", "background.ts"),
},
output: {
path: path.join(__dirname, "../dist"),
filename: "[name].js",
},
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
exclude: /node_modules/,
},
],
},
plugins: [
new CopyPlugin({
patterns: [{from: ".", to: ".", context: "public"}]
}),
],
};

This will direct webpack to load all .ts files through the ts-loader, and output a dist folder containing bundled .js files in our project.

  • Add build script in the package.json file.

package.json

{
"name": "medium-extension",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --config webpack/webpack.config.js"
},

"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"ts-loader": "^9.2.6",
"typescript": "^4.5.4",
"webpack": "^5.66.0",
"webpack-cli": "^4.9.1"
}
}

2. Create the manifest

Every extension has a JSON-formatted manifest file. A manifest file contains metadata of the whole extension application including name, version, descriptions, content scripts, permissions, and many more.

Create a file named manifest.json . Purposes and usages of each field in the manifest file can be found in the official document.

manifest.json

{
"name": "Medium Extension",
"description": "This extension is made for demonstration purposes",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
}
}

In this manifest file:

name, description, and version are the same as the name implies.

manifest_version: determines the version of the manifest file. Which is the latest and the recommended version at the moment.

permissions: these are required permissions that are needed for your extension’s basic functionality.

service_worker: Extensions register their background service workers generally when they are first initialized. This configuration allows background.js functioning as a service worker. A service worker is a script that your browser runs in the background. Your extensions functionality will be handled via a registered service worker.

3. Implement the service worker

We described background.js in the manifest file. We will create a file named background.ts and write our code type safely, handing over the bundling and the ts -> js conversion to the webpack.

background.ts

let active = false;

function makeOrange(color: string): void {
document.body.style.backgroundColor = color;
}

chrome.action.onClicked.addListener((tab) => {
active = !active;
const color = active ? 'orange' : 'white';
chrome.scripting.executeScript({
target: {tabId: tab.id ? tab.id : -1},
func: makeOrange,
args: [color]
}).then();
});

In this code block, with the help of the chrome API, we listen to the click event on the extension action button and change the background color of the currently active tab.

4. Bundle the code

In the root directory of the project, run the following script.

~$ npm run build

This will create a dist folder containing manifest.json and background.js in the project.

5. Load the extension

  • Navigate to the chrome://extensions in your chrome browser. And make sure that Developer Mode is activated on the top right side of the screen.
  • Click Load Unpacked and target the dist folder in your project.

It will bring up your extension on the screen.

  • Click the extension icon on the right side of the Chrome toolbar. And pin the extension to the toolbar.

6. Enjoy

--

--

Responses (11)