Introdução

Neste artigo, aprenderemos como criar uma biblioteca de ícones JavaScript usando Node Package Manager ( npm) . Para começar, certifique-se de ter o seguinte:

  • Node v14 ( nvm , ou Node Version Manager, pode ser usado para especificar a versão do Node por diretório de trabalho)
  • Uma conta npm
  • Uma conta Figma

Configuração inicial

Crie um diretório para o seu pacote na linha de comando, onde $ package_name é o nome real do seu pacote.

 $ mkdir $ package_name && cd $ package_name

Depois de determinar o nome do seu pacote, você precisará saber se ele terá o escopo (ou seja, pacote vs. @ nome de usuário/pacote ). Encontrar um nome e registrá-lo no início do processo é muito importante, pois os nomes só podem ser usados ​​uma vez e outros desenvolvedores podem chegar antes de você.

Para saber se um nome está disponível, você pode usar este prático npm verificador de nome ou você pode digitar https://www.npmjs.com/package/ em seu navegador e acrescente o nome de sua escolha ao final do URL, assim:

 https://www.npmjs.com/package/iconslib 

Se o nome estiver disponível, você será saudado com uma página 404. Se você suspeitar que o pacote está registrado para uso futuro, você pode perguntar ao npm para dar o nome a você.

Execute $ npm init . No caso de o nome do pacote desejado não estar disponível, você pode definir o escopo do pacote usando o seu nome de usuário, executando $ npm init--scope=$ your_username . Isso solicitará que você preencha algumas propriedades comuns do npm e crie um package.json , que continuaremos a preencher ao longo do artigo. Certifique-se de definir a versão para 0.0.0 .

Seu package.json deve ser parecido com isto:

 { "nome":"$ package_name", "versão":"0.0.0", "descrição":"$ package_description", "main":"index.js", "scripts": { "test":"echo \"Erro: nenhum teste especificado \"&& exit 1" }, "author":"$ your_username <$ your_email> ($ your_website)", "licença":"$ licença"
}

Escolha de uma licença npm

Escolher uma licença adequada é crucial para cada pacote npm que você constrói porque, sem uma, muitos indivíduos e organizações se absterão de usar seu pacote.

Visite Escolha uma licença para escolher uma. Copie o texto e substitua [ano] e [fullname] de acordo e cole o conteúdo em um arquivo de licença na raiz do diretório do seu pacote.

Não se esqueça de atualizar a propriedade license em package.json se você fez alterações.

Configurando Git e GitHub

Desde a atualização automática de suas dependências desatualizadas até a execução de testes e marcação de seus lançamentos, o GitHub terá um papel importante na manutenção do seu pacote npm.

Para começar, execute $ git init no diretório do seu pacote para inicializar um novo repositório Git.

Em seguida, crie um arquivo README.md com uma breve descrição, que você pode expandir posteriormente, e um arquivo .gitignore que contém o seguinte:

 # saída de compilação # dependências
/node_modules # construir
/contorno
/sólido # misc
.DS_Store
.npm
.eslintcache
.yarn-integridade # arquivos env
.env # Histórico
Histórico
*.registro
npm-debug.log *
yarn-debug.log *
yarn-error.log * # Saída de'npm pack'
*.tgz
/pacote

Depois disso, visite https://github.new e crie um repositório.

Antes de adicionar um remote ou enviar quaisquer alterações para este novo repositório, você primeiro deseja modificar seu package.json adicionando repositório , bugs e homepage . Você também pode adicionar a propriedade keywords para tornar seu pacote mais detectável.

 { "homepage":"https://github.com/$your_username/$github_repo#readme", "repositório": { "tipo":"git", "url":"git + https://github.com/$your_username/$github_repo.git" }, "insetos": { "url":"https://github.com/$your_username/$github_repo/issues" }, "palavras-chave": [ "ícones", "svg", "reagir" ]
}

Se você pretende ter um site para sua biblioteca de ícones, pode definir o valor de homepage para o seu nome de domínio. A página inicial pode ser acessada em $ npm home .

Você pode então prosseguir e enviar seu repositório existente para o GitHub:

 $ git add. && git commit-m'commit inicial'
$ git remote add origin [email protected]: $ your_username/$ github_repo.git
$ git branch-M main
$ git push-u origin main

