mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
Previously, there was a `deploy-to-firebase` pre-deploy action for configuring Firebase to redirect non-file requests to `angular.io`. This is used for ensuring that `rc.angular.io` is correctly redirected to `angular.io`, even when people have previously visited (and have a ServiceWorker activated on) `rc.angular.io`. This commit adds pre-deploy actions for configuring Firebase to redirect a deployment to any of `angular.io`, `rc.angular.io` or `next.angular.io` and also configure whether all requests or only non-file requests will be redirected. In a future commit, this will allow managing redirects for the `stable`, `rc` and `next` deployments via the Firebase config file (without requiring changes in the Firebase console or DNS). PR Close #43963
120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
import fs from 'fs';
|
|
import sh from 'shelljs';
|
|
import u from './utils.mjs';
|
|
|
|
|
|
// Constants
|
|
const DIST_DIR = 'dist';
|
|
const FIREBASE_JSON_PATH = 'firebase.json';
|
|
const NGSW_JSON_PATH = `${DIST_DIR}/ngsw.json`;
|
|
const NGSW_JSON_BAK_PATH = `${NGSW_JSON_PATH}.bak`;
|
|
|
|
// Exports
|
|
const exp = {
|
|
build,
|
|
checkPayloadSize,
|
|
disableServiceWorker,
|
|
undo: {
|
|
build: undoBuild,
|
|
checkPayloadSize: undoCheckPayloadSize,
|
|
disableServiceWorker: undoDisableServiceWorker,
|
|
},
|
|
};
|
|
Object.keys(u.ORIGINS).forEach(originLabel => {
|
|
[true, false].forEach(allRequests => {
|
|
const redirectFn = generateFn_redirectTo(originLabel, allRequests);
|
|
const undoRedirectFn = generateFn_undoRedirectTo(originLabel, allRequests);
|
|
|
|
exp[redirectFn.name] = redirectFn;
|
|
exp.undo[redirectFn.name] = undoRedirectFn;
|
|
});
|
|
});
|
|
export default exp;
|
|
|
|
// Helpers
|
|
function build({deployedUrl, deployEnv}) {
|
|
u.logSectionHeader('Build the AIO app.');
|
|
u.yarn(`build --configuration=${deployEnv} --progress=false`);
|
|
|
|
u.logSectionHeader('Add any mode-specific files into the AIO distribution.');
|
|
sh.cp('-rf', `src/extra-files/${deployEnv}/.`, DIST_DIR);
|
|
|
|
u.logSectionHeader('Update opensearch descriptor for AIO with `deployedUrl`.');
|
|
u.yarn(`set-opensearch-url ${deployedUrl.replace(/[^/]$/, '$&/')}`); // The URL must end with `/`.
|
|
}
|
|
|
|
function checkPayloadSize() {
|
|
u.logSectionHeader('Check payload size and upload the numbers to Firebase DB.');
|
|
u.yarn('payload-size');
|
|
}
|
|
|
|
function disableServiceWorker() {
|
|
u.logSectionHeader('Disable the ServiceWorker.');
|
|
|
|
// Rename the SW manifest (`ngsw.json`). This will cause the ServiceWorker to unregister itself.
|
|
// See https://angular.io/guide/service-worker-devops#fail-safe.
|
|
sh.mv(NGSW_JSON_PATH, NGSW_JSON_BAK_PATH);
|
|
}
|
|
|
|
function escapeForRegex(str) {
|
|
return str.replace(/[.?*+\\|^$()[\]{}]/g, '\\$&');
|
|
}
|
|
|
|
function generateFn_redirectTo(originLabel, allRequests) {
|
|
const destinationOrigin = u.ORIGINS[originLabel];
|
|
const functionName = `redirect${allRequests ? 'All' : 'NonFiles'}To${originLabel}`;
|
|
|
|
return u.nameFunction(functionName, function () {
|
|
u.logSectionHeader(
|
|
`Configure Firebase hosting to redirect ${allRequests ? 'all' : 'non-file'} requests ` +
|
|
`to '${destinationOrigin}'.`);
|
|
|
|
// Update the Firebase hosting configuration to redirect requests to the specific origin.
|
|
// If `excludeFileRequests` is `true`, only redirect non-file requests, i.e. requests that
|
|
// do not contain a dot in their last path segment.
|
|
// See also https://firebase.google.com/docs/hosting/full-config#redirects.
|
|
const redirectRule = getFirebaseRedirectRuleTo(destinationOrigin, allRequests);
|
|
const oldContent = fs.readFileSync(FIREBASE_JSON_PATH, 'utf8');
|
|
const newContent = oldContent.replace(/( *)"redirects": \[/, `$&\n$1 ${redirectRule},\n`);
|
|
|
|
fs.writeFileSync(FIREBASE_JSON_PATH, newContent);
|
|
});
|
|
}
|
|
|
|
function generateFn_undoRedirectTo(originLabel, allRequests) {
|
|
const destinationOrigin = u.ORIGINS[originLabel];
|
|
const functionName = `undoRedirect${allRequests ? 'All' : 'NonFiles'}To${originLabel}`;
|
|
|
|
return u.nameFunction(functionName, function () {
|
|
u.logSectionHeader(
|
|
`Remove Firebase hosting redirect for ${allRequests ? 'all' : 'non-file'} requests to ` +
|
|
`'${destinationOrigin}'.`);
|
|
|
|
const redirectRule = getFirebaseRedirectRuleTo(destinationOrigin, allRequests);
|
|
const oldContent = fs.readFileSync(FIREBASE_JSON_PATH, 'utf8');
|
|
const newContent = oldContent.replace(
|
|
new RegExp(`(( *)"redirects": \\[)\\n\\2 ${escapeForRegex(redirectRule)},\\n`),
|
|
'$1');
|
|
|
|
fs.writeFileSync(FIREBASE_JSON_PATH, newContent);
|
|
});
|
|
}
|
|
|
|
function getFirebaseRedirectRuleTo(origin, allRequests) {
|
|
const re = allRequests ? '^(.*)$' : '^(.*/[^./]*)$';
|
|
return `{"type": 302, "regex": "${re}", "destination": "${origin}:1"}`;
|
|
}
|
|
|
|
function undoBuild() {
|
|
u.logSectionHeader('Remove the build artifacts.');
|
|
sh.rm('-rf', DIST_DIR);
|
|
}
|
|
|
|
function undoCheckPayloadSize() {
|
|
// Nothing to undo.
|
|
}
|
|
|
|
function undoDisableServiceWorker() {
|
|
u.logSectionHeader('Re-enable the ServiceWorker.');
|
|
sh.mv(NGSW_JSON_BAK_PATH, NGSW_JSON_PATH);
|
|
}
|