-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chrome Extension Chapter 2 #105
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,64 @@ | ||||||||
--- | ||||||||
title: Job Hunting and ChatGPT - A Developer's Journey | ||||||||
published: false | ||||||||
description: Preface to give you a context of how I ended up making a Chrome extension for scraping | ||||||||
tags: 'Scrapping' | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
cover_image: ./assets/extension_chapter_1_img2.png | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ideally, the resolution of the cover image is |
||||||||
--- | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use the You should give it a common title, and on the devto page you will be able to see them together! I leave you a reference in code and the article
Suggested change
|
||||||||
|
||||||||
"A phrase that has stayed with me to this day is that job hunting as a developer is a numbers game." | ||||||||
|
||||||||
Warning: This article is not about technical guides, but rather a preface to give you a context of how I ended up making a Chrome extension for scraping. | ||||||||
|
||||||||
### The Tech Sector is... hard to explain | ||||||||
 | ||||||||
|
||||||||
Unlike many, I had an easy start in my programming career. My first and second jobs almost fell into my lap. But from my third job onwards, it was like hitting a concrete wall. | ||||||||
|
||||||||
When my second job ended, the pandemic began three weeks later, leading to a hiring freeze. After 1, 2, 3, 4 months, things didn't improve. I started job hunting again and it took 8 months. I wondered if I was the problem. | ||||||||
|
||||||||
Looking back, I lacked certain skills, but the real issue was the broken recruitment system. At 15, I was already soldering electronic boards and programming chips in C++. Yet at 21, with more experience, I struggled to find a job. It was frustrating and I don't think it will be the last time. | ||||||||
|
||||||||
### Scrapping and Form Filling | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
Job hunting was tough. I had responsibilities: no children, but three cats, a beautiful dog, and a wife. What would you do if you lost your job, had a family to feed, and knew the market was laying off? | ||||||||
|
||||||||
I practiced LeetCode problems, but that's useless without technical interviews. To have stressful interviews about data structures you won't use daily, you first need an invitation to the meeting. | ||||||||
|
||||||||
I'm a developer; I create solutions. Manual job applications are time-consuming. | ||||||||
|
||||||||
 | ||||||||
|
||||||||
The process involves: | ||||||||
|
||||||||
Uploading a CV and then filling in the same information manually. | ||||||||
Sifting through job feeds to find relevant ones. | ||||||||
Communicating with recruiters, refilling forms manually. | ||||||||
Finding a job that matches your profile but... it's in India. Why is it listed in Spanish? | ||||||||
So, I started creating solutions. | ||||||||
|
||||||||
Last year, I automated my job search process. If job hunting is a numbers game, the more applications and interviews, the better. Ironically, I didn't create any useful tools - at least none that were easy and adaptable. | ||||||||
|
||||||||
My First Use Case: LinkedIn's limited filters were a problem. Many job posts were for or from India, which didn't interest me. I wanted an automatic solution. | ||||||||
|
||||||||
 | ||||||||
|
||||||||
I looked for a scraper to save information and filter it automatically with ChatGPT. Not finding what I wanted, I created my own solution. | ||||||||
|
||||||||
Puppeter as a Mediocre Scraper | ||||||||
I had done small scraping projects before and chose to use Node instead of an existing tool. Scraping for cars on a website without login requirements is different from scraping LinkedIn, where you need to be logged in and avoid getting banned. | ||||||||
|
||||||||
The Final Question: How to scrape LinkedIn? Most tools use Chromium with Puppeter, but logging in, especially with Google, and possibly dealing with CAPTCHAs, was overly complex. The easiest way was to control the browser directly since I was already logged in. | ||||||||
|
||||||||
But, when I had to change PCs and redo the setup for Puppeter, I realized it was time to move on to something else. | ||||||||
|
||||||||
Chrome Extensions: A Hassle | ||||||||
 | ||||||||
