Este artigo descreve o processo de criação de um plugin Vite para gerar automaticamente documentação a partir de componentes Vue. O objetivo é superar as limitações de ferramentas existentes, como a falta de suporte ao Vue 3 e interfaces de usuário pouco atrativas, além de oferecer atualizações em tempo real.
Motivação
Ao trabalhar com bases de código Vue extensas, especialmente em projetos colaborativos, a falta de documentação clara para componentes pode se tornar um obstáculo significativo. Embora seja possível inspecionar props diretamente, rastrear emits e slots em componentes complexos torna-se trabalhoso. Soluções como a geração manual de arquivos README para cada componente são impraticáveis devido a restrições de tempo.
Ferramentas como o vuese oferecem uma abordagem para a geração automática de documentação Vue. No entanto, identifiquei algumas áreas de melhoria:
- Falta de suporte nativo ao Vue 3.
- A necessidade de executar comandos para gerar a documentação, o que pode ser aprimorado com atualizações em tempo real.
- Uma interface de usuário que poderia ser mais moderna e impactante.
Embora o vuese seja um excelente projeto e tenha servido de inspiração (e base para muitas ideias), essas considerações me levaram a explorar a criação de um plugin Vite próprio.
Objetivos do Plugin
- Análise automática de componentes Vue, com suporte completo ao Vue 3.
- Atualização em tempo real da documentação gerada, permitindo visualização imediata das alterações.
- Uma interface de usuário atraente que transmita profissionalismo e qualidade.
Por que um Plugin Vite?
- Novidade e Ecossistema: O Vite é uma ferramenta relativamente nova, com um ecossistema de plugins em crescimento e menos "rodas" já criadas em comparação com o Webpack, abrindo espaço para novas contribuições.
- Aprendizado de TypeScript: Muitos plugins Vite são desenvolvidos em TypeScript. Utilizar o Vite como plataforma oferece uma excelente oportunidade para aprofundar o conhecimento em TS.
- Desempenho: O Vite é conhecido por sua velocidade de inicialização e build, o que contribui para uma experiência de desenvolvimento mais ágil.
Desafios Técnicos Iniciais: Extração de Dados do Componente
O primeiro grande desafio técnico foi determinar como extrair informações como props e slots de arquivos .vue. Sem experiência prévia em projetos semelhantes, a abordagem inicial com expressões regulares parecia pouco confiável, principalmente devido à minha própria proficiência limitada em regex.
Investigando como ferramentas como o vuese lidavam com essa tarefa, descobri a importância da análise de código em Abstract Syntax Tree (AST). Bibliotecas como as do ecossistema Babel são fundamentais para esse processo:
{
"dependencies": {
"@babel/parser": "^7.10.3",
"@babel/traverse": "^7.10.3",
"@babel/types": "^7.3.0",
"vue-template-compiler": "^2.6.11"
}
}
É interessante notar que o Vue utiliza o Babel internamente para o parse de seus scripts. Para o Vue 3, a biblioteca equivalente ao vue-template-compiler é o @vue/compiler-sfc.
O @vue/compiler-sfc expõe o método parse do @babel/parser, facilitando a integração:
// Arquivo de definição de tipos do @vue/compiler-sfc
import { parse as babelParse } from '@babel/parser';
...
export { babelParse }
Uma ferramenta útil para visualizar e entender a estrutura AST gerada é o AST Explorer, que permite converter código JavaScript em sua representação AST.
Configuração do Ambiente de Desenvolvimento
Após solucionar a questão da extração de dados, o próximo passo foi configurar o ambiente de desenvolvimento do projeto. Baseado na análise de diversos plugins no repositório awesome-vite, identifiquei um padrão comum:
- Estrutura de monorepo com um diretório para o código do plugin e um ou mais diretórios para exemplos de uso (utilizando diferentes frameworks, se aplicável).
- Uso de ferramentas como
tsupoutscpara o build do código TypeScript em JavaScript, visando um ambiente de desenvolvimento rápido. - Definição dos campos
mainetypesnopackage.jsonpara referenciar os arquivos de saída do build.
Estrutura Básica do Projeto
Adotei uma estrutura de monorepo utilizando lerna, yarn e workspaces para gerenciar os diferentes pacotes:
yarn init -y
yarn add lerna -D
npx lerna init
npx lerna create vue-docs
yarn create vite packages/example # Cria o projeto de exemplo com Vite
A estrutura resultante se assemelha a:
- .git
- packages/
- example/ # Projeto Vue criado com Vite
- ...
- vue-docs/ # Código fonte do plugin
- ...
- lerna.json
- package.json
O package.json principal foi configurado para gerenciar os workspaces:
{
"name": "monorepo-vite-docs",
"version": "0.0.0",
"private": true,
"license": "MIT",
"devDependencies": {
"lerna": "^4.0.0"
},
"workspaces": ["packages/*"]
}
Configuração do Pacote vue-docs
Seguindo a convenção de usar TypeScript e tsup para o build:
yarn workspace vue-docs add typescript tsup @babel/preset-typescript @babel/preset-env -D
Criação do arquivo babel.config.js no diretório vue-docs:
// packages/vue-docs/babel.config.js
module.exports = {
presets: [
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript",
],
};
Um arquivo de teste simples index.ts no diretório lib:
// packages/vue-docs/lib/index.ts
export function addNumbers(a: number, b: number): number {
return a + b;
}
addNumbers(5, 10);
Executando o build com tsup:
npx tsup packages/vue-docs/lib/index.ts
Isso gerará um arquivo dist/index.js com o código transpilado. Para integrar o comando de build ao package.json do pacote vue-docs:
// packages/vue-docs/package.json
{
"scripts": {
"build": "tsup ./lib/index.ts"
}
}
Com a estrutura básica e o ambiente de build configurados, o projeto está pronto para as próximas etapas de desenvolvimento e implementação das funcionalidades do plugin.