Como modularizar e empacotar uma biblioteca Javascript do lado do cliente hoje?

11

Estou atualizando o ecossistema JS moderno do lado do cliente e lendo o CommonJS e a AMD (incluindo ferramentas associadas - browserify, requirejs, onejs, jam, dezenas de outras). Se estou escrevendo uma biblioteca Javascript, como modularizá-la / compactá-la para que ela possa ser acessada de maneira mais ampla (idealmente por usuários que juram pelo CommonJS, AMD e especialmente nenhum)?

Bibliotecas populares como o jQuery parecem usar apenas a concatenação de arquivos da velha escola para criar a si própria e detectar dinamicamente se devem gravar em um exportscontexto global ou. Atualmente, estou fazendo a mesma coisa, mas a principal desvantagem é que, se eu (diferentemente do jQuery) depender de algumas bibliotecas, é bom não precisar solicitar aos usuários que pré-incluam manualmente o conjunto transitivo. (Embora atualmente eu só tenha duas dependências.) E, claro, a poluição global do espaço para nome.

Ou talvez seja mais limpo gerar várias versões da minha biblioteca, para cada contexto?

Também estou pensando em embalagem e publicação. Existem vários sistemas, mas acredito que o principal é o caramanchão, o que é fácil de lidar, já que tudo o que faz é buscar. No entanto, estou me perguntando se eu também deveria ter como alvo outros sistemas de pacotes como o componente (que requer o CommonJS).

Existem outros aspectos relevantes dos quais devo estar ciente? Existem bons exemplos de projetos a seguir para tudo isso?

Yang
fonte
Este é um tutorial incrível: youtube.com/watch?v=USk1ie30z5k O cara menciona requirejs (r.js), nó, caramanchão, espinha dorsal, ...
@ MattFenwick Eu usei todas as ferramentas mencionadas; o vídeo não responde a nenhuma das minhas perguntas.
219 Yang
Você já assistiu? Parece que me lembro do cara nos guiando por uma biblioteca e explicando as linhas de código específicas que a fizeram funcionar com vários sistemas de módulos sem precisar de nenhuma delas.

Respostas:

2

Sempre usei arquivos de compilação, mas desde que iniciei meu primeiro projeto nodejs, comecei a usar o browserify . Com o browerify e outras bibliotecas semelhantes, seu código é seu arquivo de construção. Estou aproveitando uma biblioteca de cliente e servidor que pode ser executada em ambos, mas também pode funcionar com código puramente de cliente. Para resumir, o browserify oferece todos os benefícios de escrever código no nó (nenhuma função anon para evitar globais, npm, requer simples) e permite empacotar esse código para executar no cliente com um comando e carregar apenas um arquivo.

Com o browserify, você pode fazer algo como (chamado app.js):

var MyLib = require('../myLib');

if(typeof window !== 'undefined') {
    window.MyLib = MyLib;
    window._ = require('underscore');
    window.$ = require('$');
    window.MyLib.myCan = require('./3rdParty/can/can');
}

browserify app.js> client.js

Produziria algo como:

[function(require,module,exports){
    window.MyLib = //MyLib code
},
function(require,module,exports){
     window._ = //_ code
},
function(require,module,exports){
    window.$ = //$ code
},
function(require,module,exports){
    window.MyLib.myCan = //can code
}

O arquivo que você definiria pode ter todas as suas bibliotecas de terceiros incluídas e não entrar em conflito com nenhum de seus desenvolvedores que o usa.

--Editar em resposta ao comentário (e uma falha completa na pergunta)

Eu acho que isso depende de suas dependências e de quanto tempo você deseja gastar para garantir que funcionem em todas as versões e bibliotecas. Se suas dependências são comuns e seguem a mesma API de versão para versão, você pode seguir a rota Backbone e exigir que o usuário tenha $ e _. Eu sugeriria colocar as bibliotecas mais obscuras como parte do arquivo empacotado. As opções também não precisam ser cortadas e secas. Você pode oferecer um pré-construído ou criar seu próprio pacote.

reclamar
fonte
+1 para browserify, mais pessoas precisam de saber sobre essa ferramenta
Benjamin Gruenbaum
@BenjaminGruenbaum É uma ferramenta realmente ótima. Tenho muita sorte de ter verificado novamente. Inicialmente eu o ignorei porque costumava carregar os arquivos assíncronos, o que poderia acionar N # de carregamentos de arquivos no navegador. Agora existe apenas um e os mapas de origem podem ser ativados.
pllee
1
Veja, aqui está o problema - estou perguntando sobre como publicar uma biblioteca. Na verdade, eu sei sobre o browserify / onejs / outros sistemas baseados em CommonJS, mas se eu começar a usar require()no meu código, isso significa que ele não estará mais acessível aos usuários, a menos que eles também alterem seus próprios projetos para usar o CommonJS. Se eu liberar um script compilado, ele incluirá potencialmente incluir dependências redundantes com seus próprios projetos e potencialmente inchar enormemente o produto final (por exemplo, vários jquery).
219 Yang
0

Tipos de bibliotecas do lado do cliente:

  1. Toca no DOM
  2. Não toca em DOM

Com o primeiro tipo (widgets da interface do usuário, etc), você normalmente assume que o jQuery está presente. Você também pode escrever "biblioteca DOM agnóstica" e fazê-la funcionar com as menos populares também, mas eu não me incomodo.

Com o segundo tipo. Antes de tudo, não o torne um plugin do jQuery, por exemplo, "o plugin do cookie jQuery" é ridículo, mas essa biblioteca realmente existe.

Ambos os tipos podem não ter dependências, dependências pequenas ou dependências enormes - com uma biblioteca dom que não conta como dependência nesse sentido. Nos dois primeiros, você apenas os concatena dentro do escopo da sua biblioteca e não se preocupa com a possível duplicação. Por exemplo, o jQuery concatena uma isArrayLikefunção interna , mesmo que o usuário possa ter o seu próprio já incluído em alguma biblioteca de cinto de utilidades aleatória.

Eu só tenho uma experiência pessoal com uma enorme dependência ao desenvolver uma biblioteca (na verdade, uma linguagem) - moment.js. Nesse caso, eu forneceria 2 builds, um com moment.js concatenado e outro sem, onde o usuário é responsável por incluí-lo. Não sei se essa é uma boa solução.

E sim, em todos os casos, é adotada a abordagem do jQuery de criar um arquivo grande final que simplesmente funciona. Ele possui o módulo padrão na parte inferior (requer / AMD / detecção global etc).

Esailija
fonte