2018-11-19 21:01:13 -05:00
# frozen_string_literal: true
2020-09-23 11:10:14 -04:00
require 'net/http'
require 'uri'
2018-04-26 16:12:39 -04:00
module Gitlab
module Webpack
2020-09-23 11:10:14 -04:00
class Manifest
# Raised if we can't read our webpack manifest for whatever reason
class ManifestLoadError < StandardError
def initialize ( message , orig )
2020-10-07 02:09:03 -04:00
super " #{ message } \n \n (original error #{ orig . class . name } : #{ orig } ) "
2020-09-23 11:10:14 -04:00
end
end
# Raised if webpack couldn't build one of your entry points
class WebpackError < StandardError
def initialize ( errors )
super " Error in webpack compile, details follow below: \n #{ errors . join ( " \n \n " ) } "
end
end
# Raised if a supplied entry point does not exist in the webpack manifest
2018-04-26 16:12:39 -04:00
AssetMissingError = Class . new ( StandardError )
class << self
2020-09-23 23:09:48 -04:00
include Gitlab :: Utils :: StrongMemoize
2018-04-26 16:12:39 -04:00
def entrypoint_paths ( source )
2020-09-23 11:10:14 -04:00
raise WebpackError , manifest [ " errors " ] unless manifest_bundled?
2018-04-26 16:12:39 -04:00
2019-12-17 04:07:48 -05:00
dll_assets = manifest . fetch ( " dllAssets " , [ ] )
2018-04-26 16:12:39 -04:00
entrypoint = manifest [ " entrypoints " ] [ source ]
if entrypoint && entrypoint [ " assets " ]
# Can be either a string or an array of strings.
# Do not include source maps as they are not javascript
2019-12-17 04:07:48 -05:00
[ dll_assets , entrypoint [ " assets " ] ] . flatten . reject { | p | p =~ / .* \ .map$ / } . map do | p |
2020-10-07 02:09:03 -04:00
" / #{ Gitlab . config . webpack . public_path } / #{ p } "
2018-04-26 16:12:39 -04:00
end
2020-09-23 11:10:14 -04:00
else
raise AssetMissingError , " Can't find asset ' #{ source } ' in webpack manifest "
end
end
def asset_paths ( source )
raise WebpackError , manifest [ " errors " ] unless manifest_bundled?
paths = manifest [ " assetsByChunkName " ] [ source ]
if paths
# Can be either a string or an array of strings.
# Do not include source maps as they are not javascript
[ paths ] . flatten . reject { | p | p =~ / .* \ .map$ / } . map do | p |
2020-10-07 02:09:03 -04:00
" / #{ Gitlab . config . webpack . public_path } / #{ p } "
2020-09-23 11:10:14 -04:00
end
2018-04-26 16:12:39 -04:00
else
raise AssetMissingError , " Can't find entry point ' #{ source } ' in webpack manifest "
end
end
2020-09-23 11:10:14 -04:00
2020-09-23 23:09:48 -04:00
def clear_manifest!
clear_memoization ( :manifest )
end
2020-09-23 11:10:14 -04:00
private
def manifest_bundled?
! manifest [ " errors " ] . any? { | error | error . include? " Module build failed " }
end
def manifest
2020-10-07 02:09:03 -04:00
if Gitlab . config . webpack . dev_server . enabled
2021-01-07 19:10:44 -05:00
# Only cache at request level if we're in dev server mode, manifest may change ...
Gitlab :: SafeRequestStore . fetch ( 'manifest.json' ) { load_manifest }
2020-09-23 11:10:14 -04:00
else
# ... otherwise cache at class level, as JSON loading/parsing can be expensive
2020-09-23 23:09:48 -04:00
strong_memoize ( :manifest ) { load_manifest }
2020-09-23 11:10:14 -04:00
end
end
def load_manifest
2020-10-07 02:09:03 -04:00
data = if Gitlab . config . webpack . dev_server . enabled
2020-09-23 11:10:14 -04:00
load_dev_server_manifest
else
load_static_manifest
end
Gitlab :: Json . parse ( data )
end
def load_dev_server_manifest
2020-10-07 02:09:03 -04:00
host = Gitlab . config . webpack . dev_server . host
port = Gitlab . config . webpack . dev_server . port
scheme = Gitlab . config . webpack . dev_server . https ? 'https' : 'http'
uri = Addressable :: URI . new ( scheme : scheme , host : host , port : port , path : dev_server_path )
2020-09-24 14:09:51 -04:00
# localhost could be blocked via Gitlab::HTTP
response = HTTParty . get ( uri . to_s , verify : false ) # rubocop:disable Gitlab/HTTParty
return response . body if response . code == 200
raise " HTTP error #{ response . code } "
2020-10-07 02:09:03 -04:00
rescue OpenSSL :: SSL :: SSLError , EOFError = > e
ssl_status = Gitlab . config . webpack . dev_server . https ? ' over SSL' : ''
raise ManifestLoadError . new ( " Could not connect to webpack-dev-server at #{ uri } #{ ssl_status } . \n \n Is SSL enabled? Check that settings in `gitlab.yml` and webpack-dev-server match. " , e )
2021-04-26 08:09:44 -04:00
rescue StandardError = > e
2020-10-07 02:09:03 -04:00
raise ManifestLoadError . new ( " Could not load manifest from webpack-dev-server at #{ uri } . \n \n Is webpack-dev-server running? Try running `gdk status webpack` or `gdk tail webpack`. " , e )
2020-09-23 11:10:14 -04:00
end
def load_static_manifest
File . read ( static_manifest_path )
2021-04-26 08:09:44 -04:00
rescue StandardError = > e
2020-10-07 02:09:03 -04:00
raise ManifestLoadError . new ( " Could not load compiled manifest from #{ static_manifest_path } . \n \n Have you run `rake gitlab:assets:compile`? " , e )
2020-09-23 11:10:14 -04:00
end
def static_manifest_path
:: Rails . root . join (
2020-10-07 02:09:03 -04:00
Gitlab . config . webpack . output_dir ,
Gitlab . config . webpack . manifest_filename
2020-09-23 11:10:14 -04:00
)
end
def dev_server_path
2020-10-07 02:09:03 -04:00
" / #{ Gitlab . config . webpack . public_path } / #{ Gitlab . config . webpack . manifest_filename } "
2020-09-23 11:10:14 -04:00
end
2018-04-26 16:12:39 -04:00
end
end
end
end