Publicação antes das npm

Como mencionado anteriormente, publicar antecipadamente no npm protege você de que o nome do seu pacote não seja usado por outras pessoas. Para publicar no npm, crie uma conta e autentique-se na linha de comando do root do seu diretório de pacotes.

 $ npm login

Isso solicitará que você insira suas credenciais. Depois disso, você poderá publicar no registro npm com o seguinte comando:

 $ npm publish-acesso público

Isso criará um pacote npm público usando a propriedade name que você definiu em seu package.json .

Se você deseja cancelar a publicação do seu pacote , execute $ npm cancelar a publicação de $ package_name-f . O ideal é que isso seja feito dentro de 72 horas após a publicação, mas o npm tem algumas diretrizes adicionais sobre o cancelamento da publicação após esse período, se necessário.

Depois de publicado, seu pacote ficará em https://www.npmjs.com/package/$ package_name .

Criação dos ícones

A natureza flexível das especificações SVG permite que os designers de ícones alcancem os mesmos resultados visuais de várias maneiras, usando diferentes recursos da especificação, como o uso de path em vez de formas básicas ou fill vs. stroke .

No entanto, ao criar um conjunto de ícones ou biblioteca, algumas suposições devem ser feitas para permitir uma melhor otimização, porque você terá que distribuir arquivos SVG que são otimizados o máximo possível.

Contorno vs. ícones sólidos

Uma suposição que você pode facilmente fazer é usar stroke s para ícones de contorno e fill s para ícones sólidos. Ícones sólidos tendem a ser usados ​​quando a capacidade de reconhecimento é crucial, então fill s serviria bem para esse propósito. Stroke s são adequados para criar pequenos detalhes, por isso funcionam bem com ícones de contorno.

Esta é uma regra prática útil para uma otimização fácil, porque você terá um subconjunto de ícones de contorno escrito usando stroke se outro usando fill s. Você evitará o pesadelo de ter ícones individuais escritos usando stroke se fill s, o que seria impossível de otimizar de maneiras importantes.

Observe que você terá que usar táticas diferentes se estiver criando um conjunto de ícones duotônicos. O guia de ícones do sistema do Google é um bom recurso se você estiver procurando outras práticas recomendadas para a criação de ícones.

Usando o Figma como ferramenta de design

A especificação SVG é vasta e apenas parcialmente implementada por fornecedores, incluindo editores e navegadores. Você irá “quebrar” constantemente seus SVGs, exportando e importando-os para diferentes ambientes.

Se você trabalha com Figma , você pode usar a caneta para ramificar a partir de um vetor pré-desenhado e criar juntas de esquadria. Infelizmente, isso ainda não se materializa da mesma forma nos navegadores:

Usando o Figma como ferramenta de design

Ícones exportáveis ​​na Figma

Para ser capaz de exportar ícones do Figma de maneira programática posteriormente em seu processo de criação de pacote npm, você precisará criar componentes do Figma a partir de seus ícones e separá-los em contorno e sólido páginas.

Ícones de contorno criados usando traços na Figma
Ícones de contorno criados usando traço
Ícones sólidos criando usando preencher Figma
Ícones sólidos criados usando preenchimento

Criação de um processo de construção

Exportação programática

Depois de fazer isso, use o pacote figma-export para exportar seus ícones do Figma automaticamente. Você precisará de um token de acesso pessoal que pode ser obtido nas configurações da conta Figma , bem como o ID do seu arquivo Figma.

Usando o Figma como ferramenta de design

A seção destacada deste URL é o ID do seu arquivo:

ID do arquivo Figma destacado no URL

Para testar rapidamente nossos ícones Figma, podemos executar o seguinte comando npx :

 $ FIGMA_TOKEN=180901-363fe5d2-f0c2-45a9-b564-d49c708281ea npx-p @ figma-export/cli-p @ figma-export/output-components-as-svg figma-export components V7WbFH5FKFahzo-Oq export/output-components-as-svg

Substitua o valor de FIGMA_TOKEN e V7WbFH5FKFahwtiqWdxzoO por seu token e ID de arquivo, respectivamente.

O comando deve criar um diretório output que contém o seguinte:

saída