|
||||||||
Chrome extensions consist of three parts: | ||||||||
|
||||||||
The Popup | ||||||||
The Backend | ||||||||
The Content | ||||||||
The popup and backend are fully controllable, allowing installations, WebSocket connections, and requests. The content is JavaScript you can run in your browser tab, but with limitations. | ||||||||
|
||||||||
My Conclusion: I'll discuss the best way to work with Chrome extensions and ChatGPT in the next article. The less code the extension has, the better. Gather data through the content, communicate it to the backend, then connect with sockets to a Node server, linking the popup to the socket and server. |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,273 @@ | ||||||||
--- | ||||||||
title: Building a Chrome Extension with React, TypeScript, and Sockets - A Comprehensive Guid | ||||||||
published: false | ||||||||
description: Learn how to create a powerful Chrome extension with React, TypeScript, and Sockets for seamless web interactions | ||||||||
tags: 'chrome_extensions, react, typescript' | ||||||||
cover_image: ./assets/extension_chapter_2_img2.png | ||||||||
--- | ||||||||
|
||||||||
# Create an chrome extension with React, Typescript and Sockets | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
Before you i give you the context of what were my particular needs for this chrome extension, now i going to give you a How to create it. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
I don't need to explain you why someone would prefer to work with react and not with vanilla html, css and javascript instead in the extensions's UI. **But Why to use Sockets?** | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
First of all, here you have how to config the project, you can read the explanation here **after** | ||||||||
|
||||||||
## Project configuration | ||||||||
|
||||||||
yarn create react-app my-extension --template typescript | ||||||||
|
||||||||
### 1 - Project creation | ||||||||
|
||||||||
``` | ||||||||
### with yarn | ||||||||
yarn create react-app my-extension --template typescript | ||||||||
``` | ||||||||
|
||||||||
``` | ||||||||
### npm | ||||||||
npx create-next-app@latest my-extension --template typescript | ||||||||
``` | ||||||||
|
||||||||
### 2 - Dependencies | ||||||||
|
||||||||
``` | ||||||||
yarn add webextension-polyfill | ||||||||
yarn add -D @types/webextension-polyfill | ||||||||
yarn add -D @types/chrome | ||||||||
yarn add -D customize-cra react-app-rewired | ||||||||
``` | ||||||||
|
||||||||
### 3 - Main files configuration | ||||||||
|
||||||||
You have to move everything from create-react-app `App.*` to popup src/ | ||||||||
|
||||||||
src/ | ||||||||
├── popup/ | ||||||||
├── ├── App.css | ||||||||
├── ├── App.test.js | ||||||||
├── ├── App.tsx | ||||||||
├── ├── index.css | ||||||||
├── ├── index.tsx | ||||||||
├── ├── logo.svg | ||||||||
├── ├── reportWebVitals.js | ||||||||
├── ├── setupTests.js | ||||||||
├── background/ | ||||||||
│ ├── index.ts | ||||||||
├── content/ | ||||||||
│ ├── index.ts | ||||||||
├── config-iverrudes.js | ||||||||
└── public/ | ||||||||
└── manifest.json | ||||||||
Create folder structure | ||||||||
Comment on lines
+46
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Format this with a code-block as well |
||||||||
|
||||||||
``` | ||||||||
mkdir popup | ||||||||
cd src && mv * ../popup && cd .. && mv popup src | ||||||||
|
||||||||
touch src/index.ts | ||||||||
echo "import './popup/index'" > src/index.ts | ||||||||
|
||||||||
mkdir -p src/background | ||||||||
touch src/background/index.ts | ||||||||
echo "console.log('hello from background'); export {}" > src/background/index.ts | ||||||||
mkdir -p src/content | ||||||||
touch src/content/index.ts | ||||||||
echo "console.log('hello from content'); export {}" > src/content/index.ts | ||||||||
touch config-overrides.js | ||||||||
``` | ||||||||
|
||||||||
*** | ||||||||
|
||||||||
Create `rootApp/config-overrides.js` | ||||||||
|
||||||||
``` | ||||||||
const { override } = require('customize-cra') | ||||||||
|
||||||||
const overrideEntry = (config) => { | ||||||||
config.entry = { | ||||||||
main: './src/popup', // the extension UI | ||||||||
background: './src/background/index.ts', | ||||||||
content: './src/content/index.ts', | ||||||||
} | ||||||||
|
||||||||
return config | ||||||||
} | ||||||||
|
||||||||
const overrideOutput = (config) => { | ||||||||
config.output = { | ||||||||
...config.output, | ||||||||
filename: 'static/js/[name].js', | ||||||||
chunkFilename: 'static/js/[name].js', | ||||||||
} | ||||||||
|
||||||||
return config | ||||||||
} | ||||||||
|
||||||||
module.exports = { | ||||||||
webpack: (config) => override(overrideEntry, overrideOutput)(config), | ||||||||
} | ||||||||
``` | ||||||||
|
||||||||
*** | ||||||||
|
||||||||
Modify `rootApp/public/manifest.json` | ||||||||
|
||||||||
``` | ||||||||
{ | ||||||||
"short_name": "React App", | ||||||||
"name": "Create React App Sample", | ||||||||
"icons": { | ||||||||
"16": "favicon.ico", | ||||||||
"192": "logo512.png", | ||||||||
"512": "logo512.png" | ||||||||
}, | ||||||||
"manifest_version": 3, | ||||||||
"version": "1.0", | ||||||||
"background": { | ||||||||
"service_worker": "./static/js/background.js" | ||||||||
}, | ||||||||
"content_scripts": [ | ||||||||
{ | ||||||||
"matches": ["<all_urls>"], | ||||||||
"js": ["./static/js/content.js"] | ||||||||
} | ||||||||
], | ||||||||
"action": { | ||||||||
"default_popup": "index.html" | ||||||||
}, | ||||||||
"permissions": ["storage", "tabs", "activeTab", "scripting","nativeMessaging"] | ||||||||
} | ||||||||
``` | ||||||||
|
||||||||
*** | ||||||||
|
||||||||
Modify Scripts in `package.json` | ||||||||
|
||||||||
``` | ||||||||
"scripts": { | ||||||||
"build": "INLINE_RUNTIME_CHUNK=false react-app-rewired build", | ||||||||
} | ||||||||
``` | ||||||||
|
||||||||
*** | ||||||||
|
||||||||
Modify Popup layout size `src/popup/index.css` | ||||||||
|
||||||||
``` | ||||||||
html { | ||||||||
width: 720px; | ||||||||
height: 480px; | ||||||||
} | ||||||||
body { | ||||||||
margin: 0; | ||||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', | ||||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', | ||||||||
sans-serif; | ||||||||
-webkit-font-smoothing: antialiased; | ||||||||
-moz-osx-font-smoothing: grayscale; | ||||||||
width: 100%; | ||||||||
height: 100%; | ||||||||
padding: 2%; | ||||||||
} | ||||||||
|
||||||||
code { | ||||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', | ||||||||
monospace; | ||||||||
} | ||||||||
``` | ||||||||
|
||||||||
After that build it | ||||||||
|
||||||||
``` | ||||||||
yarn build | ||||||||
``` | ||||||||
And with that you are gonna have your extension configured with React | ||||||||
 | ||||||||
