Figma 插件开发 - Vite 环境搭建
最近工作主要和 Figma 插件打交道,梳理一些踩坑的经验~
开始
官方的起始例子:www.figma.com/plugin-docs…
按步骤将插件文件保存到本地即可,调试时可以右键唤起插件,可以关注下几个功能入口:
- Import plugin from manifest 导入本地插件
- Open console 控制台调试
- Run last plugin 加载最新的插件
目前 figma 插件开发流程没有有效的 hot reload 机制,【加载最新插件】在开发时比较常用,快捷键可以记一下。
插件架构
Figma 的插件架构比较简单,主要关注三部分:
- manifest.json 插件清单
- ui.html 入口
- core.js 入口
manifest.json
{"name": "test","id": "1095700741264679376","api": "1.0.0","main": "code.js","editorType": ["figma"],"ui": "ui.html"
}
ui.html
<h2>Rectangle Creator</h2>
<p>Count: <input id="count" value="5" /></p>
<button id="create">Create</button>
<button id="cancel">Cancel</button>
<script> document.getElementById('create').onclick = () => {const textbox = document.getElementById('count');const count = parseInt(textbox.value, 10);parent.postMessage({ pluginMessage: { type: 'create-rectangles', count } }, '*');};document.getElementById('cancel').onclick = () => {parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*');}; </script>
core.js
figma.showUI(__html__);
figma.ui.onmessage = msg => {if (msg.type === 'create-rectangles') {const nodes: SceneNode[] = [];for (let i = 0; i < msg.count; i++) {const rect = figma.createRectangle();rect.x = i * 150;rect.fills = [{type: 'SOLID', color: {r: 1, g: 0.5, b: 0}}];figma.currentPage.appendChild(rect);nodes.push(rect);}figma.currentPage.selection = nodes;figma.viewport.scrollAndZoomIntoView(nodes);}figma.closePlugin();
};
manifest
清单描述文件主要描述应用入口、支持编辑器类型还有一些权限相关的配置:
- main 用于指定 figma 主应用进程的脚本文件,有点类似 chrome 插件中 background 进程
- ui 用于直指定插件交互面板 html 入口,类似 chrome 插件的 popup 页面
- editorType 用于指定插件支持的编辑器类型,编辑的类型有两种,具体的看区别这里
core
core.js 运行在 figma 应用所提供的沙箱环境,其只能使用 figma 所提供 API 与一些基本的 Javascript 特性包括标准类型、JSON 和 Promise API、与 Uint8Array 一类的二进制对象。,DOM 一类的接口是无法使用的,在 core 中尽量使用 figma 提供的 api 来实现目标操作,一些依赖 DOM API 的操作可以考虑交由 ui 页面来处理。
ui
UI 主要用于插件与用户的交互,本质是一个 figma 主页面中内嵌的 iframe 页面,其使用 postmessage 与 core 进行交互。
附:之前为了方便 core 与 ui 通信还写了个页面通讯工具库 rpc-shooter 有兴趣的同学可以瞧瞧。
想具体了解插件的运行机制可以戳 How Plugins Run。
环境搭建
Vite 这段时间使用下来体验十分友好,下面以 Vite 为例搭建一个 Figma 插件开发环境。
示例的仓库地址:github.com/kinglisky/f…
yarn create vite
这里选用的 Vue 与 TS,框架随意,Figma 插件开发建议使用 TS,接入 figma plugin 的 d.ts 可以方便的当文档使用。
figma plugin 的类型支持需要配置下 tsconfig.json
:
yarn add @figma/plugin-typings -D
{"compilerOptions": {...other,"typeRoots": ["./node_modules/@types", "./node_modules/@figma"]}
}
多入口
Figma 插件中我们只关心两个入口文件:
- ui.html
- core.js
两个入口文件相互独立,需要将 ui 与 core 拆分成两个包来维护,整理下目录结构拆分出 ui 与 core 部分,示例中还拆分了一个 common 包用于提供公共配置:
.
├── lerna.json
├── manifest.json
├── package.json
├── packages
│ ├── common
│ │ ├── constants
│ │ │ └── ui.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── core
│ │ ├── favicon.svg
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── src
│ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ └── vite.config.ts
│ └── ui
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ ├── env.d.ts
│ │ ├── main.ts
│ │ └── styles
│ │ └── index.css
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── scripts
│ └── build.js
├── tsconfig.json
└── yarn.lock
github.com/kinglisky/f…
workspaces
本地进行多包开发时,workspaces 是个很好用的功能,可以将本地包作为依赖来使用,有点类似 webpack 的中 alias 配置将依赖指向本地。
将 packages 目录下的所有包做作为本地依赖:
{"private": true,"workspaces": ["packages/*"],...
}
插件中实际 core 与 ui 都会从 common 中读配置,common 包的 package.json 配置下 name 与 module 即可提供给 core 与 ui 使用:
{"name": "figma-vite-common","private": false,"version": "0.0.0","module": "./","types": "./"
}
core 与 ui 使用时:
import { VIEW_WIDTH, VIEW_HEIGHT } from 'figma-vite-common/constants/ui';
构建配置
有一点需要注意一下,core.js 与 ui.html 作为插件的入口文件只能是个单文件,简单来说就是不能拆分文件,不能使用异步模块导出多个文件。
- core 中所有依赖的资源都打包到 core.js
- ui.html 中所有的资源都会以内联形式存在
core 配置
core 的配置比较简单:
import { resolve } from 'path';
import { defineConfig } from 'vite';export default defineConfig({build: {lib: {entry: resolve(__dirname, 'src/index.ts'),formats: ['iife'],name: 'core',fileName: 'core',},outDir: resolve(__dirname, '../../dist'),},
});
由于不需要发包使用,将最终打包的 core 入口格式配置为 iife
(立即执行的函数表达式模块),简单的包一层立即调用函数即可:
// 构建结果
(function () {'use strict';figma.showUI(__html__, { width: 400, height: 490 }),(figma.ui.onmessage = (o) => {if (o.type === 'create-rectangles') {const t = [];for (let i = 0; i < o.count; i++) {const e = figma.createRectangle();(e.x = i * 150),(e.fills = [{ type: 'SOLID', color: { r: 1, g: 0.5, b: 0 } }]),figma.currentPage.appendChild(e),t.push(e);}(figma.currentPage.selection = t),figma.viewport.scrollAndZoomIntoView(t);}figma.closePlugin();});
})();
对应的配置下 package scripts:
{"name": "figma-vite-core","private": false,"version": "0.0.0","scripts": {"start": "tsc && vite build -w","build": "tsc && vite build"},"dependencies": {"figma-vite-common": "*"},"devDependencies": {"@figma/plugin-typings": "^1.42.1","typescript": "^4.5.4","vite": "^2.8.0"}
}
开发时会以 yarn start 启动, -w 监听文件变动触发构建。
ui 配置
ui 由于最终的构建产物是一个 html 文件,其他的构建的资源需要内联,这里需要将各种代码拆分的配置关闭,内联资源的阈值调大:
import { resolve } from 'path';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { viteSingleFile } from 'vite-plugin-singlefile';export default defineConfig({plugins: [vue(), viteSingleFile()],build: {target: ['es6'],assetsInlineLimit: 100000000,chunkSizeWarningLimit: 100000000,cssCodeSplit: false,brotliSize: false,outDir: resolve(__dirname, '../../dist'),rollupOptions: {inlineDynamicImports: true,output: {format: 'iife',manualChunks: () => 'everything.js',},},},
});
vite-plugin-singlefile 插件用于将构建出的 js 资源内联到 html 中,构建的包格式还是 iife
。
package scripts 配置:
{"name": "figma-vite-ui","private": false,"version": "0.0.0","scripts": {"start": "vue-tsc --noEmit && vite build -w","build": "vue-tsc --noEmit && vite build"},"dependencies": {"figma-vite-common": "*","vue": "^3.2.25"},"devDependencies": {"@figma/plugin-typings": "^1.42.1","@vitejs/plugin-vue": "^2.2.0","sass": "^1.49.7","typescript": "^4.5.4","vite": "^2.8.0","vite-plugin-singlefile": "^0.6.3","vue-tsc": "^0.29.8"}
}
同样使用 yarn start 启动,-w 监听变动构建。
启动入口
实际在插件开发时需要同时启动 core 与 ui,所以可以在根目录下配置个启动命令,可以直接使用 lerna 进行启动。
配置 lerna.json
{"packages": ["packages/*"],"version": "0.0.0","npmClient": "yarn","useWorkspaces": true
}
配置 package.json
{"private": true,"workspaces": ["packages/*"],"scripts": {"start": "lerna run --stream --scope figma-vite-ui --scope figma-vite-core start"},"publishConfig": {"access": "public"},"devDependencies": {"lerna": "^4.0.0"},"name": "fgima-vite"
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i1gEnVZq-1653620813636)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4767aab3122348879f3945c74209cb85~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
最后改一下插件manifest.json
中入口文件的路径:
{"name": "figma-vite-demo","id": "","api": "1.0.0","main": "dist/core.iife.js","ui": "dist/index.html","editorType": ["figma"]
}
自此一个简单 Figma 插件开发环境完成,仓库在这 github.com/kinglisky/f…
其他
有空会梳理下 Figma 文档数据结构与一些解析技巧,先这样~
Figma 插件开发 - Vite 环境搭建相关推荐
- vue3+vite环境搭建 vue3+vite实战
目录 1.安装 vue-cli 3 2.安装vite 3.安装成功后**package.json**中会添加 4.通过@vitejs/plugin-vue插件来支持Vue 5.安装路由 6.在入口文件 ...
- 3dsmax2014插件开发之环境搭建
做一个记录.防止做到一半以后忘了.网上CSDN等也各有操作流程,参考他们的操作帮忙加了一些速度,但是毕竟每个人遇到的坑点是不一样的,(而且网上好像都是3dmax2022插件制作,我做2014的话可能会 ...
- iphone cydia插件开发_环境搭建
以前从没弄过IOS相关的开发,突然想知道iphone越狱后的插件是怎么开发,刚刚又有相关的设备,于是从零做起. 第一步,安装MacPorts 这个东西类似于linux下面的 apt-get和yum,是 ...
- Atlassian JIRA 插件开发之一 环境搭建
参考 https://developer.atlassian.com/server/framework/atlassian-sdk/ download the SDK 说明 Download the ...
- Vue 3 组件开发:搭建基于SpreadJS的表格编辑系统(环境搭建)
Vue是一套用于构建用户界面的渐进式框架,与其它大型 JS 框架不同,Vue 被设计为可以自底向上逐层应用,更易上手,还便于与第三方库或既有项目整合,因此,Vue完全能够为复杂的单页应用提供驱动. 2 ...
- Flutter环境搭建、运行gallary项目
Flutter环境搭建.运行gallary项目 主体步骤 1.从github clone flutter的sdk, git clone -b beta https://github.com/flutt ...
- 初识 ThreeJS (ThreeJS 相关环境搭建)
初识 ThreeJS (初识 ThreeJS (ThreeJS 相关环境搭建) 参考 描述 ThreeJS 在本地搭建 NodeJS 的官方网站 获取 使用 安装依赖项 运行 官方文档 案例 场景编辑 ...
- tinymce系列(一) tinymce 环境搭建
文章目录 tinymce 环境搭建 初始化目录结构 使用 Rollup 运行,打包 Rollup 打包效果 新建 2 个插件,编写 rollup.config.js rollup 配置 ES6 转 E ...
- Ionic+Cordova开发环境搭建
Ionic+Cordova的组合是一个跨平台的移动开发框架,属于HybirdApp开发模式.其中Ionic是一个前端框架,集成了AngularJs在里面,有很好很漂亮的UI控件.Cordova本身就是 ...
最新文章
- python为什么运行慢_为什么你写的Python运行的那么慢呢?
- CSS题目系列(1) - 可滚动的Table
- 静态html使用js发送邮件,html实现邮箱发送邮件_js发送邮件至指定邮箱功能
- AutoMapper入门使用
- ITK:删除一个未连接到其边界的二进制图像中的孔
- source insight3.5显示中文_Doxygen 中文文档
- java删除通用方法_一个比较通用的java删除文件和文件夹的方法
- Ajax Control Toolkit--Slider:有朝一日倒过来
- golang延时_Golang 定时器底层实现深度剖析
- 分析LOIC流,判断DDoS攻击源
- 计算机操作系统——进程调度算法
- MATLAB牛拉法计算潮流,Matlab牛拉法潮流计算程序
- Adobe Premiere(Pr视频剪辑)下载安装
- Python - 安装sentencepiece异常
- PG-Strom学习总结
- 2014Gartner技术成熟度曲线
- 解决Destroying ProtocolHandler [“ajp-apr-8009“]
- 康宇的OJ愚人手账1
- 快速实现Thread Mesh组网详解
- Ubuntu清理系统垃圾 命令
热门文章
- QT:QSS字体设置
- utf-8等编码方式汉字和英文各占据的字节数
- ie兼容性问题:页面内容显示不全,但不会出现滚动条
- 魅族手机计算机视频教程,魅族手机屏幕电脑录制教程
- 腾讯出品:6.4亿短视频用户的狂欢洞察报告
- 新闻!牛磨王爸爸谈牛磨王抗磨网 | “绿多多”绿色资产
- PacketiX ××× 3.0在Windows Server服务器NT配置步骤
- js设置注册表中ActiveX,并添加信任站点解决IE弹出安全警告
- 用google去旅游!
- 【优化布局】基本蚁狮算法在WSN节点部署中的应用matlab源码