Skip to content

Commit

Permalink
Add a window var for CWV Tech Report to look for (#11222)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Jan 29, 2024
1 parent add6f8a commit f5f7511
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 16 deletions.
6 changes: 6 additions & 0 deletions .changeset/cwv-report-id.md
@@ -0,0 +1,6 @@
---
"react-router-dom-v5-compat": minor
"react-router-dom": minor
---

Include a window tag for CWV Report detection
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -125,10 +125,10 @@
"none": "17.1 kB"
},
"packages/react-router-dom/dist/react-router-dom.production.min.js": {
"none": "16.9 kB"
"none": "17.0 kB"
},
"packages/react-router-dom/dist/umd/react-router-dom.production.min.js": {
"none": "23.1 kB"
"none": "23.2 kB"
}
}
}
20 changes: 17 additions & 3 deletions packages/react-router-dom-v5-compat/rollup.config.js
Expand Up @@ -7,8 +7,10 @@ const replace = require("@rollup/plugin-replace");
const { terser } = require("rollup-plugin-terser");
const typescript = require("@rollup/plugin-typescript");
const {
babelPluginReplaceVersionPlaceholder,
createBanner,
getBuildDirectories,
validateReplacedVersion,
PRETTY,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
Expand Down Expand Up @@ -57,7 +59,10 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
typescript({
Expand All @@ -71,6 +76,7 @@ module.exports = function rollup() {
],
verbose: true,
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
Expand Down Expand Up @@ -110,13 +116,17 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
Expand Down Expand Up @@ -152,14 +162,18 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
terser(),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
Expand Down
17 changes: 17 additions & 0 deletions packages/react-router-dom/index.tsx
Expand Up @@ -218,11 +218,28 @@ export {

declare global {
var __staticRouterHydrationData: HydrationState | undefined;
var __reactRouterVersion: string;
interface Document {
startViewTransition(cb: () => Promise<void> | void): ViewTransition;
}
}

// HEY YOU! DON'T TOUCH THIS VARIABLE!
//
// It is replaced with the proper version at build time via a babel plugin in
// the rollup config.
//
// Export a global property onto the window for React Router detection by the
// Core Web Vitals Technology Report. This way they can configure the `wappalyzer`
// to detect and properly classify live websites as being built with React Router:
// https://github.com/HTTPArchive/wappalyzer/blob/main/src/technologies/r.json
const REACT_ROUTER_VERSION = "0";
try {
window.__reactRouterVersion = REACT_ROUTER_VERSION;
} catch (e) {
// no-op
}

////////////////////////////////////////////////////////////////////////////////
//#region Routers
////////////////////////////////////////////////////////////////////////////////
Expand Down
48 changes: 37 additions & 11 deletions packages/react-router-dom/rollup.config.js
Expand Up @@ -7,8 +7,10 @@ const replace = require("@rollup/plugin-replace");
const { terser } = require("rollup-plugin-terser");
const typescript = require("@rollup/plugin-typescript");
const {
babelPluginReplaceVersionPlaceholder,
createBanner,
getBuildDirectories,
validateReplacedVersion,
PRETTY,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
Expand Down Expand Up @@ -37,7 +39,10 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
typescript({
Expand All @@ -51,6 +56,7 @@ module.exports = function rollup() {
],
verbose: true,
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
Expand Down Expand Up @@ -78,13 +84,17 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
Expand Down Expand Up @@ -118,14 +128,17 @@ module.exports = function rollup() {
],
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
// compiler(),
validateReplacedVersion(),
terser({ ecma: 8, safari10: true }),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
Expand Down Expand Up @@ -158,13 +171,17 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
Expand Down Expand Up @@ -192,15 +209,18 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
// compiler(),
terser(),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
Expand Down Expand Up @@ -247,7 +267,10 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
typescript({
Expand All @@ -256,7 +279,7 @@ module.exports = function rollup() {
exclude: ["__tests__"],
noEmitOnError: true,
}),
// compiler()
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
Expand Down Expand Up @@ -296,10 +319,13 @@ module.exports = function rollup() {
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
// compiler()
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
Expand Down
77 changes: 77 additions & 0 deletions rollup.utils.js
@@ -1,5 +1,7 @@
const path = require("path");
const fse = require("fs-extra");
const { version } = require("./packages/react-router/package.json");
const majorVersion = version.split(".").shift();

const PRETTY = !!process.env.PRETTY;

Expand Down Expand Up @@ -62,8 +64,83 @@ function createBanner(packageName, version) {
*/`;
}

// Babel plugin to replace `const REACT_ROUTER_VERSION = "0.0.0";` with the
// current version at build time, so we can set it on `window.__reactRouterVersion`
// for consumption by the Core Web Vitals Technology Report
function babelPluginReplaceVersionPlaceholder() {
return function (babel) {
var t = babel.types;

const KIND = "const";
const NAME = "REACT_ROUTER_VERSION";
const PLACEHOLDER = "0";

return {
visitor: {
VariableDeclaration: {
enter: function (path) {
// Only operate on top-level variables
if (!path.parentPath.isProgram()) {
return;
}

let { kind, declarations } = path.node;
if (
kind === KIND &&
declarations.length === 1 &&
declarations[0].id.name === NAME &&
declarations[0].init?.value === PLACEHOLDER
) {
path.replaceWith(
t.variableDeclaration(KIND, [
t.variableDeclarator(
t.identifier(NAME),
t.stringLiteral(majorVersion)
),
])
);
}
},
},
},
};
};
}

// Post-build plugin to validate that the version placeholder was replaced
function validateReplacedVersion() {
return {
name: "validate-replaced-version",
writeBundle(_, bundle) {
Object.entries(bundle).forEach(([filename, contents]) => {
if (!filename.endsWith(".js") || filename === "server.js") {
return;
}

let requiredStrs = filename.endsWith(".min.js")
? [`{window.__reactRouterVersion="${majorVersion}"}`]
: [
`const REACT_ROUTER_VERSION = "${majorVersion}";`,
`window.__reactRouterVersion = REACT_ROUTER_VERSION;`,
];

requiredStrs.forEach((str) => {
if (!contents.code.includes(str)) {
throw new Error(
`Expected ${filename} to include \`${str}\` but it did not`
);
}
});
});
},
};
}

// rollup.config.js
module.exports = {
getBuildDirectories,
createBanner,
babelPluginReplaceVersionPlaceholder,
validateReplacedVersion,
PRETTY,
};

0 comments on commit f5f7511

Please sign in to comment.