├── esboço
│ ├── Circle.svg
│ ├── Square.svg
│ └── S.svg
└── sólido ├── Circle.svg ├── Square.svg └── S.svg

Se a exportação for bem-sucedida, podemos prosseguir com a criação do pacote npm.

Instalando dependências em seu pacote npm

De volta ao nosso diretório de pacotes, instale dotenv , @ figma-export/cli e @ figma-export/output-components-as-svg como dependências de desenvolvimento:

 $ npm install--save-dev dotenv @ figma-export/cli @ figma-export/output-components-as-svg

Em um arquivo .env , inclua a variável de ambiente FIGMA_TOKEN como:

 #.env
FIGMA_TOKEN=180901-363fe5d2-f0c2-45a9-b564-d49c708281ea # use seu próprio
FILE_ID=V7WbFH5FKFahwtiqWdxzoO

dotenv será usado para carregar nossa variável no processo de construção.

Configurando figma-export

Crie um arquivo figma.config.js no diretório raiz e prossiga com as seguintes etapas:

  • Requer a função config de dotenv , que lê .env e preenche process.env com suas variáveis
  • Defina uma constante fileId contendo sua variável env do ID do arquivo Figma
  • Defina uma constante outputters para o diretório de saída de figma-export
  • Exportar um objeto com o tipo FigmaExportRc , que ajuda no preenchimento automático e extrai das páginas solid e contorno Figma
//figma.config.js
require ("dotenv"). config (); const fileId=process.env.FILE_ID;
const outputters=[
require ("@ figma-export/output-components-as-svg") ({output:"./"})
];/** @type {import ('@ figma-export/types'). FigmaExportRC} */
module.exports={
comandos: [
["componentes", {
fileId,
onlyFromPages: ["sólido"],
outputters,
},
],
["componentes", {
fileId,
onlyFromPages: ["esboço"],
outputters,
},
],
],
};

Para testar se está funcionando, execute $ npx figma-export use-config figma.config.js , que deve criar sólido e contorno diretórios contendo nossos ícones.

Otimizando ícones

Para otimização, usaremos o onipresente svgo . O SVGO otimiza nossos SVGs com base no conjunto de plug-ins que configuramos para usar. Você pode testar um subconjunto dessas regras diretamente no navegador usando esta ferramenta de front-end SVGO .

Quanto às otimizações, aplicaremos os configuração padrão e desvie onde acharmos adequado.

removeDimensions

Ao remover largura e altura em favor de viewBox , você evita confiar no tamanho padrão. Isso ajuda a identificar SVGs mal exportados, onde a ferramenta de design adiciona um ou dois pixels às dimensões do SVG-alterando um ícone de 100px para 101px , por exemplo. Depender do tamanho padrão fará com que o SVG pareça nítido, mas redefinir manualmente o tamanho pretendido para 100px fará com que o SVG pareça um pouco borrado e solicitará que você o exporte novamente de maneira adequada.

removeAttrs e addAttributesToSVGElement

A razão pela qual dividimos as otimizações de variantes sólidas e contorno é para que tenhamos apenas uma única ocorrência de atributos específicos. removeAttrs nos permitirá remover um atributo de nossa escolha inteiramente do SVG e addAttributesToSVGElement nos permitirá adicioná-lo de volta ao próprio elemento svg .

 
  
 
  

Definindo valores de currentColor

currentColor é amplamente considerado como a primeira variável CSS. Definir um valor de cor em CSS para currentColor ( border: 2px dashed currentColor , por exemplo) escolheria automática e reativamente o valor da propriedade color desse elemento.

Em nossos SVGs, podemos preencher previamente os atributos fill e stroke com currentColor para tornar mais fácil para os usuários substituir a cor do ícone.

Observe que quando o SVG é usado em para fins de cache do navegador, currentColor simplesmente renderizará o preto do SVG. Para alterar a cor neste caso, você pode usar o filtro SVG feColorMatrix .

Além disso, observe que fill="none" em outline SVGs precisa permanecer como está.

Otimizando SVGs

Para usar o svgo , podemos instalá-lo e executá-lo diretamente em nossos SVGs exportados. Mas como já estamos usando figma-export , que tem integração svgo como um transformador , usaremos isso em seu lugar.

 $ npm i--save-dev @ figma-export/transform-svg-with-svgo

