web-dev-qa-db-fra.com

Paramètre config.assets.precompile de Rails pour traiter tous les fichiers CSS et JS dans app/assets

Je souhaite précompiler tous les fichiers CSS et JS du dossier app/assets de mon projet. Je ne veux PAS pré-compiler tout ce qui se trouve dans vendeur/assets ou lib/assets, uniquement les dépendances de mes fichiers selon les besoins.

J'ai essayé le paramètre générique suivant, mais il précompile incorrectement tout. Cela entraîne beaucoup de travail supplémentaire et provoque même un échec de compilation lors de l'utilisation de bootstrap-sass.

config.assets.precompile += ['*.js', '*.css']

Quel est mon meilleur choix pour traiter mes fichiers uniquement dans app/assets? Merci!

30
keithgaputis

Cette tâche est rendue plus difficile par le fait que les pignons fonctionnent avec des chemins logiques qui n'incluent pas l'emplacement des ressources sous-jacentes non compilées.

Supposons que mon projet contienne le fichier JS "/app/assets/javascripts/foo/bar.js.coffee".

Le compilateur de sprockets déterminera d’abord l’extension du fichier de sortie, dans ce cas ".js", puis il évaluera si le chemin logique "foo/bar.js" doit être compilé. La ressource non compilée peut se trouver dans "app/assets/javascripts", "vendor/assets/javascripts", "lib/assets/javascripts" ou une gem, il n'y a donc aucun moyen d'inclure/exclure un fichier particulier basé sur le chemin logique seul.

Pour déterminer où se trouve la ressource sous-jacente, je pense qu’il est nécessaire de demander à l’environnement sprockets (disponible via l’objet Rails.application.assets) de résoudre le chemin réel de la ressource en fonction du chemin logique. 

Voici la solution que j'utilise. Je suis assez nouveau pour Ruby, ce n'est donc pas le code le plus élégant:

# In production.rb
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(css|js)\z/
    full_path = Rails.application.assets.resolve(path).to_path
    app_assets_path = Rails.root.join('app', 'assets').to_path
    if full_path.starts_with? app_assets_path
      puts "including asset: " + full_path
      true
    else
      puts "excluding asset: " + full_path
      false
    end
  else
    false
  end
}

Avec des pignons> 3.0, cela ne fonctionnera pas en production car Rails.application.assets sera nul (en supposant que par défaut: config.assets.compile = false). 

Pour contourner le problème, vous remplacez l'affectation chemin_complet par:

@assets ||= Rails.application.assets || Sprockets::Railtie.build_environment(Rails.application)
full_path = @assets.resolve(path)

Voir aussi: https://github.com/Rails/sprockets-Rails/issues/237

19
keithgaputis

config.assets.precompile = ['*.js', '*.css']

Cela compilera tout code JavaScript ou CSS dans votre chemin d’actif, quelle que soit la profondeur du répertoire. Trouvé via cette réponse .

23
techpeace

Un léger tweak à la réponse de techpeace:

config.assets.precompile = ['*.js', '*.css', '**/*.js', '**/*.css']

J'aurais ajouté un commentaire à sa réponse mais je n'ai pas encore assez de réputation. Donnez-moi un vote positif et je serai là!

NOTE: ceci précalculera également tous les CSS/JavaScript inclus via rubygems.

14
eltiare

J'ai trouvé ceci dans le code Rails:

@assets.precompile               = [ Proc.new{ |path| !File.extname(path).in?(['.js', '.css']) },
                                     /(?:\/|\\|\A)application\.(css|js)$/ ]

Qui est sauvegardé avec le guide Rails:

Le matcher par défaut pour la compilation de fichiers comprend application.js, application.css et tous les fichiers autres que JS/CSS

Cette valeur par défaut n'est pas réinitialisée si vous utilisez +=. Vous devez donc la remplacer par un = au lieu de +=. Notez que, apparemment, vous pouvez passer un proc ou une expression rationnelle à precompile ainsi qu’une extension. Je pense que si vous voulez pré-compiler uniquement les fichiers du répertoire de niveau supérieur, vous devrez créer une regex du type:

config.assets.precompile = [ /\A[^\/\\]+\.(ccs|js)$/i ]
7
Michael Slade

Tous les .css.scss et .js seront inclus, y compris tous les fichiers des sous-répertoires.

js_prefix    = 'app/assets/javascripts/'
style_prefix = 'app/assets/stylesheets/'

