Como gerenciar dependências de JavaScript do lado do cliente? [fechadas]

95

Embora existam ótimas soluções para gerenciar dependências no lado do servidor, não consegui encontrar nenhuma que satisfaça todas as minhas necessidades de ter um fluxo de trabalho de gerenciamento de dependência de JavaScript coerente no lado do cliente. Eu quero satisfazer estes 5 requisitos:

  1. Gerenciar minhas dependências do lado do cliente em um formato semelhante ao package.json do npm ou bower 'sbower.json
  2. Ele deve ter a flexibilidade de apontar para git repo ou arquivos js reais (na web ou localmente) em meu dependency.jsonarquivo para bibliotecas menos conhecidas (npm permite que você aponte para git repos)
  3. Ele deve minimizar e definir o namespace de todas as bibliotecas em um único arquivo como ender - esse é o único arquivo js que eu precisaria colocar em minha <script>tag no lado do cliente
  4. Ele deve ter suporte imediato para CoffeeScript como BoxJS 4 (agora morto)
  5. No navegador, devo ser capaz de usar o estilo require :

    var $ = require('jquery');
    var _ = require('underscore');

    Ou melhor ainda, faça o estilo headjs :

    head.js(['jquery', 'underscore', 'mylib'], function($, _, mylib) {
      // executed when all libraries are loaded
    });

Se não existe uma ferramenta única, qual é a melhor combinação de ferramentas, ou seja, uma cadeia de ferramentas que posso combinar usando algo como volo (ou grunhido )?

Já pesquisei todas as ferramentas que vinculei aqui e elas atendem a apenas 3 dos meus requisitos, na melhor das hipóteses, individualmente. Então, por favor, não poste novamente sobre essas ferramentas. Eu só aceitaria uma resposta que forneça uma única ferramenta que satisfaça todos os 5 dos meus requisitos ou se alguém postar um fluxo de trabalho / script / exemplo de trabalho concreto de um conjunto de ferramentas de várias dessas ferramentas que também satisfaça todos os meus requisitos. Obrigado.

patikrit
fonte
6
algo como requirejs.org ?
Chandra Sekhar Walajapet
1
Para uma solução mais "no estilo de nó" que porta a requiresintaxe do nó para o navegador, considere browserify
smithclay
1
Você pode ser mais explícito? Dos 5 pontos em minha pergunta, acho que o requirejs / browserify satisfaz apenas um ou dois pontos. Estou procurando uma ferramenta (ou corrente de ferramentas) que me permita cumprir TODOS os cinco requisitos
pathikrit
3
Eu não tentei ainda, mas talvez yeoman.io seja um bom candidato também
Guillaume86
1
Acabei de ouvir sobre o onejs - parece um pouco relacionado: github.com/azer/onejs
dsummersl

Respostas:

45

require.js faz tudo que você precisa.

Minha resposta a esta pergunta pode ajudá-lo

Exemplo:

Hierarquia do projeto do aplicativo cliente:

sampleapp
    |___ main.js
    |___ cs.js
    |___ require.js

main.js é onde você inicializa seu aplicativo cliente e configura o require.js:

require.config({
    baseUrl: "/sampleapp",
    paths: {
        jquery: "libs/jquery", // Local
        underscore: "http://underscorejs.org/underscore-min.js", // Remote
        backbone: "https://github.com/documentcloud/backbone/blob/master/backbone-min.js" // Remote on github
    },
    shim: {
        backbone: {
            deps: ["underscore", "jquery"] // Backbone depends on jquery and underscore
        }
    }
});

require(["cs!someCoffeescriptFile", "jquery", "backbone", "underscore"], function (SomeCoffeescriptFile, $, Backbone, _) {
    // Dependencies are loaded...
    // Execute code
});

As dependências usarão o plugin cs quando prefixadas por "cs!". O plugin cs compila o arquivo coffeescript.

Quando você vai em prod, você pode pré-compilar o seu projeto inteiro com r.js .

node ./node_modules/requirejs/bin/r.js -o buildclientconfig.js

