Vite + Vue3 + TS + VScode + Volar, who knows? Ok, I used it, I do know, I can do it again, I learned to move.
Introduction:
- What is the
Vue3
οΌThe official documentation - What is the
Element-plus
Github - What is the
Vite
? Next generation front-end development and build tools - What is the
Chrome Extension
οΌChrome expand - What is the
Volar
? Github
This article will not focus too much on the basic use of plug-in internal logic and technology stack. It will cover how to develop a real project from scratch using Vite and Vue3, as well as some of the code design trade-offs and packaging problems encountered in the build and their solutions. About the choice of technology stack, no skills, my project I say calculate, I want to use which on which π.
Start with request interception π€
The bridge between the front-end and the back-end Battle is Ajax requests, which can be connected to the back-end services along the network cable. In a webApp, we almost always use some means to intercept requests, such as mixing some public parameters tokenUID, encrypting some data, deleting some data, and even canceling some requests. Or request response interception, such as unified error code handling, unified data formatting and so on. In the community, the well-known Axios provides two of the above Interceptors to unify the pre – and post-data reporting sessions. So how can we intercept requests without Axios? Some students said, “You can modify the XHR prototype method, you can replace the original fetch, to magic change ~” yes, but I don’t need to. Today I’m going to show you the ability to block requests using Chrome Extension. Damn it, I did it again!
Say dry dry πΆ
Initialize the warehouse
A few key points to remember:
- The product of Chrome Extension is multiple HTML, so we want to create a multi-page Vite project, powerful Vite already support
- The packaged product must have
manifest.json
This is equivalent toChrome ExtensionEntry file, each releaseversion
Automatic + 1
Create a project
yarn create @vitejs/app
Copy the code
Follow the prompts to create a vuE-TS project.
createmanifest.json
{
"name": "Bad Request"."version": "0.0.0"."description": "Bad Request"."permissions": [
"activeTab"."declarativeContent"."storage".// Get the storage permission to store the API link we want to intercept
"webRequest".// Get read permission to get things done
"webRequestBlocking".// Get request abort permission to abort the request
"<all_urls>" // Get permissions on all urls]."background": {
"page": "background/index.html"."persistent": true // Make sure background.js is always running in the background and intercepting is always in effect
},
"options_page": "options/index.html"."content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"."page_action": {
"default_title": "request"."default_icon": "images/logo.png"."default_popup": "popup/index.html"
},
"devtools_page": "devtool/index.html"."icons": {
"16": "images/logo.png"."32": "images/logo.png"."48": "images/logo.png"."128": "images/logo.png"
},
"manifest_version": 2."content_scripts": [{"matches": [
"<all_urls>"]."js": [
"content.js"]]}}Copy the code
It was transformed into a multi-entrance project
Then according to the official Vite documentation to transform it into a multi-page project. The multi-page vite.config.ts is as follows:
export default defineConfig{
// other setting...
build: {
rollupOptions: {
input: {
/** * Click the plug-in icon popup window ** /
popup: resolve(__dirname, 'popup/index.html'),
/** * Chrome Devtool Pane ** /
devtoolPage: resolve(__dirname, 'devtoolPage/index.html'),
/** * The plugin's core JS is always active in the background, listening for all requests ** /
background: resolve(
__dirname,
'background/index.html'
),
/** * Load the portal for chrome DevTool Pane ** /
devtool: resolve(__dirname, 'devtool/index.html'),
/** * Plug-in setup page ** /
options: resolve(__dirname, 'options/index.html'),
/** */ ** */
content: resolve(__dirname, 'src/content.ts'),},output: {
entryFileNames: '[name].js',}}},// other setting...
}
Copy the code
The introduction ofElement Plus
According to its official documentation, the configuration of Vite load on demand, the configuration of Vite.config.ts is as follows:
export default defineConfig{
// other setting...
plugins: [
vue(),
styleImport({
libs: [{libraryName: 'element-plus'.esModule: true.ensureStyleFile: true.resolveStyle: (name) = > {
return `element-plus/lib/theme-chalk/${name}.css`
},
resolveComponent: (name) = > {
return `element-plus/es/${name}`},},],},// other setting...
}
Copy the code
Element Plus pins don’t poke! Big work done, let us happy development ~
How do I block requests in Chrome Extension? π
One line of code is enough
Put a line like this in background.ts:
chrome.webRequest.onBeforeRequest.addListener( handlerRequest, { urls: [' < all_urls > '],}, / / definition for what permissions [' blocking ', 'requestBody', 'extraHeaders'])Copy the code
In the handlerRequest, we get the Details argument. Depending on the return value of this function, Chrome does the following:
return { redirectUrl:
newurl}
, forward the requestreturn { cancel: true }
.abort
request
/ / the type is chrome. WebRequest. WebRequestDetails
function handlerRequest(
details: chrome.webRequest.WebRequestDetails
) {
// Note that proxy and block need to be defined by yourself
/** * proxy forward */
if (proxy) {
return {
redirectUrl: details.url.replace(
proxy.origin,
proxy.target
),
}
}
/** * request to intercept ** /
if (block) {
return { cancel: true}}}Copy the code
Master pass, point so far; Intercepting a request is as simple as that.
Add some details π
Once we know how, we can refine our overall plug-in requirements
- Supports interception of corresponding requests, such as to
www.baidu.com
Request or compare key interfaces - Make a switch for blocking. We can turn blocking on or off. Click the plugin icon to pop up the switch
- Listen for special requests, such as buried requests, and log our buried flow in a new DevTool Pane
After reviewing these three requirements, let’s make the design draft. Let’s make the design draft of the plug-in popover and devtoolPane first
π π π π
The design is ready, above
Popup window
Use Element-Plus for basic layout and form controls
devtool Pane
Reference Vue Devtool panel to do the design
Switch code design
- Use the built-in storage of Extension. Similar to localStorage, the switch status is stored
backgroud.js
The stored value can be read to determine whether to intercept- Read this storage every time you activate Chrome Extension Popup and display it
The code is as follows:
<! -- I also use setup syntax sugar -->
<script setup lang="ts">
import {
ElIcon,
ElForm,
ElFormItem,
ElInput,
ElSwitch,
} from 'element-plus'
import { ref, watch } from 'vue'
/** * Storage status */
function saveCurrentStatus(
type: string,
value: boolean | string | Array<any>
) {
// eslint-disable-next-line no-undefchrome.storage? .sync? .set({ [type]: value },() = > {
console.log('Setup successful')})}// Define the switch
const blocking = ref(false)
// Use Vue 3's watch to store the state each time the value changes
watch([blocking], () = > {
saveCurrentStatus('blocking', blocking.value)
})
Setup is equivalent to the Created lifecycle
const initStatus = () = > {
conststorage = chrome.storage? .sync storage? .get('blocking'.(data) = > {
blocking.value = data.blocking || false
})
}
initStatus()
<script>
<template>
<el-form>
<el-form-item label="Intercept" size="mini">
<el-switch
v-model="blocking"
active-color="#2F86F6"
/>
</el-form-item>
</el-form>
</template>
Copy the code
Background.js listens for storage changes
/** * listen for storage changes */
chrome.storage.onChanged.addListener((changes) = > {
console.log(changes)
})
Copy the code
DevtoolPane code design
The key here is the communication between background.js and devtoolPane, which is easy to PostMessage
- DevtoolPane creates the connection and sends the message
const backgroundPageConnection = chrome.runtime?.connect({
name: 'devtool-page', }) backgroundPageConnection? .postMessage({name: 'init'.tabId: chrome.devtools.inspectedWindow.tabId, // Currently devtoolPane tabId
})
Copy the code
background.js
Interface message, get the Pane
let devtool = null
const connections: Record<string.any> = {}
chrome.runtime.onConnect.addListener((port) = > {
port.onMessage.addListener(message= > {
if (message.name === 'init') {
connections[message.tabId] = port
devtool = port
}
})
})
// Then use Devtool to send messages to and from the devtoolPane
// Here we send the request body of the buried point to parse
function devtoolandler(details: any) {
devtool && devtool.postMessage(details)
}
Copy the code
Build and publish π¦
Json version +1 = manifest.json version +1 = manifest.json version +1 = manifest.json
- copy, the use of
rollup-plugin-copy
After each build, copy the file todist
Very soon
The configuration of vite.config.ts is as follows
export default defineConfig{
// other setting...
plugins: [
copy({
verbose: true,
hook: 'writeBundle',
targets: [
{
src: 'manifest.json',
dest: 'dist',
},
],
}),
],
// other setting...
}
Copy the code
-
The version number automatically increases by 1
- Upgrade the version number with Node-semver
- Use sed or node fs to modify the file
-
Once you’ve built it, you need to compress the entire Dist, which is required to publish it in the Chrome Extension Store
To sum up, we get our release script
#! /usr/bin/env zx
const semverInc = require('semver/functions/inc')
let manifest = require('.. /manifest.json')
console.log(
chalk.yellow.bold(`Current verion: ${manifest.version}`))let types = ['patch'.'major'.'minor']
let type = await question(
chalk.cyan(
'Release type? Press Tab twice for suggestion \n'
),
{
choices: types,
}
)
let version = ' '
if (type! = =' ' || types.includes(type)) {
version = semverInc(manifest.version, type)
console.log(
chalk.green.bold(`Release verion? ${version}') // Use the sed command to change version $' sed -i' ' s/${manifest.version}/${version}/g manifest.json`
} else {
await $`exit'} // build await $' yarn build '// git await $' git add.' await $' git commit -m'Update version to ${version}'`
await $`git tag v${version}`
await $`git push origin refs/tags/v${version}`
await $`git push origin HEAD:refs/for/master '// compress await $'cddist && zip -r bundle.zip * && mv bundle.zip .. / `Copy the code
Then you can go to the Chrome Extension Store and publish
Note:
- Developers need to pay$5, can publish the code toChrome Extension Store
- Review time is variable, and it can be a long time during the pandemic, as Google is on holiday every day
So far, I have used Vue3+ Element Plus + TS + Vite to develop a Chrome Extension. The efficiency is very high, the code is very handsome, I did not cheat me.
yyx! yyds!
Finally, what would you like to teach the author, direct message, welcome you to communicate with me ~
π