Juntamente com a configuração padrão, adicionaremos essas otimizações, com sortAttrs sendo uma escolha estilística:

//figma.config.js
require ("dotenv"). config ();
const svgo=require ('@ figma-export/transform-svg-with-svgo') const fileId=process.env.FILE_ID;
const outputters=[ require ("@ figma-export/output-components-as-svg") ({output:"./"})
]; /** @type {import ('svgo'). PluginConfig []} */
const solidSVGOConfig=[ {removeDimensions: true}, {sortAttrs: true}, {removeAttrs: {attrs:"fill"}}, {addAttributesToSVGElement: {attribute: {fill:"currentColor"}}},
]; /** @type {import ('svgo'). PluginConfig []} */
const outlineSVGOConfig=[ {removeDimensions: true}, {sortAttrs: true}, {removeAttrs: {attrs:"stroke"}}, {addAttributesToSVGElement: {attribute: {stroke:"currentColor"}}},
]; /** @type {import ('@ figma-export/types'). FigmaExportRC} */
module.exports={ comandos: [ ["componentes", { fileId, onlyFromPages: ["sólido"], transformadores: [svgo ({multipass: true, plugins: solidSVGOConfig})], outputters, }, ], ["componentes", { fileId, onlyFromPages: ["esboço"], transformadores: [svgo ({multipass: true, plugins: outlineSVGOConfig})], outputters, }, ], ],
};

Finalmente, adicionaremos um script npm figma para nosso comando de criação de ícone:

 { "scripts": { "export":"figma-export use-config figma.config.js" }
}

Executar $ npm run export produzirá nossos diretórios contorno e sólido .

Empacotando seus ícones

Para publicar seus ícones, devemos primeiro determinar o que é publicado. Para isso, o package.json do npm usa o arquivos . Quando você não atribui um valor a ele, o npm publicará tudo o que não estiver incluído em .gitignore . Para nossos propósitos, contorno e sólido são tudo o que precisa ser publicado, então vamos adicionar um array files ao pacote . json como tal:

 { "arquivos": [ "contorno/", "sólido/" ]
}

Observe que README.md , package.json e LICENSE são todos publicados independentemente das configurações. Com essa mudança, agora podemos testar e publicar nosso pacote.

Testando e publicando nosso pacote npm

Para simular a publicação de nosso pacote npm, podemos usar o comando npm pack . Executar npm pack criará um arquivo TAR com o nome e versão do seu pacote. Podemos descompactar o arquivo TAR para testar nosso pacote.

 $ tar zxvf $ package_name-0.0.0.tgz

Isso gerará um diretório pacote que contém nossos arquivos publicados.

É muito importante observar que se você excluir ou modificar os diretórios contorno ou solid após executar npm run export , essas modificações serão ser publicado como npm pack indicaria. Por esse motivo, devemos configurar um script npm para limpar, exportar e publicar o pacote para eliminar qualquer chance de interferência.

Limpar e construir scripts

Para limpar nosso espaço de trabalho, precisamos remover os diretórios contorno , sólido e pacote , bem como qualquer arquivo TAR, embora package e arquivos tar são excluídos da publicação.

Podemos recorrer a $ rm-rf para remover esses diretórios e arquivos, mas rm não é multiplataforma. Uma alternativa seria instalar rimraf e use-o em seu lugar.

 $ npm i--save-dev rimraf { "scripts": { "clean":"pacote sólido do contorno do rimraf *.tgz", "export":"figma-export use-config figma.config.js" }
}

Para construir nosso pacote, executaremos os scripts clean e export consecutivamente usando o pacote npm-run-all , que expõe um script run-s que podemos usar.

 $ npm i--save-dev npm-run-all { "scripts": { "clean":"pacote sólido do contorno do rimraf *.tgz", "export":"figma-export use-config figma.config.js", "build":"run-s clean export" }
}

Executar npm run build agora executará nossos scripts clean e export .

Teste

Automatizar a exportação de nossos ícones do Figma significa que agora podemos escrever um script de teste simples para garantir que nossos ícones foram exportados corretamente. Para fazer isso, podemos instalar o cheerio , um analisador de marcação, para validar nosso atributo viewBox .

 $ npm i--save-dev cheerio