Aqui estão seus requisitos:

  • Gerenciar minhas dependências do lado do cliente em um formato semelhante ao package.json do npm ou component.json do bower. Diferente, mas TÃO BOM!

  • Devo ter a flexibilidade de apontar para git repo ou arquivos js reais (na web ou localmente) em meu arquivo dependency.json para bibliotecas menos conhecidas (npm permite que você aponte para git repos). SIM

  • Ele deve minimizar e definir o namespace de todas as bibliotecas em um único arquivo como ender - esse é o único arquivo js que eu precisaria colocar em minha tag de script no lado do cliente. SIM com r.js.

  • Ele deve ter suporte imediato para coffeescript como Box. SIM

  • No navegador, posso usar o estilo require ou headjs. SIM

Jean-Philippe Leclerc
fonte
Se eu usar r.js, posso simplesmente obter versões não minimizadas de todas as bibliotecas ou como devo decidir entre bibliotecas minimizadas e não minimizadas?
Domi
O único problema é essa porcaria de requireJS que você precisa carregar com código reduzido.
Ben Sinclair
1
@Andy não necessariamente! Você pode usar o Almond, que é muito menor!
Adam B,
24

http://requirejs.org/ é o que você está procurando, eu acredito

Chandra Sekhar Walajapet
fonte
obrigado por isso. não sabia que isso existe fora do nodejs
GottZ
1
obrigado! se achar que resolveu o propósito, marque minha resposta como a correta!
Chandra Sekhar Walajapet
3
não fui eu que
fiz
OPA, desculpe! não percebeu
Chandra Sekhar Walajapet
3
Estou confuso. Como exatamente o requirejs pode puxar um arquivo javascript arbitrário da Internet (não estou falando daqueles em seu repositório como o jquery, mas de outros menos famosos)? Ele pode ler um arquivo package.json? E não funciona com CoffeeScript ... Estou faltando alguma coisa ??
pathikrit
15

Como @ Guillaume86, acho que a bainha o levará o mais perto de onde você quer estar.

Na bainha, as dependências são gerenciadas usando uma combinação de npm e bainha. Use o npm para instalar explicitamente todas as dependências externas de seus projetos. Use hem para especificar quais dependências (externas e locais) devem ser costuradas para suas operações do lado do cliente.

Eu criei um projeto de esqueleto disso para que você possa ver como isso funcionaria - você pode vê-lo em https://github.com/dsummersl/clientsidehem

Adicionando dependências

Use o npm para pesquisar uma dependência específica e, em seguida, modifique o arquivo package.json para garantir que a dependência seja rastreada no futuro. Em seguida, especifique a dependência para seu aplicativo em slug.json.

Por exemplo, suponha que você queira adicionar a dependência do script de café. Basta usar o npm para instalar a dependência e salvá-la no arquivo package.json:

1. npm --save install coffee-script
2. Manually edit the slug.json file. Add "coffee-script" to "dependencies".

Suponha que você queira incluir seu próprio módulo 'bloomfilters' e ele não estiver no registro npm. Você pode adicioná-lo ao seu projeto da seguinte maneira:

1. npm --save install https://github.com/dsummersl/bloomfilters/tarball/master
2. Manually edit the slug.json file. Add "bloomfilters" to "dependencies".

Módulos locais

Se você quiser incluir seu próprio café ou javascript, pode fazê-lo adicionando esses arquivos ao aplicativo / pasta. Observe que para expor seu script por meio do método 'require', você deve torná-lo um módulo CommonJS. É muito simples - veja as bainhas .

Ficheiros locais

Se você deseja incluir código não CommonJS não 'obrigatório', também pode costurar isso referenciando seu javascript ou coffeescript personalizado por meio da lista 'libs' em slug.json.

CSS

A bainha irá costurar seu CSS também, se você quiser. Veja a bainha docs .

Construção

Depois de ter suas dependências listadas, você pode usar bainha para costurá-las todas juntas.

# make sure all dependencies are present:
npm install .
# make public/application.js
hem build
# see your minified js in public/application.js

