如何使用工具构建Chrome扩展?How to build a Chrome Extension with tools

作者
ZeroDoCom
分类
计算机 Compute
更新时间
Jan 26, 2023 10:08 AM
外部参考数
2
内部问题链接数
1

背景

Chrome扩展相关文章很多均是围绕普通的HTML和JS来展开的,与当前的前端开发技术栈不匹配,很多人的前端制品均是使用工具来构建产生的。

当前Chrome扩展结构简单的时候,纯HTML的JS的编写也问题不大,但当有了较多的第三方依赖包之后,就会产生巨大的效率差异:

  • 使用构建的方式,可以使用npm方便地来管理依赖。
  • 普通HTML和JS需要一个个将第三方包的CDN地址粘贴进页面中,管理比较困难。

于是使用工具来构建Chrome扩展是个不错的选择。

工具与语言选择

TypeScript + Vue3

  • 使用 TypeScript 开发可以规范工程结构,同时在IDE时也会更加友好。
  • 使用 Vue3 作为单页应用的Web应用主框架,同时配合 Vite 作为构建工具。
  • 使用CRXJS Vite Plugin来使Vite构建的产物能够打包成一个Chrome扩展。

工程生成

参考 Vue Using Vue with TypeScript 中介绍使用方法,使用命令 npm create vue@3 来直接生成工程目录。

image

其中几个选择需要注意:

  • Add TypeScript? YES 否则就是是个ES6的工程。
  • Add Vue Router? YES 创建的时候可以选择安装VueRouter,后续的页面也均是以单页应用的方式展开。VueRouter不熟悉的可以参考Vue Router详细教程

执行完成之后,这个工程就是一个标准的 Vue3+Typescript 工程了。

进入到工程目录之后,我们执行yarn installnpm install 将工程中的依赖都下载下来。

完成之后目录如下图所示

-rw-r--r--    1   1674  1 26 17:14 README.md
-rw-r--r--    1     38  1 26 17:14 env.d.ts
-rw-r--r--    1    331  1 26 17:14 index.html
drwxr-xr-x  230   7360  1 26 17:16 node_modules
-rw-r--r--    1    873  1 26 17:14 package.json
drwxr-xr-x    3     96  1 26 17:14 public
drwxr-xr-x    8    256  1 26 17:14 src
-rw-r--r--    1    219  1 26 17:14 tsconfig.config.json
-rw-r--r--    1    275  1 26 17:14 tsconfig.json
-rw-r--r--    1    300  1 26 17:14 vite.config.ts
-rw-r--r--    1  97022  1 26 17:16 yarn.lock

执行 npm run build 能够看到产出的制品:

$ npm run build

> abc@0.0.0 build
> run-p type-check build-only


> abc@0.0.0 type-check
> vue-tsc --noEmit


> abc@0.0.0 build-only
> vite build

vite v4.0.4 building for production...
✓ 46 modules transformed.
dist/assets/logo-da9b9095.svg        0.31 kB
dist/index.html                      0.42 kB
dist/assets/AboutView-4d995ba2.css   0.09 kB │ gzip:  0.10 kB
dist/assets/index-b9365240.css       4.18 kB │ gzip:  1.31 kB
dist/assets/AboutView-fe92dac1.js    0.23 kB │ gzip:  0.20 kB
dist/assets/index-c7d3f2c1.js       83.97 kB │ gzip: 33.05 kB

这是标准的单页应用的结构,但是这个结构Chrome扩展并不认识,于是我们需要引入一个插件进行Chrome扩展的构建。

关于Chrome扩展的工程结构上有哪些文件?可以参考这个问题 什么是Chrome扩展程序?What is Chrome Extension?

Chrome扩展程序构建

参考 What is CRXJS? 我们知道CRXJS是一个Vite Plugin的插件,能够帮助我们生成符合Chrome扩展要求的制品。

使用下面的命令将crxjs引入:npm i @crxjs/vite-plugin@latest -D

从前面Chrome扩展程序的介绍可以知道, manifest.json 是扩展程序最核心的一个文件,描述了这个扩展程序有哪些资源。是的,这个CRXJS插件也是使用这个文件中的描述,使用vite进行制品生成的。

在工程的根目录下创建一个manifest.json 文件:

{
  "manifest_version": 3,
  "name": "CRXJS Vue Vite Example",
  "version": "1.0.0",
  "action": { "default_popup": "index.html" }
}

然后修改vite.config.ts,加入下面三行代码

import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.json'

// defineConfig 的 plugins 中加入crx
crx({ manifest })

修改完成后 vite.config.ts 的代码如下图所示:

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.json' // Node 14 & 16

export default defineConfig({
  plugins: [
      vue(),
      crx({ manifest })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

然后尝试使用npm run build,会遇到一些问题,下面收集了这个过程中会产生的问题,供大家参考

问题解决:

问题1:放在根目录下的manifest.json 文件无法被使用:

解决1:在tsconfig.config.json中的include字段中加入"manifest.json"

问题2: 构建报错 [ERROR] [plugin externalize-deps] Failed to resolve entry for package "@crxjs/vite-plugin". The package may have incorrect main/module/exports specified in its package.json.

解决2: 在package.json中加入 "type": "module",使用标准的模块方式引用依赖。

构建制品

在解决了上述的问题之后,可以看一下产出的制品已经包含了manifest.json

vite v4.0.4 building for production...
✓ 48 modules transformed.
dist/manifest.json                   0.14 kB
dist/assets/logo-da9b9095.svg        0.31 kB
dist/index.html                      0.43 kB
dist/assets/AboutView-4d995ba2.css   0.09 kB │ gzip:  0.10 kB
dist/assets/index-b9365240.css       4.18 kB │ gzip:  1.31 kB
dist/assets/AboutView-bce53526.js    0.23 kB │ gzip:  0.20 kB
dist/assets/index.html-b820a928.js  83.97 kB │ gzip: 33.05 kB

在浏览器的更多工具 → 扩展程序 中,点击 加载已解压的扩展程序,将目录指向上面制品的产生的dist目录即可:

image

如下图可以看到,一个应用的popup页面已经嵌入了我们在第一步构建出来的vue页面。

image