Para testar nossos ícones, criaremos um test.js que contém o seguinte:

 const fs=require ("fs");
const $=require ("cheerio"); diretórios const=["contorno","sólido"];
deixe erros=0; directory.forEach ((dir)=> fs.readdirSync (dir).forEach ((arquivo)=> { const viewBox=$.load (fs.readFileSync (`$ {dir}/$ {arquivo}`)) ("svg"). attr ( "viewBox" ); if (viewBox!=="0 0 16 16") { console.error ( `Erro: \` $ {dir}/$ {arquivo} \ `tem um viewBox de \ x1b [31m \` $ {viewBox} \ `\ x1b [0m` ); erros ++; } })
); if (erros> 0) { process.exit (1);
} senão { console.log ("Testes aprovados!");
}

Isso lê todos os SVGs dos diretórios outline e solid e faz loops sobre eles, comparando seus atributos viewBox com 0 0 16 16 . Se a comparação falhar, exibimos uma mensagem útil e saímos do processo do nó com um código de saída 1 , indicando que nosso script de teste falhou.

Em nosso package.json , devemos atualizar nossos scripts, adicionando um script test :

 { "scripts": { "clean":"pacote sólido do contorno do rimraf *.tgz", "export":"figma-export use-config figma.config.js", "test":"node test.js", "build":"run-s clean export" }
}

npm t é uma abreviação para npm run test que podemos usar para executar nosso script de teste manualmente.

Publicando nossos ícones

Publicar uma nova versão no npm envolve executar testes, alterar a versão do pacote e adicionar uma tag Git.

Controle de versão semântico

Para alterar a versão, o npm usa o Controle de versão semântico, ou semver , por meio do comando npm version .

semver é um dos formatos mais populares para versões de API. Para nossos propósitos, um formato MAJOR.MINOR.PATCH simplista será suficiente.

De acordo com semver , MAJOR deve aumentar quando suas alterações quebram os usos existentes de sua API. MINOR é reservado para funcionalidade adicional enquanto mantém a compatibilidade com versões anteriores. PATCH deve aumentar quando nossas alterações visam corrigir um bug.

Depois de confirmar suas alterações para git , executando npm version seguido por major , minor ou patch aumentaria a versão de acordo.

Tags Git

Tags Git são usado para vincular uma versão específica a um ponto no histórico do Git, o que é útil ao trabalhar com usuários que usam versões não mais recentes do seu pacote.

Para criar uma tag, você pode executar git tag v0.0.0-m versão inicial com a versão correspondente e uma anotação.

Uma publicação npm melhor

Com a adição de testar, alterar a versão e marcar nossos lançamentos, é muito possível pular acidentalmente uma etapa ao lançar uma nova versão. Para ajudar a publicar nosso pacote com segurança, podemos contar com np .

 $ npm i--save-dev np

Em nosso package.json , adicionaremos um script release que executa build e np .

 { "scripts": { "clean":"pacote sólido do contorno do rimraf *.tgz", "export":"figma-export use-config figma.config.js", "test":"node test.js", "build":"run-s clean export", "np":"np", "release":"run-s build np" }
}

Para publicar nosso lançamento, devemos primeiro comprometer nossas alterações-sem empurrar, já que np irá empurrar nossas alterações para nós-e então devemos executar:

 $ npm run release

Isso construirá nosso pacote e nos solicitará que alteremos nossa versão e executemos várias verificações em nosso repositório Git e dependências npm. np abrirá uma nova página de lançamento no GitHub para nos permitir anotar nossa tag mais recente e adicionar anexos.

Usando SVGs como componentes React

Existem várias maneiras de os usuários converter SVGs para uso como componentes do React em tempo real. Podemos, no entanto, fazer o trabalho antecipadamente para tornar nosso pacote mais versátil.

Contaremos com o svgr para transformar nossos SVGs em componentes React. E como o svgo , figma-export também tem um plug-in para svgr que usaremos.

 $ npm i--save-dev @ figma-export/output-components-as-svgr

Em figma.config.js , podemos adicionar um valor adicional ao nosso array outputters como:

 const outputters=[ require ("@ figma-export/output-components-as-svg") ({output:"./"}), require ("@ figma-export/output-components-as-svgr") ({ saída:"./src", }),
];

Executar npm run export agora criará um diretório src que contém subdiretórios contorno e sólido nossos componentes React.

Esses componentes React são escritos em JSX, o que significa que o usuário precisará de uma etapa de build para consumi-los. Portanto, usaremos um bundler para transpilar os componentes em JavaScript. Também adicionaremos suporte para TypeScript.

 $ npm i--save-dev react rollup typescript @ rollup/plugin-typescript @ types/react

Primeiro, criaremos um ponto de entrada index.js para Rollup at the root of our project that will export our React components.

//./index.js
export * from"./src/solid";
export * from"./src/outline";

Then, modify our outputters to generate tsx files.

const capitalize=(s)=> s.charAt(0).toUpperCase() + s.slice(1); const fileId=process.env.FILE_ID;
const outputters=[ require("@figma-export/output-components-as-svg")({ output:"./"}), require("@figma-export/output-components-as-svgr")({ getFileExtension: ()=>".tsx", getComponentName: ({ componentName, pageName })=> componentName + capitalize(pageName), getSvgrConfig: ()=> ({ typescript: true }), output:"./src", }),
];

Next, we’ll create tsconfig.json and rollup.config.js files as well as a bundle npm script to bundle our files into a react/index.js file:

//tsconfig.json
{ "compilerOptions": { "jsx":"react", "strict": true, "noImplicitAny": true, "allowSyntheticDefaultImports": true, "declaration": true, "outDir":"react" }
} //rollup.config.js
import typescript from"@rollup/plugin-typescript"; const config=[ { input:"index.js", output: { dir:"react", format:"module", }, plugins: [typescript()], },
]; export default config; { "scripts": { "bundle":"rollup--config", "build":"run-s clean export bundle", }
}

Running npm run build will generate a react directory with an index.js that holds our bundled components, which we will specify as our main entry to the package in package.json.

{ "main":"react/index.js"
}

Users will be able to use these components by importing them as such:

import { HouseSolid, GlobeOutline } from'iconlib'

To publish React components’ support, we must first add the react directory to npm’s files, clean script, and .gitignore alongside src before we run npm run release. We should also add a peerDependencies field to indicate that react is needed to use our package.

//package.json "files": [ "outline/", "solid/", "react/"
], "peerDependencies": { "react":">=16"
} //package.json "scripts": { "clean":"rimraf outline solid react src package *.tgz"
} #.gitignore # build
/outline
/solid
/react
/src

Using sprites and CDNs

Sprites are single files that hold all of our icons, and serve as yet another way to use SVGs. To display an icon, we rely on the use SVG element:

 

For some projects, sprites are the most appropriate way to consume SVGs. Thus, we will export sprites for our SVGs and make them readily available through package CDNs.

To start, we can install @figma-export/output-components-as-svgstore as a dev dependency:

$ npm i--save-dev @figma-export/output-components-as-svgstore

And then we can add another item in our outputters array and point to a sprite directory. We also use our icon names as ids and lowercase them.

const outputters=[ //... require("@figma-export/output-components-as-svgstore")({ getIconId: ({ componentName })=> componentName.toLowerCase(), output:"./sprite", }),
];

Running npm run export would generate sprites in a sprite directory.

By adding our sprite directory to .gitignore, clean script, and files array, we can publish our sprites to npm.

#.gitignore # build
/outline
/solid
/react
/src
/sprite //package.json "files": [ "outline/", "solid/", "react/", "sprite/"
] //package.json "scripts": { "clean":"rimraf outline solid react src sprite package *.tgz"
}

We can then point to either our outline or solid sprites whenever someone visits our package through a CDN like unpkg or jsDelivr by adding unpkg, cdn, and jsdelivr fields in our package.json and point them to our sprites:

{ "jsdelivr":"sprite/outline.svg", "cdn":"sprite/outline.svg", "unpkg":"sprite/outline.svg"
}

If someone were to visit https://unkg.com/$package_name, the URL would resolve to our outline.svg sprites.

Conclusão

This blog post covers publishing to npm, creating optimized icons, and directly exporting them from Figma. We also tackled testing and added React and sprite support. Tell us how your implementation went below!

The post Using npm to create JavaScript icon libraries appeared first on LogRocket Blog.