Notas

A bainha foi feita para o projeto spinejs - mas você não precisa usá-la para isso. Ignore qualquer documento que mencione a coluna vertebral como desejar ...

dsummersl
fonte
1
+1 pelo esforço de entrar em detalhes;)
Guillaume86
11

Bem, estou surpreso que ninguém mencionou o Browserify ainda.

  1. suporta o formato package.json
  2. usa npm embaixo, que pode usar um repositório github (ou qualquer git) como fonte do pacote
  3. minimiza e concatena todas as dependências em um único arquivo.
  4. suporta coffeescript se você incluí-lo em suas dependências
  5. exigem estilo por completo.
  6. suporta mapas de origem
Floby
fonte
você pode usar qualquer repositório github (ou pacote bower) com o browserify? Isso requer algo parecido napaou não? npmjs.org/package/napa
Connor Leech
9

Tenho certeza de que o Hem atende aos seus requisitos (eu uso um fork pessoal com compiladores adicionais - jade e stylus - é fácil de personalizar de acordo com suas necessidades). Ele usa npm para gerenciar dependências.

Guillaume86
fonte
A partir da leitura desta questão em particular, acho que isso resolve 1,3,5 muito bem fora da caixa. Para o # 2, você pode colocar seus próprios pacotes JS locais em node_modules (ele usa npm local) e pode usar o submódulo git para quaisquer dependências apenas no git. Para o # 4, acho que você está preso tendo que compilar café no js sozinho antes de executá-lo (o que é fácil).
dsummersl
Obrigado pelo comentário, mas hem compila meu coffeescript sem problemas :), ele foi inicialmente feito para Spine.js que é um framework orientado a coffeescript, então era um requisito básico
Guillaume86
Eu entendo que seria para spine like apps (ou seja, colocar café no app / ...), mas e os módulos externos que contêm coffeescript? Acho que é isso que Wrick está perguntando, mas posso estar totalmente errado ...
dsummersl
1
Ok, não sei se compila o coffeescript para módulos externos, mas não acho que seja útil, os módulos externos geralmente fornecem o JS compilado :)
Guillaume86
Sim, concordo. Ele entra no reino de make a cakefile / grunt ...
dsummersl
5

Você pode querer dar uma olhada em Yeoman , que usa várias técnicas para ajudá-lo com seus requisitos.

Nosso fluxo de trabalho é composto por três ferramentas para melhorar sua produtividade e satisfação ao construir um aplicativo da web: yo (a ferramenta de andaime), grunt (a ferramenta de construção) e bower (para gerenciamento de pacotes).

Suporte integrado para CoffeeScript, Compass e mais. Funciona com r.js ( RequireJS ), teste de unidade etc.

Quanto aos seus requisitos:

  1. Bower é usado para gerenciamento de dependências
  2. O Bower pode trabalhar com arquivos locais, git: //, http: // e mais
  3. Suporte integrado para minificação e concatenação (mesmo para suas imagens)
  4. Suporte integrado para compilar automaticamente CoffeeScript & Compass (com LiveReload)
  5. Conforme declarado no processo de construção: se você estiver usando AMD, irei passar esses módulos por meio de r.js para que você não precise.

Todos os recursos:

Andaime ultrarrápido - arme facilmente novos projetos com modelos personalizáveis ​​(por exemplo, HTML5 Boilerplate, Twitter Bootstrap), RequireJS e muito mais.

Ótimo processo de construção - você não só obtém minificação e concatenação; Eu também otimizo todos os seus arquivos de imagem, HTML, compilo seus arquivos CoffeeScript e Compass, se você estiver usando AMD, irei passar esses módulos por r.js para que você não precise.

Compilar CoffeeScript & Compass automaticamente automaticamente - Nosso processo de observação LiveReload compila automaticamente os arquivos de origem e atualiza seu navegador sempre que uma alteração é feita para que você não precise fazer isso.

Lint automaticamente seus scripts - Todos os seus scripts são executados automaticamente no JSHint para garantir que estejam seguindo as práticas recomendadas de linguagem.

