Class: Ichiban::JSCompiler

Inherits:
Object
  • Object
show all
Defined in:
lib/ichiban/js_compiler.rb

Overview

This class uses the UglifyJS2 binary to concatenate and minify JS source files.

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ JSCompiler

Returns a new instance of JSCompiler.



72
73
74
# File 'lib/ichiban/js_compiler.rb', line 72

def initialize(file)
  @file = file
end

Instance Method Details

#compileObject



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ichiban/js_compiler.rb', line 4

def compile
  rel = @file.rel_to 'assets/js'
  Ichiban.config.js_manifests.each do |dest, sources|
    if sources.include? rel
      # Make the destination folder if necessary.
      dest_folder = File.expand_path(File.join(
        Ichiban.project_root, 'compiled', 'js',
        File.dirname(dest)
      ))
      unless File.exists? dest_folder
        FileUtils.mkdir_p dest_folder
      end
      
      # Build the name of the source map.
      map_name = File.basename(dest, File.extname(dest)) + '.js.map'
      
      # Shell out to UglifyJS2.
      uglify_stdout = `
        cd #{File.join(Ichiban.project_root, 'assets', 'js')} && \
        uglifyjs \
          #{sources.join(' ')} \
          --output #{File.join(Ichiban.project_root, 'compiled', 'js', dest)} \
          --source-map #{map_name} \
          --source-map-url /js/#{map_name} \
          --source-map-root /js \
        2>&1 # Redirect STDERR to STDOUT.
      `
      unless $?.success?
        raise UglifyError, "uglifyjs command failed:\n\n#{uglify_stdout}"
      end
      
      # Uglify populates the source map's "file" property with the absolute path.
      # Replace it with the filename.
      map_path = File.join Ichiban.project_root, 'assets', 'js', map_name
      map_json = JSON.parse(File.read(map_path))
      File.open map_path, 'w' do |f|
        f << JSON.dump(map_json.merge('file' => dest))
      end
      
      # Uglify writes the source map in assets/js.
      # Move it into compiled/js.
      FileUtils.mv(
        File.join(Ichiban.project_root, 'assets', 'js', map_name),
        File.join(Ichiban.project_root, 'compiled', 'js')
      )
      
      # Copy each of the source files into compiled/js so that JS debuggers
      # can use them with the source map.
      sources.each do |filename|
        folder = File.expand_path(File.join(
          Ichiban.project_root, 'compiled', 'js',
          File.dirname(filename)
        ))
        unless File.exists? folder
          FileUtils.mkdir_p folder
        end
        FileUtils.cp(
          File.join(Ichiban.project_root, 'assets', 'js', filename),
          File.join(Ichiban.project_root, 'compiled', 'js')
        )
      end
      
      # Log the compilation of the JS file, but don't log the compilation of the map.
      Ichiban.logger.compilation(@file.abs, dest)
    end
  end
end