利用 Vite 将 JavaScript 打包成书签工具 Bookmarklet
传送:书签工具打包器 bookmark-script-builder
Bookmarklet
Bookmarklet
是由 Bookmark(书签)
和 Applet(小程序)
组合而来。 Bookmarklet
可以翻译为: 书签小程序
,书签工具等
。
浏览器收藏栏基本用于收藏网页,但除了支持网页收藏栏还可以支持别的协议,比如用浏览器打开本地一个文件也能收藏。
常见支持协议
HTTP
,HTTPS
:访问和浏览网页。 FTP
:FTP文件传输的协议,浏览器中也可以打开和访问文件。 JavaScript
:在浏览器中也可以将 JavaScript 代码片段添加到收藏栏中,用于执行特定的操作或运行脚本。
Bookmarklet 格式
text
# 格式:
javascript: (JavaScript 代码);
# 例如:
javascript: alert("hello world");
注意: Bookmarklet 可以看作把代码注入到网页执行, 所以最好还是编写自执行函数来避免环境污染
js
(()=>{
// code
alert("hello world");
})();
利用 Vite
打包代码
简单的需求:可以自行编写JavaScript
代码添加协议
复制到书签栏
就可以了。
复杂的需求:则可以祭出神器Vite
将代码压缩,打包成Bookmarklet
格式,然后直接将Bookmarklet
拖入书签栏,或者将带有Bookmarklet
的书签文件html
直接导入浏览器岂不美哉。
原理可行,那就开始吧。
定制 Vite
功能,实现自己的 Bookmarklet
打包工具
由于Vite
默认入口是index.html
不太符合需求,于是直接使用Vite中的内置打包器编写一个通用代码打包工具,这样就可以打包代码了 js
ts
- 编写通用代码打包器:简单包装一下Vite,让其可以指定入口,打包格式等
- 代码格式转换:将Vite打包好的代码转换到 Bookmarklet 格式
- 将 Bookmarklet 添加到书签HTML中,方便导入浏览器和浏览
通用代码打包器
ts
// build.ts
import { AliasOptions, InlineConfig, build as viteBuild } from 'vite';
import { ExternalOption, OutputChunk, OutputOptions, RollupOutput } from 'rollup';
import path from 'node:path';
/**
* 打包代码配置
*/
export type BuildScriptOptions = Pick<
InlineConfig,
'logLevel' | 'plugins' | 'envDir' | 'envPrefix' | 'mode'
> & {
/**
* 入口
*/
input: string
/**
* 输出配置
*/
outputOptions?: OutputOptions
/**
* 排除模块
*/
external?: ExternalOption
/**
* 路径别名
*/
alias?: AliasOptions;
/**
* 是否压缩代码
*
* @default false
*/
minify?: boolean
}
/**
* 打包结果
*/
export type BuildScriptRes = Pick<OutputChunk, 'code'>;
/**
* 打包代码 vite
* @param options 打包配置
* @returns 打包结果
*/
export async function build(options: BuildScriptOptions): Promise<OutputChunk> {
const {
input, envDir, envPrefix, logLevel = 'error', plugins, outputOptions,
external, alias, mode, minify
} = options;
const inlineConfig: InlineConfig = {
logLevel,
mode,
envDir,
envPrefix,
plugins,
resolve: {
alias
},
build: {
// 不写入文件
write: false,
// 禁用css拆分
cssCodeSplit: true,
// 静态资源内联
assetsInlineLimit: () => true,
minify: minify ? 'terser' : false,
// 压缩配置
terserOptions: {
format: {
// 排除全部注释
comments: false,
}
},
rollupOptions: {
input,
preserveEntrySignatures: 'strict',
external,
output: {
name: path.basename(input),
...outputOptions
},
}
}
};
const res = await viteBuild(inlineConfig);
const rollupOutput = Array.isArray(res) ? res[0] : res;
return (<RollupOutput>rollupOutput).output[0];
}
代码格式转换
ts
import { build as viteBuild } from './build'
import fs from 'node:fs'
(async () => {
const { code } = await viteBuild({
input: 'xxx.ts',
mode: 'dev',
minify: true,
outputOptions: {
// iife 自执行格式
format: 'iife'
},
});
// 添加格式 特殊字符转换
const bookmarklet = `javascript:${encodeURIComponent(code)}void(0);`
// 保存文件
fs.writeFileSync('dist/xxx.txt', bookmarklet, 'utf-8');
})()
将 Bookmarklet
添加到 书签HTML
中
书签HTML格式特殊,切记不可格式化文件(标签不是成对出现,格式化后无法浏览器识别),格式大致如下:
html
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
DO NOT EDIT! -->
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Bookmarklet</TITLE>
<H1>Bookmarklet</H1>
<!-- 其他部分随意修改,经过测试可以添加 js 代码, css 样式 -->
<!-- 以下部分格式固定,请勿格式化,更改缩进 -->
<DL><p>
<DT><H3 PERSONAL_TOOLBAR_FOLDER="true"></H3>
<DL><p>
<DT><H3>搜索</H3>
<DL><p>
<DT><A HREF="https://www.baidu.com" ICON="https://www.baidu.com/favicon.ico">baidu</A>
</DL><p>
</DL><p>
</DL><p>
<!-- 以上部分格式固定,请勿格式化,更改缩进 -->
而我们要做的就是将 Bookmarklet 代码替换掉 HREF
原本网址链接就可以了
<DT><A HREF="{{Bookmarklet}}" ICON="https://www.baidu.com/favicon.ico">baidu</A>
编写 Bookmarklet Cli工具
上面的代码简单实现了将js代码打包成Bookmarklet功能,那么接下来就可以完整封装一下,编写成cli工具,方便使用。于是就有下面项目bookmark-script-builder
简单使用
添加依赖
shell
npm i @xiaohuohumax/bookmark-script
大致目录结构
txt
project
├── bm.config.ts
├── package.json
├── src
│ ├── index.ts
│ └── time.png
└── tsconfig.json
添加配置文件 bm.config.ts
或 bm.config.js
js
import { defineConfig } from '@xiaohuohumax/bookmark-script';
export default defineConfig({
// 输出目录
outDir: 'dist',
// 书签打包结构, 以及书签脚本入口文件, 图标等
bms: [
{
name: 'show time',
description: ''
href: 'src/time.ts',
icon: 'src/time.png'
}
],
// 其他必要配置
...
});
添加智能提示 (可选) 添加到 tsconfig.json
json
{
"compilerOptions": {
"types": [
"@xiaohuohumax/bookmark-script/client"
],
},
}
编写脚本 src/index.ts
ts
// 也可以使用第三方库 比如: axios, sweetalert2等
// import axios from 'axios';
alert(new Date());
打包构建
修改 package.json
使用 npx bookmark-script --help 可查看其他参数
json
{
"scripts": {
"build": "bookmark-script"
},
}
输出结果
txt
dist
├── favorites.html // 可以通过浏览器直接导入
└── show time
├── bookmark.txt // 书签脚本版本(手动添加至书签)
└── console.js // 控制台版本(F12执行即可)
打包 Vue
组件到 Bookmarklet
,React
同理
添加插件 @vitejs/plugin-vue
ts
import { defineConfig } from '@xiaohuohumax/bookmark-script';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
scans: [{
root: 'src'
}]
});
修改入口文件 src/main.ts
ts
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
// 自己创建 root dom
const root = document.createElement('div');
createApp(App).mount(root);
// 添加到 body 中
document.body.appendChild(root);
最后
用 Cli
实现的一些自用Bookmarklet
bookmark-script
玩的开心 🎉🎉🎉🎉