|
||||||||
## Explanation | ||||||||
So... my head is bumping, i spend more than 3 hours writing this and i know you are gonna read it in 5 minutes or less, F*** me. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
So, what we just did? | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
### What is an Extension | ||||||||
An extension is just a folder with a manifest.json file and some more stuff, but the basic things is the manifest.json. | ||||||||
|
||||||||
folder/ | ||||||||
└── logo.png | ||||||||
└── index.html | ||||||||
└── manifest.json | ||||||||
|
||||||||
manifest.json | ||||||||
``` | ||||||||
{ | ||||||||
"manifest_version": 3, | ||||||||
"name": "Hello Extensions", | ||||||||
"description": "Base Level Extension", | ||||||||
"version": "1.0", | ||||||||
"action": { | ||||||||
"default_popup": "index.html", | ||||||||
"default_icon": "logo.png" | ||||||||
} | ||||||||
} | ||||||||
``` | ||||||||
|
||||||||
index.html | ||||||||
``` | ||||||||
<html> | ||||||||
<body> | ||||||||
<h1>Hello Extensions</h1> | ||||||||
</body> | ||||||||
</html> | ||||||||
``` | ||||||||
*** | ||||||||
|
||||||||
|
||||||||
After installed, you have your extension | ||||||||
 | ||||||||
|
||||||||
But you want to create a react extension. So what you did was: | ||||||||
1. Change your React manifest.json to be valid as an extension | ||||||||
2. Move your CRA content to Popup | ||||||||
3. Create content and backend for the extension | ||||||||
4. Build everything separatly with customize-cra and react-app-rewired | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
5. Build and run | ||||||||
6. Also and PD. You install webextension-polyfill and some types to make typescript able to use Chrome API | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this step 6 correct? doesn't seem to follow what happened above |
||||||||
|
||||||||
### What is popup, content and backend and why build everything separtly? | ||||||||
1. The popup that you see when you click the icon in the toolbar. | ||||||||
2. The content scripts that run on top of an existing website. | ||||||||
3. The background scripts that run in the background of Google Chrome. | ||||||||
|
||||||||
*** | ||||||||
#### Popup | ||||||||
This is a webpage you can create and is going to run when user click in the extension icon in the toolbar, you can put js, css, html, and more types of files. With the popup you can interact with the chrome API also. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
*** | ||||||||
#### Backend | ||||||||
This is a script that is going to be running from the moment you install the extension, and you have all the control over it, it can comunicate with the popup and the content. | ||||||||
|
||||||||
*** | ||||||||
|
||||||||
#### Content | ||||||||
This is also an script but in this case is isolated from the backend and the popup, in this case is the only one who is going to be able to run and interact with the web application running in the tab. In is limited but it can interact with the backend. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
*** | ||||||||
|
||||||||
At least content and backend files cannot interact with each other so that's why we use react-app-rewired and customize-cra to separate Popup files from, Backend files and Content files. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
## Why and how to use sockets in Chrome extensions? | ||||||||
|
||||||||
Every change you make you have to build everything again. And this is going to cost you time, a lot of time so i prefer to do the less in the extension and have an external server and control everything with Websockets. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
Imagine you have a list of objects saved in a DB and you what to scrappe, how are you going to interact with the WebPage UI with the extension from the server. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
Short answer, by default you can't, you have to connect the content to the backend and the backend with sockets to the server. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
The server code when you update it is going to run continusly and is not going to require to build again and again, also it gives you the chance to have all the pros of having an external application without the cons of the extension time consuming in the construction. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
When you use sockets, you can connect the popup, the backend, the content and the server, fast and "easy" (is easy after you already implemented). | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
So, how to implement sockets? :) :) :) :) :) :) :) | ||||||||
I going to tell you in the next chapter... | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe you can apply other tags!
JobHunting
ChatGPT
ChromeExtension
WebScraping
Automation
LinkedIn
It would be nice to have the same tags in both articles! since they would be part of the same series
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe dev.to only supports 4 tags max