Uglifiers rename function and variable names to single letters and removes newline characters. This makes it very hard to read the scripts for developers via browser console or by other means.
Uglifying and debugging
For example, see the following error and its stack trace in the console.
TypeError: Unable to get property 'id' of undefined at Anonymous function(/assets/onboarding/index-772a8127b092d6eaf7bf19b399517afdc847925d9281d3f0b35681eb6741817f.js:1:15624) at lt.event.dispatch(/assets/jquery-c567de05321bae803d07181b60c2cedba30ec424166235b5075d83a91ff72233.js:2:6550) ...
This is where source maps come in handy.
What are source maps?
From the above example, if there is a source map, the stack trace would look like this:
TypeError: Cannot read property 'id' of undefined at apply(/assets/onboarding/index.js:660:36) at apply(/assets/jquery.js:3075:9)
Source map contents are put in a different file and the uglified file refers the source map file using a special comment:
... //# sourceMappingURL=https://my-domain.com/path/to/file.js.map
Sprockets and Rails
Up until Rails version 5.*, the framework implemented asset pipeline using Sprockets. Sprockets is a Ruby library for compiling and serving web assets. It allows to combine multiple files into one and uglify the resulting files.
Sprockets is shipped with different Uglifiers (or compressors) and Uglifier is one of them. Its configured in the environment’s config file in Rails using the following line.
config.assets.js_compressor = :uglifier
Sprockets and Source maps
Sprockets version 4 supports generation of source maps.
However, version 4 is still in beta.
If one is on version 3, source maps generation with
uglifier JS compressor
is not supported.
Uglifier wrapper itself supports generation of
Generation of source maps
Sprockets support writing your own JS compressor and registering it with
sprockets to use it.
Since we know that Uglifier already supports generation of source maps, we will
Sprockets::UglifierCompressor from Sprockets to support source
To do so, we create an initializer in our Rails application
the following contents.
Lets look at what is happening in the
- We initialize Uglifier with default options.
- Compile along with source maps generation.
- Extend source maps’ JSON to add more information.
sources: Specify the filename of the contents’ source.
sourcesContent: Original and non-uglified source of the file.
- Write the file to disk.
- Append source maps URL to the uglified content.
- Return the uglified content to Sprockets for it to write it to the asset file.
Now, configure Sprockets to use the new compressor.
Add the following line to the respective environment config file
config.assets.js_compressor = :uglify_with_source_maps
Now, force pre-compilation of the assets and restart Rails server.
# Clear already compiled assets. rake assets:clobber. # Precompile assets. rake assets:precompile.
Visit the application in the browser and navigate to the sources section in the developer section to see the source maps.