During assets:precompile the javascript is minified, but console.logs are left in.
is there a way to remove all console.logs on precompile when the code is pushed to production?
As of Uglifier 2.4.0 the :compress option includes support for :drop_console which means you can easily remove all console.* functions using something like this in your config/environments/production.rb file:
# Compress JavaScripts
config.assets.compress = true
config.assets.js_compressor = Uglifier.new(
# Remove all console.* functions
:compress => { :drop_console => true }
) if defined? Uglifier
You could add this to application.js.erb
. This solution would prevent any logging to console.log()
in production environment, period. But it will still allow logging to 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 %>
To point you in the right direction, check out the Use as a code pre-processor section of UglifyJS .
I need to research more about how to pass a --define DEVMODE=false
flag within the rake assets:precompile
, but adjusting your code to wrap console.log
in with the DEVMODE
boolean as described in the link above should get you the result you're looking for.
Update:
In some file that will load during rake assets:precompile
, add the following monkey patch.
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
As I mentioned in a comment below, Uglifier does not support passing a :defines
mangle option . You could optionally change the marked line above to "defines" => @options[:defines]
and update your config with this line
config.assets.js_compressor = Uglifier.new(defines: { DEVMODE: ["name", "null"] })
When running the rake task, DEVMODE
will now be converted to null
in your source. Now, given the following code in your Javascript source:
if (typeof DEVMODE === 'undefined') {
DEVMODE = true;
}
if (DEVMODE) {
console.log('some log message');
}
By default (in development mode) , DEVMODE
will be set to true
, causing the console.log()
to execute. When rake assets:precompile
is run, UglifyJS is going to set DEVMODE
to null
before compilation/compression begins. When walking over if (null) {
it will see that the condition will never evaluate true
, and will strip this dead code from the resulting source.
As long as you write your console.log()
calls like above or shorthand as
DEVMODE && console.log('some log message');
the console.log()
calls will be stripped from the production code. I can see other benefits to this too outside of stripping console.log()
, allowing for other development-specific code to coexist with other Javascript in development mode and only development mode.
I'd like to mention the solution of bitcrowd . Their idea basically is:
data
attribute in your body tag that represents the state of your app (development/production/...) - eg <body data-env="<%= Rails.env %>">
depending on this let console.log()
print something out or do nothing at all - eg:
if ($('body').data('env') == 'production' || typeof console == "undefined"){ var console = { log: function() {}, debug: function() {}, info: function() {} }; }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.