Nut Mark
Nut Mark is a browser extension to help you collect bookmarks more easily.
Why call "Nut Mark"
I like to collect and organize bookmarks like a squirrel hoards nuts, so I build this browser extension and call it "Nut Mark".
Feature
Nut Mark focus on the following features to make bookmarking step more smoothly and easily
✨ Clean "dirty" URL with one click
✨ Quick search to find the folder to hold the bookmark
Other Bonus features
🎈 Manage bookmarks with a user-friendly interface
🎈 Share bookmarks in different format, like Markdown links, JSON object, images with QR Code
预备技能
本项目使用 Vue(Vue 3.0 版本)和 Chrome 所提供的 API 进行开发(当然还使用了必不可少的前端三大基本技能 HTML、CSS、JavaScript),此外 CSS 主要使用 Tailwindcss 框架。
- HTML
- CSS、Tailwind CSS
- Vue、JavaScript
- Chrome APIs
搭建开发环境
搭建一个使用 Vue + Vite + Tailwindcss 的开发环境,其中开发的扩展程序属于 Manifest V3 版本
项目模板
在终端输入以下命令,使用 Vite 初始化一个项目(提示选择 Vue 作为前端框架)
yarn create vite
说明
本项目采用 Javascript 而不是 TypeScript 进行开发
然后安装依赖包
# 安装依赖包
yarn install
代码规范
为了在项目中使用 ESLint 进行代码规范管理,需要安装 eslint-plugin-vue 模块
npm install --save-dev eslint eslint-plugin-vue
然后在终端输入以下命令进行初始化配置,并根据自己的编程习惯和团队的要求,按照提示设置代码样式规范
eslint --init
提示
对最新的版本的 ESLint(本文更新时 ESLint 的版本是 v8.30.0)还可以使用以下命令来进行初始化配置
npm init @eslint/config
在本项目会采用以下 ESLint 配置项
To check syntax, find problems, and enforece code style
JavaScript modules (import/export)
Vue.js
Browser
&Node
(这里是同时选中,默认选中的是Browser
,使用空格键加选或取消)Use a popular style guide
->Airbnb
(采用 Airbnb 推出的关于 JavaScript 的代码规范)JavaScript
(生成的配置文件采用 JavaScript 格式)
接着会提示确认安装所需依赖的包
最后会在项目的根目录下生成一个 ESLint 配置文件 .eslintrc.cjs
由于在项目中使用的是 Vue3 版本,所以需要打开配置文件 .eslintrc.cjs
进行相应的修改,采用相应的插件对 Vue 的相关代码进行规范
module.exports = {
// ...
extends: [
'plugin:vue/vue3-recommended',
'airbnb-base',
],
// ...
}
另外还需要对 IDE 代码编辑器进行配置
本项目使用的代码编辑器是 VS Code,需要在 📁 文件夹 .vscode
中创建一个文件 settings.json
进行编辑器的 eslint 配置
{
// 在文件保存时对代码进行修正(而且采用 eslint 作为唯一的修正器)
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
// eslint 会对以下类型的文件进行代码修改正
"eslint.validate": [
"javascript",
"vue"
],
}
提示
更多关于使用 ESLint 进行代码规范管理的细节可以参考该 🎬 影片
插件
由于开发扩展程序的项目结构和一般开发网页的项目不同,例如最终 Build 后需要在根目录有一个 manifest.json
文档作为描述/入口文件,以描述扩展程序相关信息和权限。
所以还需要安装一个特殊的插件 CRXJS 以提供引导 Vite 正确打包,以及提供更友好的插件开发体验
在终端输入以下命令安装该插件
# 本项目使用 Vite 3 进行开发
# 该插件对于 Vite 3 版本仍处于 beta 版本,请谨慎使用
yarn add @crxjs/vite-plugin@beta -D
注意
请确保 package.json
文件里的属性 "type": "module"
否则扩展无法根据 vite.config.ts
进行正确的构建
然后在文件 vite.config.js
对 Vite 进行配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { crx } from '@crxjs/vite-plugin' // 引入插件
// 导入 manifest
// 如果 Node 版本是 14 & 16 就采用该方式
import manifest from './manifest.json'
// 如果 Node >=17 就采用以下的方式
// import manifest from './manifest.json' assert { type: 'json' }
export default defineConfig({
plugins: [
vue(),
crx({ manifest }),
],
})
CRXJS 插件会通过自动分析导入的扩展清单 manifest 文件,并将扩展所使用的文件(如 popup page 弹出页面、options page 配置页等)在 Vite 中进行配置,以提供 HMR 热重载、打包优化等更佳的开发体验,一般在 manifest 文件会声明/列出了扩展所使用的大部分页面/文件。
但是也有一些扩展会使用到的页面/文件未包含在 manifest 之中,可以在 vite.config.js
的属性 build.rollupOptions.input
中进行手动的配置追加
export default defineConfig({
build: {
rollupOptions: {
input: {
// 插件首次安装成功后自动弹出的欢迎页面
welcome: 'src/pages/welcome.html',
},
},
},
})
manifest 文件
在根目录(与 vite.config.js
文件处于同一级)创建一个 manifest.json
文件
{
"manifest_version": 3,
"name": "Extension Name",
"version": "1.0.0",
"action": {
"default_popup": "index.html"
}
}
文档 manifest.json
是扩展程序的配置清单,其中包含的常见字段如下
{
"name": "TagDown",
"manifest_version": 3,
"version": "1.0.0",
"description": "TagDown is a bookmark manager.",
"background": {
"service_worker": "src/background/main.js",
"type": "module"
},
"action": {
"default_title": "TagDown",
"default_popup": "src/popup/index.html",
"default_icon": {
"16": "src/assets/images/icon16.png",
"32": "src/assets/images/icon32.png",
"48": "src/assets/images/icon48.png",
"64": "src/assets/images/icon64.png",
"128": "src/assets/images/icon128.png"
}
},
"options_page": "src/options/index.html",
"icons": {
"16": "src/assets/images/icon16.png",
"32": "src/assets/images/icon32.png",
"48": "src/assets/images/icon48.png",
"64": "src/assets/images/icon64.png",
"128": "src/assets/images/icon128.png"
},
"default_locale": "en"
}
提示
根据上一章节的代码可知,扩展的 manifest 文件会被导入到 vite.config.js
配置文件中,先经由 CRXJS 插件进行解析,分析出扩展的 manifest 文件,将扩展所使用的文件正确地到整合到 vite config 配置项中。
所以除了默认的 manifest.json
文件格式作为扩展的清单,采用了 CRXJS 插件的项目,还支持以 manifest.config.js
或 manifest.config.ts
文件作为扩展的配置清单(打包构建时最终也是输出 manifest.json
文件)
如果采用 JavaScript 或 TypeScript 作为扩展的配置清单,利用 CRXJS 插件所提供的方法 defintManifest()
就可以实现参数的动态设置
import { defineManifest } from '@crxjs/vite-plugin'
import packageJson from './package.json' // 导入项目的依赖包管理文件
const { version } = packageJson
// Convert from Semver (example: 0.1.0-beta6)
const [major, minor, patch, label = '0'] = version
// can only contain digits, dots, or dash
.replace(/[^\d.-]+/g, '')
// split into version parts
.split(/[.-]/)
// 设置扩展的配置清单,支持异步函数
export default defineManifest(async (env) => ({
manifest_version: 3,
// 扩展的名称根据环境变量而不同
name:
env.mode === 'staging'
? '[INTERNAL] CRXJS Power Tools'
: 'CRXJS Power Tools',
// 扩展的版本和 package.json 里的版本相关
// up to four numbers separated by dots
version: `${major}.${minor}.${patch}.${label}`,
// semver is OK in "version_name"
version_name: version,
}))
说明
在扩展的 manifest 文件的配置项中,其指定的文件(路径)是基于 Vite 项目的根目录的(与 manifest 文件的实际位置无关)
正确
所以应该采用以下方式(以单词作为开头,即从根目录开始由目录和文件所构成的绝对路径)来指定所使用的文件
{
"options_page": "src/options/index.html",
}
错误
以下则是错误的文件引用/指定,不应该采用先对路径
{
"options_page": "./src/options/index.html",
"devtools_page": "/root/user/.../devtools.html"
}
可以参考 chrome-extension-vite-vue-starter-template 这个模板,它也是采用了 CRXJS 插件
该模板为扩展所使用的每个页面都单独设置一个 Vue 实例,和入口文件 index.html
,如下图所标注的 popup page 弹出页面和 options page 配置页面
所以应该可以 ❓ 删除使用 Vite CLI 自动生成项目模板时,在根目录下的 index.html
文件,以及它所引用的 src/main.js
文件(用于创建 Vue 实例),和对应的根组件 src/app.vue
文件
Tailwind
本项目使用 Tailwindcss 框架对页面进行样式设置,按照官方文档依次执行以下步骤
- 在终端输入以下命令安装 Tailwind CSS 及相关的依赖包shell
yarn add -D tailwindcss postcss autoprefixer
- 在终端输入以下命令初始化 Tailwind CSS 以生成一个配置文件
tailwind.config.js
shellnpx tailwindcss init -p
为了优化项目开发和打包时的文件大小,在 Tailwind CSS 的配置文件中进行相应的设置,以删除未使用的样式代码tailwind.config.jsjs/** @type {import('tailwindcss').Config} */ export default { content: [ './index.html', './src/**/*.{js,vue}', ], theme: { extend: {}, }, plugins: [], };
- 在样式表入口文件通过 Tailwind 指令引入相关的样式src/index.csscss
@tailwind base; @tailwind components; @tailwind utilities;