DEV: Allow us to use Ember CLI assets in production
This adds an optional ENV variable, `EMBER_CLI_PROD_ASSETS`. If truthy, compiling production assets will be done via Ember CLI and will replace the assets Rails would otherwise use.
This commit is contained in:
parent
a341dba5d9
commit
18c5e9338f
|
@ -28,8 +28,7 @@
|
||||||
<bootstrap-content key="hidden-login-form">
|
<bootstrap-content key="hidden-login-form">
|
||||||
<bootstrap-content key="preloaded">
|
<bootstrap-content key="preloaded">
|
||||||
|
|
||||||
<script src="{{rootURL}}assets/scripts/start-app.js"></script>
|
<script src="{{rootURL}}assets/start-discourse.js"></script>
|
||||||
<script src="{{rootURL}}assets/scripts/discourse-boot.js"></script>
|
|
||||||
|
|
||||||
<bootstrap-content key="body-footer">
|
<bootstrap-content key="body-footer">
|
||||||
{{content-for "body-footer"}}
|
{{content-for "body-footer"}}
|
||||||
|
|
|
@ -19,6 +19,12 @@ module.exports = function (defaults) {
|
||||||
"ember-qunit": {
|
"ember-qunit": {
|
||||||
insertContentForTestBody: false,
|
insertContentForTestBody: false,
|
||||||
},
|
},
|
||||||
|
sourcemaps: {
|
||||||
|
// There seems to be a bug with brocolli-concat when sourcemaps are disabled
|
||||||
|
// that causes the `app.import` statements below to fail in production mode.
|
||||||
|
// This forces the use of `fast-sourcemap-concat` which works in production.
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ember CLI does this by default for the app tree, but for our extra bundles we
|
// Ember CLI does this by default for the app tree, but for our extra bundles we
|
||||||
|
@ -60,5 +66,12 @@ module.exports = function (defaults) {
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
digest(prettyTextEngine(vendorJs, "discourse-markdown")),
|
digest(prettyTextEngine(vendorJs, "discourse-markdown")),
|
||||||
|
digest(
|
||||||
|
concat("public/assets/scripts", {
|
||||||
|
outputFile: `assets/start-discourse.js`,
|
||||||
|
headerFiles: [`start-app.js`],
|
||||||
|
inputFiles: [`discourse-boot.js`],
|
||||||
|
})
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,28 @@ module ApplicationHelper
|
||||||
@extra_body_classes ||= Set.new
|
@extra_body_classes ||= Set.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def discourse_config_environment
|
||||||
|
# TODO: Can this come from Ember CLI somehow?
|
||||||
|
{ modulePrefix: "discourse",
|
||||||
|
environment: Rails.env,
|
||||||
|
rootURL: Discourse.base_path,
|
||||||
|
locationType: "auto",
|
||||||
|
historySupportMiddleware: false,
|
||||||
|
EmberENV: {
|
||||||
|
FEATURES: {},
|
||||||
|
EXTEND_PROTOTYPES: { "Date": false },
|
||||||
|
_APPLICATION_TEMPLATE_WRAPPER: false,
|
||||||
|
_DEFAULT_ASYNC_OBSERVERS: true,
|
||||||
|
_JQUERY_INTEGRATION: true
|
||||||
|
},
|
||||||
|
APP: {
|
||||||
|
name: "discourse",
|
||||||
|
version: "#{Discourse::VERSION::STRING} #{Discourse.git_version}",
|
||||||
|
exportApplicationGlobal: true
|
||||||
|
}
|
||||||
|
}.to_json
|
||||||
|
end
|
||||||
|
|
||||||
def google_universal_analytics_json(ua_domain_name = nil)
|
def google_universal_analytics_json(ua_domain_name = nil)
|
||||||
result = {}
|
result = {}
|
||||||
if ua_domain_name
|
if ua_domain_name
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
|
|
||||||
<%= tag.meta id: 'data-discourse-setup', data: client_side_setup_data %>
|
<%= tag.meta id: 'data-discourse-setup', data: client_side_setup_data %>
|
||||||
|
|
||||||
|
<meta name="discourse/config/environment" content="<%=u discourse_config_environment %>" />
|
||||||
<%- if authentication_data %>
|
<%- if authentication_data %>
|
||||||
<meta id="data-authentication" data-authentication-data="<%= authentication_data %>">
|
<meta id="data-authentication" data-authentication-data="<%= authentication_data %>">
|
||||||
<%- end %>
|
<%- end %>
|
||||||
|
|
|
@ -197,9 +197,11 @@ module Discourse
|
||||||
app.config.assets.precompile += ['application.js']
|
app.config.assets.precompile += ['application.js']
|
||||||
|
|
||||||
start_path = ::Rails.root.join("app/assets").to_s
|
start_path = ::Rails.root.join("app/assets").to_s
|
||||||
exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '']
|
exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '.lock', '.json', '.log', '.html', '']
|
||||||
app.config.assets.precompile << lambda do |logical_path, filename|
|
app.config.assets.precompile << lambda do |logical_path, filename|
|
||||||
filename.start_with?(start_path) &&
|
filename.start_with?(start_path) &&
|
||||||
|
!filename.include?("/node_modules/") &&
|
||||||
|
!filename.include?("/dist/") &&
|
||||||
!exclude.include?(File.extname(logical_path))
|
!exclude.include?(File.extname(logical_path))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,9 +18,7 @@ task 'assets:precompile:before' do
|
||||||
# is recompiled
|
# is recompiled
|
||||||
Emoji.clear_cache
|
Emoji.clear_cache
|
||||||
|
|
||||||
if !`which terser`.empty? && !ENV['SKIP_NODE_UGLIFY']
|
$node_compress = `which terser`.present? && !ENV['SKIP_NODE_UGLIFY']
|
||||||
$node_uglify = true
|
|
||||||
end
|
|
||||||
|
|
||||||
unless ENV['USE_SPROCKETS_UGLIFY']
|
unless ENV['USE_SPROCKETS_UGLIFY']
|
||||||
$bypass_sprockets_uglify = true
|
$bypass_sprockets_uglify = true
|
||||||
|
@ -36,6 +34,15 @@ task 'assets:precompile:before' do
|
||||||
|
|
||||||
require 'sprockets'
|
require 'sprockets'
|
||||||
require 'digest/sha1'
|
require 'digest/sha1'
|
||||||
|
|
||||||
|
if ENV['EMBER_CLI_PROD_ASSETS']
|
||||||
|
# Remove the assets that Ember CLI will handle for us
|
||||||
|
Rails.configuration.assets.precompile.reject! do |asset|
|
||||||
|
asset.is_a?(String) &&
|
||||||
|
(%w(application.js admin.js ember_jquery.js pretty-text-bundle.js start-discourse.js vendor.js).include?(asset) ||
|
||||||
|
asset.start_with?("discourse/tests"))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task 'assets:precompile:css' => 'environment' do
|
task 'assets:precompile:css' => 'environment' do
|
||||||
|
@ -165,7 +172,7 @@ def max_compress?(path, locales)
|
||||||
end
|
end
|
||||||
|
|
||||||
def compress(from, to)
|
def compress(from, to)
|
||||||
if $node_uglify
|
if $node_compress
|
||||||
compress_node(from, to)
|
compress_node(from, to)
|
||||||
else
|
else
|
||||||
compress_ruby(from, to)
|
compress_ruby(from, to)
|
||||||
|
@ -216,8 +223,66 @@ def copy_maxmind(from_path, to_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def copy_ember_cli_assets
|
||||||
|
ember_dir = "app/assets/javascripts/discourse"
|
||||||
|
ember_cli_assets = "#{ember_dir}/dist/assets/"
|
||||||
|
assets = {}
|
||||||
|
files = {}
|
||||||
|
|
||||||
|
system("yarn --cwd #{ember_dir} run ember build -prod")
|
||||||
|
|
||||||
|
# Copy assets and generate manifest data
|
||||||
|
Dir["#{ember_cli_assets}**/*"].each do |f|
|
||||||
|
if f !~ /test/ && File.file?(f)
|
||||||
|
rel_file = f.sub(ember_cli_assets, "")
|
||||||
|
digest = f.scan(/\-([a-f0-9]+)\./)[0][0]
|
||||||
|
|
||||||
|
dest = "public/assets"
|
||||||
|
dest_sub = dest
|
||||||
|
if rel_file =~ /^([a-z\-\_]+)\//
|
||||||
|
dest_sub = "#{dest}/#{Regexp.last_match[1]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
FileUtils.mkdir_p(dest_sub) unless Dir.exists?(dest_sub)
|
||||||
|
log_file = File.basename(rel_file).sub("-#{digest}", "")
|
||||||
|
|
||||||
|
# It's simpler to serve the file as `application.js`
|
||||||
|
if log_file == "discourse.js"
|
||||||
|
log_file = "application.js"
|
||||||
|
rel_file.sub!(/^discourse/, "application")
|
||||||
|
end
|
||||||
|
|
||||||
|
res = FileUtils.cp(f, "#{dest}/#{rel_file}")
|
||||||
|
|
||||||
|
assets[log_file] = rel_file
|
||||||
|
files[rel_file] = {
|
||||||
|
"logical_path" => log_file,
|
||||||
|
"mtime" => File.mtime(f).iso8601(9),
|
||||||
|
"size" => File.size(f),
|
||||||
|
"digest" => digest,
|
||||||
|
"integrity" => "sha384-#{Base64.encode64(Digest::SHA384.digest(File.read(f))).chomp}"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Update manifest file
|
||||||
|
manifest_result = Dir["public/assets/.sprockets-manifest-*.json"]
|
||||||
|
if manifest_result && manifest_result.size == 1
|
||||||
|
json = JSON.parse(File.read(manifest_result[0]))
|
||||||
|
json['files'].merge!(files)
|
||||||
|
json['assets'].merge!(assets)
|
||||||
|
File.write(manifest_result[0], json.to_json)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
task 'test_ember_cli_copy' do
|
||||||
|
copy_ember_cli_assets
|
||||||
|
end
|
||||||
|
|
||||||
task 'assets:precompile' => 'assets:precompile:before' do
|
task 'assets:precompile' => 'assets:precompile:before' do
|
||||||
|
|
||||||
|
copy_ember_cli_assets if ENV['EMBER_CLI_PROD_ASSETS']
|
||||||
|
|
||||||
refresh_days = GlobalSetting.refresh_maxmind_db_during_precompile_days
|
refresh_days = GlobalSetting.refresh_maxmind_db_during_precompile_days
|
||||||
|
|
||||||
if refresh_days.to_i > 0
|
if refresh_days.to_i > 0
|
||||||
|
@ -261,6 +326,7 @@ task 'assets:precompile' => 'assets:precompile:before' do
|
||||||
puts "Compressing Javascript and Generating Source Maps"
|
puts "Compressing Javascript and Generating Source Maps"
|
||||||
startAll = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
startAll = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||||
manifest = Sprockets::Manifest.new(assets_path)
|
manifest = Sprockets::Manifest.new(assets_path)
|
||||||
|
|
||||||
locales = Set.new(["en"])
|
locales = Set.new(["en"])
|
||||||
|
|
||||||
RailsMultisite::ConnectionManagement.each_connection do |db|
|
RailsMultisite::ConnectionManagement.each_connection do |db|
|
||||||
|
|
Loading…
Reference in New Issue