Gerenciador de plugins com lazy.nvim

    Definição curta: O lazy.nvim é o gerenciador de plugins padrão do ecossistema Lua-first, com carregamento preguiçoso por evento, comando ou tipo de arquivo.

    Antes de começar

    • Neovim v0.11 ou mais recente instalado — confira com nvim --version
    • Um init.lua que já carrega, ainda que vazio

    O que você vai aprender

    • Explicar Bootstrap com suas palavras
    • Explicar Organização em arquivos com suas palavras
    • Explicar Carregamento sob demanda com suas palavras
    • Localizar o assunto desta página no :help do seu próprio Neovim

    O que é

    O Neovim não vem com gerenciador de plugins. O lazy.nvim se tornou o padrão de fato por dois motivos: a especificação declarativa em Lua e o carregamento sob demanda, que mantém o tempo de inicialização baixo mesmo com dezenas de plugins.

    Bootstrap

    O trecho abaixo instala o próprio lazy.nvim na primeira execução. Vai no init.lua, antes de qualquer configuração de plugin:

    local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
    if not (vim.uv or vim.loop).fs_stat(lazypath) then
      vim.fn.system({
        'git', 'clone', '--filter=blob:none',
        'https://github.com/folke/lazy.nvim.git',
        '--branch=stable', lazypath,
      })
    end
    vim.opt.rtp:prepend(lazypath)

    Defina a tecla líder antes de carregar o lazy, ou os mapeamentos dos plugins vão apontar para a tecla errada:

    vim.g.mapleader = ' '
    vim.g.maplocalleader = '\\'
    
    require('lazy').setup('plugins')   -- carrega lua/plugins/*.lua

    Organização em arquivos

    Passar uma string a setup() faz o lazy importar todos os módulos daquele diretório. A estrutura recomendada:

    ~/.config/nvim/
    ├── init.lua
    └── lua/
        ├── config/
        │   ├── options.lua
        │   └── keymaps.lua
        └── plugins/
            ├── lsp.lua
            ├── telescope.lua
            └── treesitter.lua

    Cada arquivo em lua/plugins/ devolve uma tabela de especificações:

    return {
      {
        'nvim-telescope/telescope.nvim',
        dependencies = { 'nvim-lua/plenary.nvim' },
        cmd = 'Telescope',
        keys = {
          { '<leader>ff', '<cmd>Telescope find_files<cr>', desc = 'Busca arquivos' },
          { '<leader>fg', '<cmd>Telescope live_grep<cr>',  desc = 'Busca texto' },
        },
        opts = {},
      },
    }

    Carregamento sob demanda

    As chaves que controlam quando o plugin carrega:

    ChaveCarrega quando
    eventum evento de autocommand dispara (BufReadPre, InsertEnter, VeryLazy)
    cmdo comando é executado pela primeira vez
    keysa tecla é pressionada
    ftum arquivo daquele tipo é aberto
    lazy = falsesempre, na inicialização

    Regras que funcionam bem na prática:

    • Tema: lazy = false, priority = 1000 — precisa carregar antes de tudo, senão há um flash
    • Ferramentas com comando próprio: cmd
    • Complementos de edição: event = 'InsertEnter'
    • LSP e Treesitter: event = { 'BufReadPre', 'BufNewFile' }
    • O que não tem pressa: event = 'VeryLazy' — depois que a interface já apareceu

    opts versus config

    -- forma curta: equivale a require('plugin').setup({ ... })
    { 'autor/plugin', opts = { opcao = true } }
    
    -- forma completa: quando é preciso lógica
    {
      'autor/plugin',
      config = function()
        local p = require('plugin')
        p.setup({ opcao = true })
        vim.keymap.set('n', '<leader>x', p.acao)
      end,
    }

    Prefira opts. Ele é mesclado corretamente quando o mesmo plugin é especificado em mais de um lugar, o que config não faz.

    Comandos do dia a dia

    :Lazy            " painel principal
    :Lazy sync       " instala, atualiza e limpa
    :Lazy update     " só atualiza
    :Lazy clean      " remove o que não está mais na config
    :Lazy profile    " tempo de carregamento por plugin
    :Lazy health     " diagnóstico

    O :Lazy profile é a ferramenta certa quando a inicialização começa a incomodar — ver desempenho e tempo de inicialização.

    Travar versões

    O lazy-lock.json registra o commit exato de cada plugin. Versione esse arquivo junto com a configuração: é o que garante que a mesma config produza o mesmo ambiente em outra máquina.

    { 'autor/plugin', version = '*' }        -- última tag estável
    { 'autor/plugin', version = '^2.0.0' }   -- faixa semver
    { 'autor/plugin', commit = 'abc1234' }   -- commit fixo

    Erros comuns

    • Definir mapleader depois do setup() — os keys dos plugins ficam com a tecla errada
    • lazy = false em tudo — anula o motivo de usar o lazy
    • Não versionar o lazy-lock.json — a config vira irreprodutível
    • config = true junto com opts — redundante; opts já chama o setup
    • Plugin de tema carregado tarde — flash de cores na inicialização

    Você aprendeu

    • Bootstrap
    • Organização em arquivos
    • Carregamento sob demanda
    • opts versus config
    • Comandos do dia a dia

    Perguntas para reflexão

    1. O que Bootstrap resolve, e o que se perde sem isso?
    2. O que Organização em arquivos resolve, e o que se perde sem isso?
    3. O que Carregamento sob demanda resolve, e o que se perde sem isso?
    4. Qual parte desta página você conseguiria reproduzir sem consultar, direto no editor?

    Artigos relacionados

    Veja também

    Referências