mirror of
https://github.com/discourse/discourse.git
synced 2026-08-07 11:45:21 -05:00
PERF: Use correctly-encoded JS files for webpack chunks on S3 (#35444)
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
This commit is contained in:
co-authored by
Jarek Radosz
parent
2fd6d69bf1
commit
e65395cce4
@@ -16,6 +16,9 @@ const withSideWatch = require("./lib/with-side-watch");
|
||||
const crypto = require("crypto");
|
||||
const commonBabelConfig = require("./lib/common-babel-config");
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const {
|
||||
CustomizeChunkUrlPlugin,
|
||||
} = require("./lib/webpack-customize-chunk-url-plugin");
|
||||
|
||||
process.env.BROCCOLI_ENABLED_MEMOIZE = true;
|
||||
|
||||
@@ -217,6 +220,7 @@ module.exports = function (defaults) {
|
||||
return JSON.stringify(output, null, 2);
|
||||
},
|
||||
}),
|
||||
new CustomizeChunkUrlPlugin(),
|
||||
new RetryChunkLoadPlugin({
|
||||
retryDelay: 200,
|
||||
maxRetries: 2,
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
const pluginName = "CustomizeChunkUrlPlugin";
|
||||
|
||||
export class CustomizeChunkUrlPlugin {
|
||||
apply(compiler) {
|
||||
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
|
||||
const { mainTemplate } = compilation;
|
||||
mainTemplate.hooks.localVars.tap(
|
||||
{ name: pluginName, stage: 1 },
|
||||
(source) => {
|
||||
return `
|
||||
${source}
|
||||
(function () {
|
||||
// Rewrite chunk URLs to match the encoding of the current script
|
||||
if (
|
||||
typeof __webpack_require__ !== "undefined" &&
|
||||
typeof document !== "undefined" &&
|
||||
document.currentScript
|
||||
) {
|
||||
const currentScriptUrl = document.currentScript.src;
|
||||
|
||||
let targetExt = ".js";
|
||||
if (currentScriptUrl.endsWith(".br.js")) {
|
||||
targetExt = ".br.js";
|
||||
} else if (currentScriptUrl.endsWith(".gz.js")) {
|
||||
targetExt = ".gz.js";
|
||||
}
|
||||
|
||||
let oldGetScript = __webpack_require__.u;
|
||||
__webpack_require__.u = function (chunkId) {
|
||||
let result = oldGetScript(chunkId);
|
||||
return result.replace(/\.js$/, targetExt);
|
||||
};
|
||||
}
|
||||
})();
|
||||
`;
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe "script encoding" do
|
||||
let(:js_cdn_requests) { [] }
|
||||
|
||||
before { stub_and_log_cdn_requests }
|
||||
|
||||
def stub_and_log_cdn_requests
|
||||
page.driver.with_playwright_page do |page|
|
||||
page.route(
|
||||
"http://cdn.example.com/**/*",
|
||||
->(route, request) do
|
||||
js_cdn_requests << request.url if request.url.end_with?(".js")
|
||||
origin_uri = URI(request.frame.url)
|
||||
request_uri = URI(request.url)
|
||||
|
||||
# We don't actually have .br.js files or a CDN, so invisibly
|
||||
# rewrite the request to the regular assets
|
||||
mocked_result =
|
||||
URI::HTTP.build(
|
||||
scheme: origin_uri.scheme,
|
||||
host: origin_uri.host,
|
||||
port: origin_uri.port,
|
||||
path: request_uri.path.sub(".br.js", ".js"),
|
||||
)
|
||||
route.continue(url: mocked_result.to_s)
|
||||
end,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "without s3 assets" do
|
||||
before { set_cdn_url "http://cdn.example.com" }
|
||||
|
||||
it "loads JS chunks with the .js extension" do
|
||||
user = Fabricate(:admin)
|
||||
sign_in user
|
||||
|
||||
visit "/latest"
|
||||
|
||||
expect(page).to have_css("#site-logo")
|
||||
|
||||
expect(js_cdn_requests.length).to be > 1
|
||||
expect(js_cdn_requests.any? { |r| r.end_with?(".br.js") }).to eq(false)
|
||||
expect(js_cdn_requests.all? { |r| r.end_with?(".js") }).to eq(true)
|
||||
|
||||
js_cdn_requests.clear
|
||||
|
||||
# Use the composer to trigger an async chunk load
|
||||
find("#create-topic").click
|
||||
find(".d-editor-input").fill_in(with: "This is a test")
|
||||
expect(page).to have_css(".d-editor-preview", text: "This is a test")
|
||||
|
||||
expect(js_cdn_requests.length).to be > 1
|
||||
expect(js_cdn_requests.any? { |r| r.end_with?(".br.js") }).to eq(false)
|
||||
expect(js_cdn_requests.all? { |r| r.end_with?(".js") }).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "with s3 assets" do
|
||||
before do
|
||||
global_setting :s3_bucket, "test_bucket"
|
||||
global_setting :s3_region, "ap-australia"
|
||||
global_setting :s3_access_key_id, "123"
|
||||
global_setting :s3_secret_access_key, "123"
|
||||
global_setting :s3_cdn_url, "http://cdn.example.com"
|
||||
end
|
||||
|
||||
it "loads JS chunks with the .br.js extension" do
|
||||
user = Fabricate(:admin)
|
||||
sign_in user
|
||||
|
||||
visit "/latest"
|
||||
|
||||
expect(page).to have_css("#site-logo")
|
||||
|
||||
expect(js_cdn_requests.length).to be > 1
|
||||
expect(js_cdn_requests.all? { |r| r.end_with?(".br.js") }).to eq(true)
|
||||
|
||||
js_cdn_requests.clear
|
||||
|
||||
# Use the composer to trigger an async chunk load
|
||||
find("#create-topic").click
|
||||
find(".d-editor-input").fill_in(with: "This is a test")
|
||||
expect(page).to have_css(".d-editor-preview", text: "This is a test")
|
||||
|
||||
expect(js_cdn_requests.length).to be > 1
|
||||
expect(js_cdn_requests.all? { |r| r.end_with?(".br.js") }).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user