产品经理又给出难题了——图片插件开发
大厂技术 高级前端 Node进阶
点击上方 程序员成长指北,关注公众号
回复1,加入高级Node交流群
前言
最近做项目的时候,就是产品经理给的图总是很大,不压缩。每天要处理这些图片真的很累哇。于是一怒之下写下了这个「vscode 插件」。「插件核心功能是压缩,然后上传图片」。压缩的网站其实就是「tinypng」 这个网站然后图片压缩后,然后再上传到cdn上,然后然后这个压缩过的url 直接放到我们的粘贴板上。下面跟着我的步伐一步一步来写实现它。先看效果图:
效率对比
开发这个主要是提高团队开发效率, 绝不是为了炫技。看图:
需求分析
可在vscodde的setting中配置上传所需的参数,可以根据个人的需求单独进行配置; 2.在开发过程中可在编辑器中直接选择图片并上传到阿里云将图片链接填写到光标位置;
中文文档
❝一个好的文档可以帮助我们更容易的开发:如果英文比较好的同学可以直接看Vscode英文文档,这里api会比较全,可以找到更简洁的方案实现功能;不过我的话,还是花很久时间找了这篇比较全的中文文档
❞
搭建项目
vscode 插件的开发需要全局安装脚手架:
npm install -g yo generator-code
安装成功后,直接使用对应命令 「yo code」 来生成一个插件工程:
这就开始脚手架页面了,可以选择自己习惯的配置。输入对应的配置 然后 就创建了对应的项目了。
我们看下项目结构:
插件运行
这时候我们先要去测试下我的这个插件到底是不是能够成功运行。在项目根目录按住F5 然后运行 「vscode extension」 ,这时候会出现一个新的vscode 窗口,但是我这里遇到的一个问题就是这个:
我大概理解了下就是vscode 插件的依赖版本比较低:
目前是:
这上面说的很清楚 vscode扩展指定 与其兼容的 vscode 版本兼容 很显然我这里太高了, 给他降级。然后给他换成1.60.2 完美解决
插件运行——成功演示
ok, 怎么查看自己查看插件有没有成功运行呢, 分为3步
F5 开始调试 —— 产生一个新的调试窗口 在新的窗口—— command + shift + P 找到 hello word 点击运行看见弹窗 显示 表示弹窗运行成功
直接看下面的gif 图吧:
这里图太大:加载不出来干
插件开发——配置参数
配置插件的属性面板, 这个主要是要在package.json 配置一些参数
第一个参数我们稍后再讲其实就是对应你注册的自定义command, 下面的配置 其实就是对应插件属性面板一些参数,然后你可以通过vscode 的一些api 可以获得你配置的这些参数
下面我是我配置的参数,你可以会根据插件自定义去调整
"properties": {
"upload_image.domain": {
"type": "string",
"default": "",
"description": "设置上传域名"
},
"upload_image.accessKey": {
"type": "string",
"default": "",
"description": "设置oss上传accessKey"
},
"upload_image.secretKey": {
"type": "string",
"default": "",
"description": "设置oss上传secretKey"
},
"upload_image.scope": {
"type": "string",
"default": "",
"description": "设置oss上传上传空间"
},
"upload_image.gzip": {
"type": "boolean",
"default": "true",
"description": "是否启用图片压缩"
}
}
大概就是这几个参数, 然后我们测试下同样打开f5 然后在新窗口 找到设置然后找到扩展, 设置项其实就是对应我们的 上面的「title」
压缩图片。
我们看下效果:
插件开发——配置右键菜单
这个功能描述大概就是,你在写的时候突然要上传,直接点击鼠标右键,然后直接选择图片。对就是这个简单的东西,做东西需要从用户的角度考虑,一定要爽,能省一步是一步。呵呵哈哈哈
这个配置其实就是在 还是在刚才的「package.json」 上继续配置:
"menus": {
"editor/context": [
{
"when": "editorFocus",
"command": "extension.choosedImage",
"group": "navigation"
}
]
}
when:就是你鼠标在编辑的时候
command: 就是自定义的事件,我叫他选择图片, 这个其实就是在extension.js 注册的事件名字 tips:就是对应的事件名称
let texteditor = vscode.commands.registerTextEditorCommand(
'extension.choosedImage', ... )
这个其实就是在extension .js 注册对应的事件名,这里的「事件名」 一定要和 「package.json」 中文件对应不然会出不来的。给大家演示下:
重启插件 按下f5 然后按下右键就有我们自定义的右键菜单了。但是问题来了我们按住右键 是不是得弹出一个选择图片的框哇,不然怎么上传对吧?
打开图片上传 弹框
强大的vscode支持了内置的api, 支持打开:
const uri = await vscode.window.showOpenDialog({
canSelectFolders: false,
canSelectMany: false,
filters: {
images: ['png', 'jpg','apng','jpeg','gif','webp'],
},
});
就是这个 api, 你可以过滤出想要的图片, 在filters 里面,然后呢 吐出给我们的是对应图片的路径。
我们看下效果:
读取图片数据
其实这个时候我们我们已经有了图片的路径,这时候就要利用 「node.js」的fs 模块 去读取 这个图片的数据 buffer ,这个其实为了方便我们将图片上传到oss 上。代码如下:
const uri = await vscode.window.showOpenDialog({
canSelectFolders: false,
canSelectMany: false,
filters: {
images: ['png', 'jpg','apng','jpeg','gif','webp'],
},
});
let imgBuffer = await fs.readFile(uri[0].path);
这里还涉及到一个就是说:本地图片的名字 进行加密, 不能上传到oss 各种中文啥的, 显示的我们很不专业哇
所以这里写了一个MD5的转换
function md5Name(name) {
const index = name.lastIndexOf('.')
const sourceFileName = name.substring(0, index)
const suffix = name.substring(index)
const fileName = md5(sourceFileName + Date.now()) + suffix
return fileName.toLowerCase()
}
就是将名字搞成花里胡哨的样子,呵呵哈哈哈!
图片压缩
我们得到图片的buffer 数据后其实要对图片要支持压缩, 其实社区里面有很多方案, 这里的话我调研的很多还是决定使用tinfiy, 他也有对应的「node.js」 使用的他主要理由主要是看下面这张图:
对的这家伙支持「apng」, 其他的不是很清楚。但是他不是免费的一个人一个月免费「500」 次, 思考了下还行,我们也用不到辣么多次最终还是考虑用它去实现。
安装
安装npm包并添加到您应用的依赖中,您就可以使用Node.js客户端:
npm install --save tinify
认证
您必须提供您的API密钥来使用API。您可以通过注册您的姓名和Email地址来获取API密钥。请秘密保存API密钥。
const tinify = require("tinify");
tinify.key = "YOUR_API_KEY";
这个的话其实就是你的邮箱去注册一下,然后把你对应的「key」 去激活其实就可以了
其实就是下面这个你的key 设置激活就好了
tinify压缩图片
您可以上传任何JPEG或PNG图片到Tinify API来进行压缩。我们将自动检测图片类型并相应的使用TinyPNG或TinyJPG引擎进行优化。只要上传文件或提供图片URL,就会开始压缩。
您可以选择一个本地文件作为源并写入到另一个文件中。
const source = tinify.fromFile("unoptimized.webp");
source.toFile("optimized.webp");
您还可以从缓冲区(buffer)(二进制字符串)上传图片并获取压缩后图片的数据。
const fs = require("fs");
fs.readFile("unoptimized.jpg", function(err, sourceData) {
if (err) throw err;
tinify.fromBuffer(sourceData).toBuffer(function(err, resultData) {
if (err) throw err;
// ...
});
});
代码实现
function compressBuffer(sourceData, key = 'xxx') {
return new Promise((resolve,reject) => {
tinify.key = key;
tinify.fromBuffer(sourceData).toBuffer(function(err, resultData) {
if(resultData) {
resolve(resultData)
}
if (err) {
reject(err);
}
// ...
});
})
}
基于他这个封装了一个promise, 这个「fromBuffer」 , 到 「toBuffer」 是真的好用。哈哈哈哈很香,记得一定要设置key 不然promise 直接会报错的, 设置key的方法 就在上面👆🏻, 然后这样其实我们就获得了压缩的图片数据了。
上传图片到oss
这里的话其实有的使用七牛云、 有的使用阿里云。去上传图片,或者是ajax 去上传其实都可以
一般都是要获取token 啥的以及各种签名信息,然后直接上传就好了, 然后呢你就可以获得一张图片地址了。代码我就不展示了, 都是前端应该都懂。这里我说下我遇到的一些问题
第一个就是js 跑的 是node js 的环境, 如果使用「FormData」 这个类的话 他直接会报找不到, 这个方法是 undefined, 还有「fetch」, 所以说要去安装对应node js 包 ,我这里使用的是 「cross-fetch」 和 「form-data」
这里我说一下配置的问题就是你在扩展中如何获得的你配置的参数:
"configuration": [
{
"title": "压缩图片",
"properties": {
"upload_image.secretKey": {
"type": "string",
"default": "",
"description": "设置tinify的ApIKey"
},
"upload_image.secretTokenUrl": {
"type": "string",
"default": "",
"description": "设置得物的tokenUrl"
}
}
}
]
每个属性前面对应的 upload_image 其实你在扩展中你可以通过:
const imageConfig = vscode.workspace.getConfiguration('upload_image')
然后你就可以拿到配置了,upload_image 后面的属性 其实对应的就是对象中的key 然后呢你就可以对吧操作了
这个东西还是具体项目, 具体分析,你们自己 可以针对自己的项目去配置
插件开发——图片链接写入编辑器中
通过上面的方法已经可以获得图片上传后的链接,接下来就是将链接写入编辑器中:首先判断编辑器选择位置,editor.selection
中可以获得光标位置、光标选择首尾位置。若光标有选中内容则editBuilder.replace
替换选中内容,否则editBuilder.insert
在光标位置插入图片链接:
// 将图片链接写入编辑器
function addImageUrlToEditor(url) {
let editor = vscode.window.activeTextEditor
if (!editor) {
return
}
const { start, end, active } = editor.selection
if (start.line === end.line && start.character === end.character) {
// 在光标位置插入内容
const activePosition = active
editor.edit((editBuilder) => {
editBuilder.insert(activePosition, url)
})
} else {
// 替换内容
const selection = editor.selection
editor.edit((editBuilder) => {
editBuilder.replace(selection, url)
})
}
}
插件发布
到这里,其实一整个vscode插件 其实已经可以开发完成了, 然后我们要把他进行打包发布到vscode 的应用市场
创建账号
我是直接github 登录创建, 首先我们进入文档中提到的主页,完成验证登录后创建一个组织。
创建发布者
进入下面这个页面 https://marketplace.visualstudio.com/manage/publishers/fly,成为一个「vscode」 插件发布者, 给大家看下我的:
打包发布
首先全局 安装脚手架
npm install -g vsce
然后 cd 到当前插件目录 使用下面命令
$ cd myExtension
$ vsce package
# myExtension.vsix generated
这里的打包会报一些error:
第一个就是插件的package.json 增加发布者
"publisher": "Fly",
如果给插件加图标:其实在项目中创建一个文件夹:image 然后把图片放进去:同时也要在package.json 中配置
"icon": "images/dewu.jpeg",
这里可能有⚠️,不过没什么关系,继续跑就完事了
最后的话其实就是要写readme ,不然 不让你发布。
打包上传
一切准备就绪:命令行 输入
vsce package
然后项目中就会出现:
然后可以把这个东西拖到页面这个页面
https://marketplace.visualstudio.com/manage/publishers
然后点击上传就好了,你就可以在vscode 插件商场可以看到自己写的插件了