DEV: Include ember deprecation messages in production builds (#20587)

By default, Ember uses a babel transformation to strip out calls to `deprecate()` in production builds. Given that Discourse is a development platform for third-party themes/plugins, having deprecation messages visible in production is essential - many themes/plugins do not have comprehensive test-suites, and rely on production feedback to prompt changes. This commit patches Ember to print its deprecation messages to the console in production. In future we intend to improve the visibility of these to hosting providers and/or site admins.

There are two main parts to this commit:

1. Use yarn's 'resolutions' feature to point `babel-plugin-debug-macros` to a discourse-owned fork. This fork prevents `deprecate()` calls from being stripped. Relevant change can be found at https://github.com/discourse/babel-plugin-debug-macros/commit/d179d613bf

2. Introduce a production shim for Ember's deprecation library, including the `registerDeprecationHandler` API. The default implementation is stripped out of production builds via an `if(DEBUG)` wrapper.

Long term we hope that this kind of functionality can be made available in Ember itself via a flag.
This commit is contained in:
David Taylor 2023-03-10 10:37:28 +00:00 committed by GitHub
parent cd3c35418c
commit 270e98e45f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 125 additions and 12 deletions

View File

@ -70,6 +70,7 @@
"ember-load-initializers": "^2.1.1",
"ember-modifier": "^4.1.0",
"ember-on-resize-modifier": "^1.1.0",
"ember-production-deprecations": "1.0.0",
"ember-qunit": "^6.2.0",
"ember-rfc176-data": "^0.3.18",
"ember-source": "~3.28.11",

View File

@ -0,0 +1,25 @@
"use strict";
/**
* Ember's deprecation and registerDeprecationHandler APIs are stripped from production
* builds via the DEBUG flag. This file provides a minimal reimplementation of them
* to be used in production.
*
* Designed to be used alongside our fork of babel-plugin-debug-macros, which maintains
* deprecate calls in production builds. This fork is introduced via a custom yarn resolution
* in app/assets/javascripts/package.json.
*
* https://github.com/discourse/babel-plugin-debug-macros/commit/d179d613bf
*/
module.exports = {
name: require("./package").name,
included() {
this._super.included.apply(this, arguments);
this.app.import("vendor/ember-production-deprecations/deprecate-shim.js");
},
isDevelopingAddon() {
return true;
},
};

View File

@ -0,0 +1,15 @@
{
"name": "ember-production-deprecations",
"version": "1.0.0",
"description": "Prevents ember-cli from stripping deprecations in the production build",
"author": "Discourse",
"license": "GPL-2.0-only",
"keywords": [
"ember-addon"
],
"ember-addon": {
"after": "ember-cli-babel",
"before": "ember-cli-deprecation-workflow"
},
"dependencies": {}
}

View File

@ -0,0 +1,41 @@
// Ember's deprecation and registerDeprecationHandler APIs are stripped from production
// builds via the DEBUG flag. This file provides a minimal reimplementation of them
// to be used in production
define("discourse/lib/deprecate-shim", ["exports"], function (exports) {
exports.applyShim = function () {
let handler = () => {};
require("@ember/debug/lib/deprecate").registerHandler = (fn) => {
const next = handler;
handler = (message, options) => fn(message, options, next);
};
require("@ember/debug").deprecate = (message, test, options) => {
if (test) {
return;
}
handler(message, options);
};
function formatMessage(message, options) {
if (options && options.id) {
message = message + ` [deprecation id: ${options.id}]`;
}
if (options && options.url) {
message += ` See ${options.url} for more details.`;
}
return message;
}
require("@ember/debug").registerDeprecationHandler(
function shimLogDeprecationToConsole(message, options) {
var updatedMessage = formatMessage(message, options);
console.warn(`DEPRECATION: ${updatedMessage}`);
}
);
};
});
if (!require("@glimmer/env").DEBUG) {
require("discourse/lib/deprecate-shim").applyShim();
}

View File

@ -11,9 +11,13 @@
"discourse-plugins",
"discourse-widget-hbs",
"ember-cli-progress-ci",
"ember-production-deprecations",
"pretty-text",
"select-kit",
"truth-helpers",
"wizard"
]
],
"resolutions":{
"**/babel-plugin-debug-macros": "npm:@discourse/babel-plugin-debug-macros@0.4.0-pre1"
}
}

View File

@ -2189,17 +2189,10 @@ babel-loader@^8.0.6:
make-dir "^3.1.0"
schema-utils "^2.6.5"
babel-plugin-debug-macros@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.2.0.tgz#0120ac20ce06ccc57bf493b667cf24b85c28da7a"
integrity sha512-Wpmw4TbhR3Eq2t3W51eBAQSdKlr+uAyF0GI4GtPfMCD12Y4cIdpKC9l0RjNTH/P9isFypSqqewMPm7//fnZlNA==
dependencies:
semver "^5.3.0"
babel-plugin-debug-macros@^0.3.4:
version "0.3.4"
resolved "https://registry.yarnpkg.com/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.3.4.tgz#22961d0cb851a80654cece807a8b4b73d85c6075"
integrity sha512-wfel/vb3pXfwIDZUrkoDrn5FHmlWI96PCJ3UCDv2a86poJ3EQrnArNW5KfHSVJ9IOgxHbo748cQt7sDU+0KCEw==
babel-plugin-debug-macros@^0.2.0, babel-plugin-debug-macros@^0.3.4, "babel-plugin-debug-macros@npm:@discourse/babel-plugin-debug-macros@0.4.0-pre1":
version "0.4.0-pre1"
resolved "https://registry.yarnpkg.com/@discourse/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.4.0-pre1.tgz#f1aa632fcf5d0d673edfba7dc84003acc6b507b3"
integrity sha512-faMBuks7QDgwS9Vz+lw60z0CHk5jd0NlLtcxXSIJ13X9Fil5v8k0fOztIF9eYkqKuGHuDoCC2mFQlFNftb1RxA==
dependencies:
semver "^5.3.0"

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
describe "Production mode debug shims", type: :system, js: true do
it "can successfully print a deprecation message after applying prod shims" do
visit("/latest")
expect(find("#main-outlet-wrapper")).to be_visible
# Intercept console.warn so we can enumerate calls later
page.execute_script <<~JS
window.intercepted_warnings = [];
console.warn = (msg) => window.intercepted_warnings.push([msg, (new Error()).stack])
JS
# Apply deprecate shims. These are applied automatically in production
# builds, but running a full production build for system specs would be
# too slow
page.execute_script <<~JS
require("discourse/lib/deprecate-shim").applyShim();
JS
# Trigger a deprecation, then return the console.warn calls
warn_calls = page.execute_script <<~JS
const { deprecate } = require('@ember/debug');
deprecate("Some message", false, { id: "some.id" })
return window.intercepted_warnings
JS
expect(warn_calls.size).to eq(1)
call, backtrace = warn_calls[0]
expect(call).to eq("DEPRECATION: Some message [deprecation id: some.id]")
expect(backtrace).to include("shimLogDeprecationToConsole")
end
end