最近一直在写前端项目、然后又使用strapi在写后端服务,在使用到加解密这快内容,相同的代码需要复制粘贴,索性写一个工具吧,于是带着研究,百度了一番,目前常见的工具有webpack、vite、rollup,相对主流的vite和rollup目前比较流行,webpack实在是卡顿
于是我又找找看看,又翻翻看,看到了tsup,构建方式简单,不用繁琐的配置,这不正是我想要的嘛
介绍一下tsup
tsup 是一个用于打包web脚本的轻量级工具,它基于 esbuild,旨在提供快速且简单的打包体验。tsup 支持多种输出格式,如 CommonJS、ES 模块、UMD 等
特点
- 快速打包:利用 esbuild 的高性能,tsup 能够非常快速地打包 TypeScript 项目
- 多格式输出:支持多种输出格式,包括 CommonJS (cjs)、ES 模块 (esm)、UMD 等
- 零配置:默认情况下,tsup 可以自动检测项目配置并进行打包,无需复杂的配置文件
- 灵活配置:可以通过命令行参数或配置文件进行灵活配置
- 树摇优化:自动进行树摇优化,减少最终包的大小
- TypeScript 支持:原生支持 TypeScript,无需额外配置
看下如何使用
需要先安装它,我们先npm init,初始化基本项目项目环境,然后进行安装
npm i tsup -D
# Or Yarn
yarn add tsup --dev
# Or pnpm
pnpm add tsup -D
安装完成
在根目录下手动建一个tsup.config.ts
文件,这个就是tsup的配置文件,这里我列出我的配置文件
import { defineConfig } from 'tsup';
export default defineConfig([
{
format: ['esm', 'cjs', 'iife'], // 指定输出的模块格式。常见的格式有 esm(ES 模块)、cjs(CommonJS)、iife(立即执行函数表达式)等
entry: ['./example/index.js'], // 指定项目的入口文件。可以是一个或多个文件路径
outDir: 'lib', // 指定输出文件的目录
platform: 'neutral', // 指定目标平台。常见的值有 neutral(中立平台,适用于所有环境)、browser(浏览器环境)、node(Node.js 环境)
globalName: 'WebUtils', //当输出格式为 iife 时,指定全局变量的名称
outExtension({ format }) { // 自定义输出文件的扩展名。接收一个对象参数,包含当前的格式信息
if (format === 'iife') return { js: '.browser.js' };
return { js: `.${format}.js` };
},
minify: true, // 是否启用代码压缩
sourcemap: true, // 是否生成源映射文件
shims: true, // 是否启用 polyfills 和 shims,以确保兼容性
clean: true, // 清理输出目录
dts: true, // 是否生成 TypeScript 声明文件
}
]);
我已经在后面都标注说明了,不要我在解释了吧
编写加解密代码
这里我使用的是crypto-js
、jsencrypt
,两个仓库,一个是对称加密,一个和做非对称加密,这个两个兼容浏览器端和Node.js环境
import CryptoJS from "crypto-js";
import JSEncrypt from "jsencrypt"
/**
* 对称加密
* @param word
* @param iv
* @param key
* @returns {string}
*/
function aesEncrypt(word, iv, key) {
let str = typeof word == "string" ? word : JSON.stringify(word);
const data = CryptoJS.enc.Utf8.parse(str);
const encrypted = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
/**
* 对称解密
* @param word
* @param iv
* @param key
* @returns {string}
*/
function aesDecrypt(word, iv, key) {
const decrypt = CryptoJS.AES.decrypt(word, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return CryptoJS.enc.Utf8.stringify(decrypt);
}
/**
* 获取加密的密钥
* @param iv
* @param key
*/
function getCrypto({iv = '', key = ''} = {}) {
return {
CryptoJS,
iv: CryptoJS.enc.Utf8.parse(iv),
key: CryptoJS.enc.Utf8.parse(key), //16位
}
}
/**
* 非对称加密
* @param str
* @param publicKey
* @returns {*}
*/
const rsaEncrypt = (str, publicKey) => {
let encrypted = new JSEncrypt() // 创建加密对象实例
encrypted.setPublicKey(publicKey) // 设置公钥
return encrypted.encrypt(str) // 对内容进行加密
}
/**
* 非对称解密
* @param str
* @param privateKey
*/
const rasDecrypt = (str, privateKey) => {
const decrypted = new JSEncrypt() // 创建解密对象实例
decrypted.setPrivateKey(privateKey) // 设置私钥
return decrypted.decrypt(str) // 拿私钥解密内容
}
/**
* 非对称生成Key
* @param keySize
*/
const getJSEncrypt = (keySize = '512') => {
const crypt = new JSEncrypt({default_key_size: keySize});
return new Promise((resolve) => {
crypt.getKey(function () {
return resolve({
privateKey: crypt.getPrivateKey(),
publicKey: crypt.getPublicKey()
})
})
})
}
export {
aesEncrypt,
aesDecrypt,
getCrypto,
rsaEncrypt,
rasDecrypt,
getJSEncrypt
}
打包构建
执行npx tsup
构建成功,并且我也生成了lib目录下的文件
测试脚本
我写了个列子进行测试
import {aesEncrypt,aesDecrypt, getCrypto,rasDecrypt,rsaEncrypt,getJSEncrypt} from "../packages/index";
const {iv,key} = getCrypto({
iv: '1234567890123456',
key: '1234567890123456'
})
getJSEncrypt().then((res)=>{
console.log(res)
})
使用node进行测试
node ./lib/index.cjs.js
发现jsencrypt
出现了window,这肯定就不行了哇,node环境那来的window的,如是我逛了下百度,找到了答案,也就是在代码的前面加上window=this
这是打包出来的代码,需要在前面加上window=this
,我先手动加上进行测试
测试正常,这里我生成了一个非对称密钥对
自动加window=this
当实现自动化的时候,我就想到了gulp
, Gulp 是一个流式构建系统,用于自动化前端工作流程。它使用 JavaScript 和 Node.js,通过一系列插件和任务来处理文件和资源,它的特点如下
- 流式处理:Gulp 使用 Node.js 流来处理文件,这意味着文件可以在内存中被处理,而不需要多次读写磁盘,从而提高性能。
- 简洁的 API:Gulp 的 API 非常简洁,易于理解和使用。
- 丰富的插件生态系统:Gulp 拥有庞大的插件生态系统,可以轻松找到你需要的插件,如编译 LESS/SASS、压缩 CSS/JS、图像优化等。
- 任务自动化:Gulp 可以自动化常见的开发任务,如代码检查、文件合并、代码压缩、文件监听等。
使用gulp
在根目录下新建文件gulpfile.js
,内容如下
const {src, dest} = require('gulp');
const insert = require('gulp-insert');
function defaultTask(cb) {
src('lib/index.cjs.js') // 指定要编辑的文件路径
.pipe(insert.prepend('window = this;')) // 向文件开头插入指定的字符串
.pipe(dest('lib')); // 指定输出目录
cb();
}
exports.default = defaultTask
注意gulp的写法,gulp一直在升级,写法和使用方式一直在变化
执行gulp
测试成功
回归功能,完整加解密代码
import CryptoJS from "crypto-js";
import JSEncrypt from "jsencrypt"
/**
* 对称加密
* @param word
* @param iv
* @param key
* @returns {string}
*/
function aesEncrypt(word, iv, key) {
let str = typeof word == "string" ? word : JSON.stringify(word);
const data = CryptoJS.enc.Utf8.parse(str);
const encrypted = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
/**
* 对称解密
* @param word
* @param iv
* @param key
* @returns {string}
*/
function aesDecrypt(word, iv, key) {
const decrypt = CryptoJS.AES.decrypt(word, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return CryptoJS.enc.Utf8.stringify(decrypt);
}
/**
* 获取加密的密钥
* @param iv
* @param key
*/
function getCrypto({iv = '', key = ''} = {}) {
return {
CryptoJS,
iv: CryptoJS.enc.Utf8.parse(iv),
key: CryptoJS.enc.Utf8.parse(key), //16位
}
}
/**
* 非对称加密
* @param str
* @param publicKey
* @returns {*}
*/
const rsaEncrypt = (str, publicKey) => {
let encrypted = new JSEncrypt() // 创建加密对象实例
encrypted.setPublicKey(publicKey) // 设置公钥
return encrypted.encrypt(str) // 对内容进行加密
}
/**
* 非对称解密
* @param str
* @param privateKey
*/
const rasDecrypt = (str, privateKey) => {
const decrypted = new JSEncrypt() // 创建解密对象实例
decrypted.setPrivateKey(privateKey) // 设置私钥
return decrypted.decrypt(str) // 拿私钥解密内容
}
/**
* 非对称生成Key
* @param keySize
*/
const getJSEncrypt = (keySize = '512') => {
const crypt = new JSEncrypt({default_key_size: keySize});
return new Promise((resolve) => {
crypt.getKey(function () {
return resolve({
privateKey: crypt.getPrivateKey(),
publicKey: crypt.getPublicKey()
})
})
})
}
export {
aesEncrypt,
aesDecrypt,
getCrypto,
rsaEncrypt,
rasDecrypt,
getJSEncrypt
}
测试代码
import {aesEncrypt,aesDecrypt, getCrypto,rasDecrypt,rsaEncrypt,getJSEncrypt} from "../packages/index";
const {iv,key} = getCrypto({
iv: '1234567890123456',
key: '1234567890123456'
})
// getJSEncrypt().then((res)=>{
// console.log(res)
// })
//
const privateKey = '-----BEGIN RSA PRIVATE KEY-----\n' +
'MIIBOAIBAAJASj9QjNul1xu4Bpq6MByZJePADyBsoLvoGj+sSLuaPEy4pdJ6lEqW\n' +
'0EjpT1nakDzlwXB1IDHQeeHlga31KkSUKwIDAQABAkAxWlLFvr9G9ELoCPOYRXo7\n' +
'aF9i7q+mTCFlSUvQ8Pr9915Aot8qwjW3tcH0HhRbytikEmZ2esplPd832ie5qRKZ\n' +
'AiEAigM6NID/wtv01bGBbmOgUePeD5UnHbD2IiwnAKcJ6/cCIQCJuLmkVNrOcVNe\n' +
'Fz4vFRqvjOd95XBwlFkI4nfTVC7EbQIgYGPYpwrhlmqhGQ6cY0jZk9geI6v8YdRS\n' +
'U5Oaue3wFAkCIDXE9F3Pb1oYbrcWlgWl1LRja+IAWUTq9lP8r1HH1TaFAiBSZ8oJ\n' +
'Obty329SSgnl7ZICHome91o1BoxwWU5IBRKNaQ==\n' +
'-----END RSA PRIVATE KEY-----'
const publicKey = '-----BEGIN PUBLIC KEY-----\n' +
'MFswDQYJKoZIhvcNAQEBBQADSgAwRwJASj9QjNul1xu4Bpq6MByZJePADyBsoLvo\n' +
'Gj+sSLuaPEy4pdJ6lEqW0EjpT1nakDzlwXB1IDHQeeHlga31KkSUKwIDAQAB\n' +
'-----END PUBLIC KEY-----'
const str1 = aesEncrypt('123456', iv, key)
console.log(str1)
console.log(aesDecrypt(str1, iv, key))
console.log('------')
const str2 = rsaEncrypt('abcdefg', publicKey)
console.log(str2)
console.log(rasDecrypt(str2, privateKey))
执行结果,均没有问题
源码我放在了github上面有兴趣的看一看https://github.com/hangjob/web-utils
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。