利用 Vite 将 JavaScript 打包成书签工具 Bookmarklet

利用 Vite 将 JavaScript 打包成书签工具 Bookmarklet

传送:书签工具打包器 bookmark-script-builder

Bookmarklet

Bookmarklet 是由 Bookmark(书签)Applet(小程序) 组合而来。 Bookmarklet 可以翻译为: 书签小程序书签工具等

浏览器收藏栏基本用于收藏网页,但除了支持网页收藏栏还可以支持别的协议,比如用浏览器打开本地一个文件也能收藏。

常见支持协议

HTTPHTTPS:访问和浏览网页。 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

  1. 编写通用代码打包器:简单包装一下Vite,让其可以指定入口,打包格式等
  2. 代码格式转换:将Vite打包好的代码转换到 Bookmarklet 格式
  3. 将 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.tsbm.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 组件到 BookmarkletReact 同理

添加插件 @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

玩的开心 🎉🎉🎉🎉

相关推荐
小许_.5 天前
vite+vue3快速构建项目+router、vuex、scss安装
前端·css·vue3·vite·scss
唯之为之8 天前
vue3项目部署到Github
vue·github·pnpm·vue3·vite
williamdsy11 天前
【vite-plugin-vuetify】自动导入 vuetify 组件和指令
vite·plugin·vuetify·自动导入
whyfail16 天前
在 Vite 项目中自动为每个 Vue 文件导入 base.less
前端·less·vite
har01d17 天前
vue3,扫雷
开发语言·javascript·vue·ecmascript·vite
Vgbire24 天前
我把前端部署用户提醒做成了一个npm包
前端·webpack·性能优化·npm·vite·打包优化·webpack优化
威哥爱编程1 个月前
为什么用Vite框架?来看它的核心组件案例详解
前端·javascript·vite
站在顶峰看星星1 个月前
React + Vite项目别名配置
前端·webpack·typescript·vue·react·vite·angular
奶昔不会射手1 个月前
nuxt3学习
前端·vite·nuxt3
泡泡码客2 个月前
vite instanceof 失效
前端·javascript·webpack·vite