Servidor de visualização integrado - Chega de precisar iniciar seu próprio servidor HTTP. Meu embutido pode ser disparado com apenas um comando.

Otimização de imagens incrível - Eu otimizo todas as suas imagens usando OptiPNG e JPEGTran para que seus usuários possam gastar menos tempo baixando ativos e mais tempo usando seu aplicativo.

Gerenciamento de pacotes Killer - Precisa de uma dependência? É apenas uma tecla de distância. Eu permito que você pesquise facilmente por novos pacotes através da linha de comando (por exemplo, `bower search jquery), instale-os e mantenha-os atualizados sem precisar abrir seu navegador.

Teste de unidade PhantomJS - execute facilmente seus testes de unidade no WebKit sem cabeça via PhantomJS. Quando você cria um novo aplicativo, também incluo alguns andaimes de teste para seu aplicativo.

MarcoK
fonte
Por favor, deixe um comentário para o -1?
MarcoK de
4

O Bower pode ser adequado às suas necessidades (1) e (2) para o resto que você precisar. Do leia-me:

Bower is a package manager for the web. Bower lets you easily install assets such as images, CSS and JavaScript, and manages dependencies for you.

Para instalar um pacote:

bower install jquery
bower install git://github.com/maccman/package-jquery.git
bower install http://code.jquery.com/jquery-1.7.2.js
bower install ./repos/jquery
user18428
fonte
Eu pesquisei todos os que vinculei em meu OP (incluindo o Bower) e nenhum deles satisfez mais do que 3 dos meus 5 requisitos. Estou procurando uma única ferramenta (ou uma combinação de ferramentas) que resolveria todos os 5 dos meus problemas.
pathikrit
Não sei se isso merece um voto negativo, afirmei que o bower + requirejs mays atende às suas necessidades. Você disse que também estava aberto para 'a melhor combinação de ferramentas'. Boa sorte com sua pesquisa
user18428
O que há de errado com isso: (1) bower (2) também bower (3) requirejs build (4) você já tem um nó instalado não? (5) requirejs
user18428
2

Veja o gerenciador de pacotes Jam . A seguir está a descrição de sua página inicial

Para desenvolvedores front-end que desejam ativos sustentáveis, Jam é um gerenciador de pacotes para JavaScript. Ao contrário de outros repositórios, colocamos o navegador em primeiro lugar.

Parece muito semelhante ao npm na forma como funciona.

Instale o pacote como abaixo

jam install backbone

mantendo os pacotes atualizados executando

jam upgrade
jam upgrade {package} 

Otimize pacotes para produção

jam compile compiled.min.js

As dependências do Jam podem ser adicionadas ao package.jsonarquivo.

Para obter a documentação completa, leia a documentação Jam

himanshu
fonte
2

Acabei de encontrar o inject.js

Alguns dos recursos do site do projeto :

Inject (Apache Software License 2.0) é uma forma revolucionária de gerenciar suas dependências de uma forma independente de biblioteca. Alguns de seus principais recursos incluem:

  • Conformidade CommonJS no navegador (exportações. *)
  • Veja a Matriz de Suporte CommonJS completa
  • Recuperação de arquivos entre domínios (via easyXDM)
  • localStorage (carregue um módulo uma vez)
Veverke
fonte
Gosto de injetar. É muito mais limpo do que RequireJS e quase exatamente como escrever com o node.
Mardok,
1

Há um par de opções:

O componente também pode ser de interesse, ele não gerencia dependências por si só, mas permite que você use versões fragmentadas de bibliotecas grandes.

JoelKuiper
fonte
1

Eu uso hem com npm e gostaria de adicionar alguns benefícios adicionais que acho que não foram abordados até agora.

  • O Hem possui um servidor web autocontido (estratos) para que você possa desenvolver seu código sem precisar recompilar. Eu nunca usohem build menos que esteja publicando um aplicativo.
  • Você não precisa usar o Spine.js para usar o hem, você pode usá-lo para compilar pacotes de coffeescript arbitrários se configurar o slug.json corretamente. Aqui está um dos meus pacotes que é compilado automaticamente com cakefile: https://github.com/HarvardEconCS/TurkServer/tree/master/turkserver-js-client
  • Falando no acima, hem permite que você vincule outras dependências em seu sistema local com o link npm e as combina perfeitamente, mesmo quando você estiver usando o servidor de strata. Na verdade, você não precisa nem usar o cakemétodo acima, você pode apenas vincular diretamente ao coffeescript de projetos dependentes.
  • Hem suporta eco(Coffeescript incorporado) para visualizações e Stylus para CSS, e compila tudo isso, junto com seu Coffeescript, em um arquivo JS e um arquivo CSS.

Aqui está uma lista básica para configurar um aplicativo Spine, hem, coffeescript. Sinta-se à vontade para ignorar as partes da coluna vertebral. Na verdade, às vezes eu costumo spine appconfigurar uma estrutura de diretório para um aplicativo não Spine e, em seguida, edito slug.jsonpara mudar para uma estrutura de compilação diferente.

  1. Instale o NPM: curl http://npmjs.org/install.sh | shem um sistema * nix. Presumo que esteja disponível na linha de comando.
  2. Instale a bainha globalmente ( npm install -g hem). O desenvolvimento se ramificou recentemente, então você pode querer tirá-lo diretamente do github ( https://github.com/spine/hem ), fazer checkout de um branch e npm install -g .dentro dessa pasta.
  3. npm install -g spine.app tornará a coluna disponível como um comando global
  4. spine app foldervai fazer um projeto Spine chamada appemfolder , gerando a estrutura de diretórios direita e um monte de arquivos esqueleto para começar.
  5. cdpara dobrar e editar dependencies.jsonas bibliotecas de que você precisa. Adicione-os para slug.jsonque a bainha também saiba onde encontrá-los.
  6. Opcional: npm linkqualquer um de seus pacotes locais em desenvolvimento para node_modules, e você pode adicioná-los a slug.jsonpara bainha (um index.jspara incluir diretamente ou um index.coffeese quiser que bainhe para compilá-lo).
  7. npm install . para baixar todas as dependências que você acabou de inserir.
  8. Se você der uma olhada na configuração padrão da spine, verá app/lib/setup.coffeeque você encontrará requiretodas as bibliotecas de que precisa em suas dependências. Exemplos:

    # Spine.app had these as dependencies by default
    require('json2ify')
    require('es5-shimify')
    require('jqueryify')
    
    require('spine')
    require('spine/lib/local')
    require('spine/lib/ajax')
    require('spine/lib/manager')
    require('spine/lib/route')
    
    # d3 was installed via dependencies.json
    require 'd3/d3.v2'
  9. Em index.coffee, basta require lib/setupcarregar o controlador principal do seu aplicativo. Além disso, você precisa de requirequaisquer outras classes nesses outros controladores. Você pode usar spine controller somethingou spine model somethingpara gerar modelos para controladores e modelos. O controlador Spine típico se parece com o seguinte, usando o do nó require:

    Spine = require('spine')
    # Require other controllers
    Payment = require('controllers/payment')
    
    class Header extends Spine.Controller
      constructor: ->
        # initialize the class
    
      active: ->
        super
        @render()
    
      render: ->
        # Pull down some eco files
        @html require('views/header')   
    
    # Makes this visible to other controllers    
    module.exports = Header
  10. O padrão gerado index.htmlnormalmente servirá para carregar seu aplicativo, mas modifique conforme necessário. De acordo com seus requisitos, ele puxa apenas um jse um cssarquivo, que você nunca precisa modificar.

  11. Edite seus arquivos de caneta conforme necessário na csspasta. É muito mais flexível do que CSS :)
  12. Em folder, execute hem serverpara iniciar um servidor de bainha e navegue até localhost:9294para ver seu aplicativo. (Se você instalou o hem globalmente.) Ele possui alguns argumentos ocultos, por exemplo, --host 0.0.0.0escuta em todas as portas.
  13. Construa o resto do seu aplicativo usando técnicas MVC adequadas e use a caneta para CSS e eco para visualizações. Ou não use o Spine, e a bainha ainda funcionará muito bem com Coffeescript e npm. Existem muitos exemplos de projetos usando os dois modelos.

Mais uma coisa: normalmente, hem serverserá atualizado automaticamente conforme você atualiza seu código e salva arquivos, o que o torna fácil de depurar. A execução hem buildirá compilar seu aplicativo em dois arquivos application.js,, que é reduzido e application.css. Se você executar hem serverdepois disso, ele usará esses arquivos e não será mais atualizado automaticamente. Portanto, não faça isso hem buildaté que você realmente precise de uma versão reduzida do seu aplicativo para implantação.

Referências adicionais: Spine.js & hem primeiros passos

Andrew Mao
fonte
1

Esta é uma solução que tem uma abordagem muito diferente: empacote todos os módulos em um objeto JSON e exija módulos lendo e executando o conteúdo do arquivo sem solicitações adicionais.

Implementação de demonstração do cliente puro: http://strd6.github.io/editor/

https://github.com/STRd6/require/blob/master/main.coffee.md

STRd6 / require depende de ter um pacote JSON disponível no tempo de execução. A requirefunção é gerada para esse pacote. O pacote contém todos os arquivos que seu aplicativo pode exigir. Nenhuma outra solicitação http é feita porque o pacote reúne todas as dependências. Isso é o mais próximo que se pode chegar da exigência de estilo Node.js no cliente.

A estrutura do pacote é a seguinte:

entryPoint: "main"
distribution:
  main: 
    content: "alert(\"It worked!\")"
  ...
dependencies:
  <name>: <a package>

Ao contrário do Node, um pacote não sabe seu nome externo. Cabe ao pacakge incluir a dependência para nomeá-lo. Isso fornece encapsulamento completo.

Dada toda essa configuração, aqui está uma função que carrega um arquivo de dentro de um pacote:

loadModule = (pkg, path) ->
  unless (file = pkg.distribution[path])
    throw "Could not find file at #{path} in #{pkg.name}" 

  program = file.content
  dirname = path.split(fileSeparator)[0...-1].join(fileSeparator)

  module =
    path: dirname
    exports: {}

  context =
    require: generateRequireFn(pkg, module)        
    global: global
    module: module
    exports: module.exports
    PACKAGE: pkg
    __filename: path
    __dirname: dirname

  args = Object.keys(context)
  values = args.map (name) -> context[name]

  Function(args..., program).apply(module, values)

  return module

Este contexto externo fornece algumas variáveis ​​às quais os módulos têm acesso.

Uma requirefunção é exposta aos módulos, portanto, eles podem exigir outros módulos.

Propriedades adicionais, como uma referência ao objeto global e alguns metadados, também são expostas.

Finalmente, executamos o programa dentro do módulo e no contexto fornecido.

Esta resposta será mais útil para aqueles que desejam ter uma instrução de solicitação de estilo node.js síncrona no navegador e não estão interessados ​​em soluções de carregamento de script remoto.

Daniel X Moore
fonte
1

Verifique o cartero se estiver usando node / express no backend.

Bravo dave
fonte
0

Eu sugiro que você dê uma olhada no kit de ferramentas do dojo, que parece atender à maioria dos seus requisitos. O que eu não tenho certeza é CoffeeScript.

dojo trabalha com módulos escritos no formato Asynchronous Module Definition (AMD). Possui um sistema de construção com pacotes e você pode agregá-los em um ou vários arquivos (chamados de camadas). Aparentemente, ele aceita repositórios do tipo git, mais detalhes sobre o sistema de compilação aqui:

http://dojotoolkit.org/documentation/tutorials/1.8/build/

Para o registro, v1.9 beta é esperado no próximo mês.

Christophe
fonte
0

Outro framework que satisfaz todos os meus critérios lançado recentemente: http://duojs.org/ (e também suporta tratar outros recursos como CSS como dependências).

patikrit
fonte