lib/sewing_kit/webpack/manifest.rb in sewing_kit-0.7.1 vs lib/sewing_kit/webpack/manifest.rb in sewing_kit-0.8.0

- old
+ new

@@ -1,73 +1,76 @@ +# frozen_string_literal: true +require 'open3' 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 + # Raised if the node sewing-kit isn't installed/runnable. + class NodeSewingKitNotRunnable < StandardError + def initialize(mode, cause) + env_message = if 'production' == mode + "\nIf this is a container build, try:\n" \ + " - Adding `YARN_PRODUCTION=false` to your pipeline's environment variables\n" \ + " - Adding the node buildpack: https://github.com/heroku/heroku-buildpack-nodejs" + else + "Try `yarn add --dev @shopify/sewing-kit`" + end + + super( + "Could not fetch manifest because node sewing-kit is not runnable. " \ + "#{env_message}\n" \ + "Original error #{cause}" + ) + end + end + + # Raised if the node-generated manifest cannot be read from the filesystem. class ManifestLoadError < StandardError - def initialize(message, orig) - super "#{message} (original error #{orig})" + def initialize(path, cause) + super "Could not load manifest from #{path} (original error #{cause})" end end + # Raised if the node-generated manifest returns unparseable JSON. + class ManifestParseError < StandardError + def initialize(cause) + super "Could not parse manifest JSON (original error #{cause})" + 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] + def asset_paths(entrypoint_name) + instance.asset_paths(entrypoint_name) end def clear_cache! - @metadata = nil - @metadata_expiry_time = nil + @instance = nil end def manifest - metadata['assets'] + instance.manifest end - private - - def metadata - if ::Rails.env.production? - # Cache at class level, as JSON loading/parsing can be expensive. - @metadata ||= load_metadata + def instance + return @instance if @instance + @instance = if Rails.env.development? && ENV['SK_SIMULATE_PRODUCTION'] != '1' + Development.new 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 + Production.new 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 + +require 'sewing_kit/webpack/manifest/development' +require 'sewing_kit/webpack/manifest/production'