require 'uri' module SewingKit module Webpack # Webpack manifest loading, caching & entry point retrieval class Manifest # Raised if we can't read our webpack manifest for whatever reason class ManifestLoadError < StandardError def initialize(message, orig) super "#{message} (original error #{orig})" end end class LegacyManifestError < StandardError def initialize(manifest) super "manifest must contain 'entrypoints' key (found: #{manifest})" end end class << self # :nodoc: def asset_paths(entrypointName) metadata['entrypoints'][entrypointName] end def clear_cache! @metadata = nil @metadata_expiry_time = nil end def manifest metadata['assets'] end private def metadata if ::Rails.env.production? # Cache at class level, as JSON loading/parsing can be expensive. @metadata ||= load_metadata else # In development, the manifest may change. # A short cache lifetime avoids time consuming node callouts. if self.instance_variable_defined?('@metadata_expiry_time') && @metadata_expiry_time && @metadata_expiry_time >= Time.now @metadata else @metadata = load_metadata @metadata_expiry_time = Time.now + 4 end end raise LegacyManifestError.new(@metadata) if !@metadata['entrypoints'] @metadata end def manifest_bundled? !manifest["errors"].any? { |error| error.include? "Module build failed" } end def load_metadata JSON.parse(`node_modules/.bin/sewing-kit manifest --mode #{mode}`) rescue => e raise ManifestLoadError.new("Could not load compiled manifest - have you run `rake sewing_kit:build`?", e) end def mode ENV['NODE_ENV'] || Rails.env.to_s || 'production' end end end end end