【问题标题】:remove console.log on assets precompile删除资产预编译上的 console.log
【发布时间】:2012-08-01 17:56:26
【问题描述】:

在 assets:precompile 期间,javascript 被缩小,但 console.logs 留在里面。

有没有办法在将代码推送到生产环境时删除预编译时的所有 console.log?

【问题讨论】:

  • 有趣!我想用gsub 来实现这不会太难,但是rails 从来没有让我惊讶于已经内置的有用的东西。

标签: ruby-on-rails ruby-on-rails-3 asset-pipeline


【解决方案1】:

从 Uglifier 2.4.0 开始,:compress 选项包括对 :drop_console 的支持,这意味着您可以在 config/environments/production.rb 文件中使用类似的内容轻松删除所有 console.* 函数:

# Compress JavaScripts
config.assets.compress = true
config.assets.js_compressor = Uglifier.new(
  # Remove all console.* functions
  :compress => { :drop_console => true }
) if defined? Uglifier

【讨论】:

  • for( i=0; i<10; i++ ){ console.log( "i = " + i ) } 怎么样?它是否返回一个空循环?
  • Ivan Black,是的,或者更好:u = Uglifier.new(compress: {drop_console: true}); u.compress 'for( i=0; i<10; i++ ){ console.log( "i = " + i ) }'会给你:"for(i=0;10>i;i++);"
【解决方案2】:

您可以将此添加到application.js.erb。此解决方案将防止在生产环境期间对console.log() 进行任何日志记录。但它仍然允许登录到console.error()

<% if Rails.env.production? %>
  window.console = {};
  window.console.log = function(){};
<% else %>
  // the || in the code ensures IE compatability
  window.console = window.console || {};
  window.console.log = window.console.log || function(){};
<% end %>

【讨论】:

    【解决方案3】:

    要为您指明正确的方向,请查看 UglifyJSUse as a code pre-processor 部分。

    我需要研究更多关于如何在rake assets:precompile 中传递--define DEVMODE=false 标志的信息,但是调整您的代码以将console.log 包装在上面链接中描述的DEVMODE 布尔值中应该可以得到结果你正在寻找。

    更新:

    rake assets:precompile 期间将加载的某些文件中,添加以下猴子补丁。

    class Uglifier
      private
        def mangle_options
          {
            "mangle" => @options[:mangle],
            "toplevel" => @options[:toplevel],
            "defines" => { DEVMODE: ["name", "null"] }, # This line sets DEVMODE
            "except" => @options[:except],
            "no_functions" => @options[:mangle] == :vars
          }
        end
    end
    

    正如我在下面的评论中提到的,Uglifier does not support passing a :defines mangle option。您可以选择将上面标记的行更改为 "defines" =&gt; @options[:defines] 并使用此行更新您的配置

    config.assets.js_compressor = Uglifier.new(defines: { DEVMODE: ["name", "null"] })
    

    运行 rake 任务时,DEVMODE 现在将在您的源中转换为 null。现在,在您的 Javascript 源代码中给出以下代码:

    if (typeof DEVMODE === 'undefined') {
      DEVMODE = true;
    }
    
    if (DEVMODE) {
      console.log('some log message');
    }
    

    默认情况下(在开发模式下)DEVMODE 将被设置为true,导致console.log() 执行。当rake assets:precompile 运行时,UglifyJS 将在编译/压缩开始之前将DEVMODE 设置为null。当走过if (null) { 时,它会看到条件永远不会评估true,并将从结果源中删除这个死代码。

    只要你像上面那样写你的console.log()调用或简写为

    DEVMODE && console.log('some log message');
    

    console.log() 调用将从生产代码中删除。除了剥离 console.log() 之外,我还可以看到其他好处,允许其他特定于开发的代码在开发模式下与其他 Javascript 共存并且仅开发模式。

    【讨论】:

    • 如何将其添加到资产管道中?
    • 我正在研究那个(我自己从来没有做过),但它可能需要一些猴子补丁,作为 Uglifier does not accept a :defines option。跨度>
    • 这个解决方案对我不起作用 - Uglify 没有消除死代码。所以我做了:if &lt;%= Rails.env.production? ? 'null' : 'true' %&gt; 然后它似乎工作正常。
    • Uglify 似乎对 false 值很挑剔,它会识别为包装死代码。我并不感到惊讶(在我测试了这个答案之后)你需要为你的应用程序稍微调整一下。
    【解决方案4】:

    我想提一下bitcrowd的解决方案。他们的想法基本上是:

    1. 在你的 body 标签中定义一个 data 属性,代表你的应用程序的状态(开发/生产/...) - 例如。 &lt;body data-env="&lt;%= Rails.env %&gt;"&gt;
    2. 根据这一点,让console.log() 打印一些东西或什么都不做 - 例如:

      if ($('body').data('env') == 'production' || typeof console == "undefined"){
          var console = { log: function() {}, debug: function() {}, info: function() {} };
      }
      

    【讨论】:

    • 如果您不使用让您完全删除代码的工具,这很好,但通常最好根本不输出代码。
    猜你喜欢
    • 1970-01-01
    • 2014-06-20
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多