Vue3 开发 chrome 插件的心得

772 阅读3分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

前言

公司需要一款爬取网页数据的插件,因此下面是开发中所遇到的问题。

热更新开发

项目的热更新是开发阶段十分重要的部分,能够减少开发的时间成本。由于使用的是 Vue3 开发项目,因此打包工具 是使用 Vite,这里使用到的一个 Vite 的插件 @crxjs/vite-plugin

vite.config.ts

vite.config.ts 的代码配置

import { defineConfig } from "vite";
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin'
import manifest from './src/manifest.json'
import pkg from './package.json'


const isProd = process.env.NODE_ENV === "production"

manifest.name = isProd ? 'ac简历采集插件' : 'ac简历采集插件测试'

const crxOptions = {
  manifest: Object.assign(manifest, {
    version: pkg.version,
  })
}

export default defineConfig({
  build: {
    outDir: isProd ? 'dist/build' : 'dist/dev',
  },
  plugins: [
    vue(),
    crx(crxOptions)
  ]
});

遇到问题

在项目中我使用到了 jquery 技术,因此把 jquery 文件放在项目的目录下面,在 npm run dev 时,插件是 copy 了 src的目录,未进行代码的压缩,因此在开发中可以使用 $, 但是在 npm run build 进行了代码的压缩工作,导致 jquery 文件也进行了一次压缩,因此 build 打出来的包是有问题的。这个时候就需要使用yarn add jquery 就可以使用 import $ from jquery

从中学习到了当使用打包 压缩已经被压缩过的技术,或者要使用 import 不能把包放到本地文件上面,应该 npm install 放到 node_modules 。

fetch 的跨域解决

看了 fetch 解决跨域只需要添加 mode: 'cors'。

let myHeaders = new Headers({
    'Access-Control-Allow-Origin': '*',
    'Content-Type': 'text/plain'
});

fetch(url, {
    method: 'GET',
    headers: myHeaders,
    mode: 'cors'
}) .then((res) => {
    // TODO 
}) 

但是不知道为啥项目配置了,接口请求还是发生了跨域的错误。后面的查阅资料, 只需要在 manifest.json 文件配置:

 "host_permissions": ["http://*/*", "https://*/*", "<all_urls>"]

就可以解决 chrome 插件调用接口时的跨域错误。

为了开发方便也对 fetch 进行了的分装。

import { ElMessage, ElLoading } from 'element-plus';
let baseUrl = import.meta.env.VITE_APP_API;
export default function request(
  method,
  url,
  body = undefined,
  formData = undefined,
  headers = {},
) {
  method = method.toUpperCase();
  if (method === 'GET') {
    // fetch的GET不允许有body,参数只能放在url中
    body = undefined;
  } else if (formData) {
    body = formData;
  } else {
    body = body && JSON.stringify(body);
  }

  let cookie = undefined;
  chrome.storage.local.get(['cookies'], function (res) {
    if (res['cookies']) {
      cookie = res['cookies'];
    }
  });

  headers.Cookie = cookie;

  const loadingInstance = ElLoading.service({
    lock: true,
    text: '请求中...',
    spinner: 'el-icon-loading',
  });

  // response.json() 能获取 接口返回的值,这个是异步的操作,因此搭配上了 async 和 await
  return fetch(baseUrl + url, {
    method,
    headers,
    body,
  }).then(async (response) => {
    loadingInstance.close();
    let res = await response.json();
    if (!res.success) {
      ElMessage.error(res.message || 'error!');
    }
    return res;
  });
}

注意点: fetch的GET不允许有body,参数只能放在url中

cookies 怎么获取保存

 chrome.cookies.getAll(
    { domain: 域名, name: 'uid' },
    (cookies) => {
      chrome.storage.local.set({ cookies: cookies[0].value });
    },
  );

image.png

根据 domain 获取到对应的数组,然后拿到下面的cookies值。

这个cookies是保存在 chrome,域名下的 cookies,不是保存在 popup里面。

登录的时候拿到 cookies 再进行存储到 chrome.storage.local. 这里就分装到了前面的 fetch 代码里面。

最后

插件已经给了公司部门同事使用了,在使用的过程中发现有些同事程序无法运行,因为我使用chrome 最新 V3 的版本进行开发。所以当大家开发插件也是 V3 版本,使用者遇到不知名的 bug 可以让他升级下 chrome的版本。