javascripts = Dir["#{js_prefix}**/*.js"].map      { |x| x.gsub(js_prefix,    '') }
css         = Dir["#{style_prefix}**/*.css"].map  { |x| x.gsub(style_prefix, '') }
scss        = Dir["#{style_prefix}**/*.scss"].map { |x| x.gsub(style_prefix, '') }

Rails.application.config.assets.precompile = (javascripts + css + scss)
3
TJ Biddle

Je revisite ce post à l'année 2017. 

Notre produit utilise toujours beaucoup RoR, nous avons constamment modifié nos configurations de précompilation en ajoutant Rails.application.config.assets.precompile à mesure que nous ajoutons de nouveaux modules. Récemment, j'essayais d'optimiser cela en ajoutant un motif regex. J'ai constaté que le motif glob suivant fonctionnait: 

Rails.application.config.assets.precompile += %w(**/bundle/*.js)

Cependant, il me faut toujours exclure certains modules, j'ai donc essayé d'utiliser regex au lieu de glob.

Jusqu'à ce que j'examine le code source de Sprockets: https://github.com/Rails/sprockets-Rails/blob/master/lib/sprockets/railtie.rb#L108 , j'ai constaté qu'ils utilisent déjà regex 

app.config.assets.precompile +=
  [LOOSE_APP_ASSETS, /(?:\/|\\|\A)application\.(css|js)$/]

Alors je change mon code en:

Rails.application.config.assets.precompile +=
  [/^((?!my_excluded_module)\w)*\/bundle\/\w*\.js$/]

Ce qui fonctionne bien 

3
Evi Song

Je voulais que tous les actifs de/app et/vendor soient compilés, sauf les partiels (dont le nom commence par le caractère de soulignement _). Alors voici ma version d'une entrée dans application.rb:

config.assets.precompile << Proc.new { |path|
  if path =~ /\.(css|js)\z/
    full_path = Rails.application.assets.resolve(path).to_path
    app_assets_path = Rails.root.join('app', 'assets').to_path
    vendor_assets_path = Rails.root.join('vendor', 'assets').to_path

    if ((full_path.starts_with? app_assets_path) || (full_path.starts_with? vendor_assets_path)) && (!path.starts_with? '_')
      puts "\t" + full_path.slice(Rails.root.to_path.size..-1)
      true
    else
      false
    end
  else
    false
  end
}

De plus, il affiche la liste des fichiers en cours de compilation à des fins de débogage ...

2
Piotr Kuczynski

Ce fragment de code inclut tous les fichiers js/css, à l’exclusion de gems , sous: app/assets, vendor/assets , lib/assets , sauf s’il s’agit de fichiers partiels (par exemple, "_file.sass" ). Il a également une stratégie pour inclure les actifs de Gems qui ne sont pas inclus dans chaque page.

    # These assets are from Gems which aren't included in every page.
    # So they must be included here
    # instead of in the application.js and css manifests.
    config.assets.precompile += %w(a-gem.css a-gem.js b-gem.js)

    # This block includes all js/css files, excluding gems,
    # under: app/assets, vendor/assets, lib/assets
    # unless they are partial files (e.g. "_file.sass")
    config.assets.precompile << Proc.new { |path|
      if path =~ /\.(css|js)\z/
        full_path = Rails.application.assets.resolve(path).to_path
        aps = %w( /app/assets /vendor/assets /lib/assets )
        if aps.any? {|ap| full_path.starts_with?("#{Rails.root}#{ap}")} &&
            !path.starts_with?('_')
          puts "\tIncluding: " + full_path.slice(Rails.root.to_path.size..-1)
          true
        else
          puts "\tExcluding: " + full_path
          false
        end
      else
        false
      end
    }

Cependant, vous ne voudriez probablement pas faire cela car vous pré-compileriez probablement deux fois plus d’actifs gem (en gros tout ce qui est déjà requis dans votre application.js ou css). Cet extrait inclut tous les fichiers js/css, y compris les gems , sous: app/assets, vendor/assets , lib/assets , sauf s’il s’agit de fichiers partiels (par exemple, "_file.sass" )

# This block includes all js/css files, including gems, 
# under: app/assets, vendor/assets, lib/assets
# and excluding partial files (e.g. "_file.sass")
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(css|js)\z/
    full_path = Rails.application.assets.resolve(path).to_path
    asset_paths = %w( app/assets vendor/assets lib/assets)
    if (asset_paths.any? {|ap| full_path.include? ap}) && 
        !path.starts_with?('_')
      puts "\tIncluding: " + full_path
      true
    else
      puts "\tExcluding: " + full_path
      false
    end
  else
    false
  end
}
0
proteantech