зеркало из https://github.com/mozilla/fxa.git
task(settings): Support CDN in fxa-settings
Because: - Settings is not being served from a CDN This Commit: - Configures webpack so that it can build assets that will work with a CDN - Updates docker build to produce static bundle for stage cdn - Updates docker build to produce static bundle for prod cdn - Makes a couple changes to target these new build assets in content server - Uses the full hash in bundle names to reduce the chance of conflict Note, that we currently do a string replacement on index.html to inject some config and a flow id. If we didn't do this, we could serve this as a SPA directly off the CDN which would be faster. This should be a future consideration. To test what this would look like once deployed on stage / production, override the following in local.json config. "static_directory": "dist" "page_template_subdirectory": "dist" "proxy_settings": false
This commit is contained in:
Родитель
b88e6fa4b4
Коммит
6d79b616ff
|
@ -32,7 +32,7 @@ done
|
|||
# `npx yarn` because `npm i -g yarn` needs sudo
|
||||
npx yarn install
|
||||
npx yarn gql:allowlist
|
||||
NODE_OPTIONS="--max-old-space-size=7168" CHOKIDAR_USEPOLLING=true SKIP_PREFLIGHT_CHECK=true npx nx run-many -t build --all --verbose --skip-nx-cache
|
||||
NODE_OPTIONS="--max-old-space-size=7168" CHOKIDAR_USEPOLLING=true SKIP_PREFLIGHT_CHECK=true BUILD_TARGETS=stage,prod,dev npx nx run-many -t build --all --verbose --skip-nx-cache
|
||||
|
||||
# This will reduce packages to only production dependencies
|
||||
npx yarn workspaces focus --production --all
|
||||
|
|
|
@ -211,18 +211,13 @@ function makeApp() {
|
|||
);
|
||||
}
|
||||
|
||||
if (config.get('env') === 'production') {
|
||||
app.get(settingsPath, modifySettingsStatic);
|
||||
|
||||
addNonSettingsRoutes(modifySettingsStatic);
|
||||
|
||||
app.get(settingsPath + '/*', modifySettingsStatic);
|
||||
}
|
||||
|
||||
if (config.get('env') === 'development') {
|
||||
if (config.get('proxy_settings')) {
|
||||
app.use(settingsPath, createSettingsProxy);
|
||||
|
||||
addNonSettingsRoutes(createSettingsProxy);
|
||||
} else {
|
||||
app.get(settingsPath, modifySettingsStatic);
|
||||
addNonSettingsRoutes(modifySettingsStatic);
|
||||
app.get(settingsPath + '/*', modifySettingsStatic);
|
||||
}
|
||||
|
||||
// it's a four-oh-four not found.
|
||||
|
|
|
@ -40,7 +40,9 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"proxy_settings": true,
|
||||
"static_directory": "app",
|
||||
"page_template_subdirectory": "src",
|
||||
"subscriptions": {
|
||||
"enabled": true
|
||||
},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"env": "production",
|
||||
"proxy_settings": false,
|
||||
"static_directory": "dist",
|
||||
"page_template_subdirectory": "dist",
|
||||
"csp": {
|
||||
|
|
|
@ -9,21 +9,30 @@ const config = require('./configuration');
|
|||
const FLOW_ID_KEY = config.get('flow_id_key');
|
||||
const flowMetrics = require('./flow-metrics');
|
||||
|
||||
let settingsIndexFile;
|
||||
const env = config.get('env');
|
||||
const settingsIndexPath = join(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
config.get('static_directory'),
|
||||
'settings',
|
||||
'index.html'
|
||||
);
|
||||
|
||||
if (env !== 'development') {
|
||||
settingsIndexFile = readFileSync(settingsIndexPath, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
let settingsIndexFile;
|
||||
function getSettingsIndexFile() {
|
||||
if (settingsIndexFile === undefined) {
|
||||
const proxy_settings = config.get('proxy_settings');
|
||||
if (!proxy_settings) {
|
||||
const static_directory = config.get('static_directory');
|
||||
const static_settings_directory = config.get('static_settings_directory');
|
||||
const settingsIndexPath = join(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
static_directory,
|
||||
'settings',
|
||||
static_settings_directory,
|
||||
'index.html'
|
||||
);
|
||||
settingsIndexFile = readFileSync(settingsIndexPath, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
}
|
||||
}
|
||||
return settingsIndexFile;
|
||||
}
|
||||
|
||||
const settingsConfig = {
|
||||
|
@ -162,9 +171,14 @@ const createSettingsProxy = createProxyMiddleware({
|
|||
|
||||
// Modify the static settings page by replacing __SERVER_CONFIG__ with the config object
|
||||
const modifySettingsStatic = function (req, res) {
|
||||
const indexFile = getSettingsIndexFile();
|
||||
if (indexFile === undefined) {
|
||||
throw new Error('Could not locate settings index file.');
|
||||
}
|
||||
|
||||
const flowEventData = flowMetrics.create(FLOW_ID_KEY);
|
||||
return res.send(
|
||||
swapBetaMeta(settingsIndexFile, {
|
||||
swapBetaMeta(indexFile, {
|
||||
__SERVER_CONFIG__: settingsConfig,
|
||||
__FLOW_ID__: flowEventData.flowId,
|
||||
__FLOW_BEGIN_TIME__: flowEventData.flowBeginTime,
|
||||
|
|
|
@ -642,7 +642,7 @@ const conf = (module.exports = convict({
|
|||
doc: 'The root path of server-rendered page templates',
|
||||
},
|
||||
page_template_subdirectory: {
|
||||
default: 'src',
|
||||
default: 'dist',
|
||||
doc: 'Subdirectory of page_template_root for server-rendered page templates',
|
||||
env: 'PAGE_TEMPLATE_SUBDIRECTORY',
|
||||
format: ['src', 'dist'],
|
||||
|
@ -890,12 +890,24 @@ const conf = (module.exports = convict({
|
|||
env: 'METRIC_PREFIX',
|
||||
},
|
||||
},
|
||||
proxy_settings: {
|
||||
default: false,
|
||||
doc: 'Indicates if settings requests should proxy to fxa-settings. This should only be true for local development.',
|
||||
env: 'PROXY_SETTINGS',
|
||||
format: Boolean,
|
||||
},
|
||||
static_directory: {
|
||||
default: 'app',
|
||||
default: 'dist',
|
||||
doc: 'Directory that static files are served from.',
|
||||
env: 'STATIC_DIRECTORY',
|
||||
format: String,
|
||||
},
|
||||
static_settings_directory: {
|
||||
default: 'prod',
|
||||
doc: 'Directory in fxa-settings build folder that contains the target output.',
|
||||
env: 'STATIC_SETTINGS_DIRECTORY',
|
||||
format: ['dev', 'stage', 'prod'],
|
||||
},
|
||||
static_max_age: {
|
||||
default: '10 minutes',
|
||||
doc: 'Cache max age for static assets, in ms',
|
||||
|
|
|
@ -220,11 +220,11 @@ module.exports = function (webpackEnv) {
|
|||
// There will be one main bundle, and one file per asynchronous chunk.
|
||||
// In development, it does not produce real files.
|
||||
filename: isEnvProduction
|
||||
? 'static/js/[name].[contenthash:8].js'
|
||||
? 'static/js/[name].[contenthash].js'
|
||||
: isEnvDevelopment && 'static/js/bundle.js',
|
||||
// There are also additional JS chunk files if you use code splitting.
|
||||
chunkFilename: isEnvProduction
|
||||
? 'static/js/[name].[contenthash:8].chunk.js'
|
||||
? 'static/js/[name].[contenthash].chunk.js'
|
||||
: isEnvDevelopment && 'static/js/[name].chunk.js',
|
||||
assetModuleFilename: 'static/media/[name].[hash][ext]',
|
||||
// webpack uses `publicPath` to determine where the app is being served from.
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
"build-css": "NODE_ENV=production tailwindcss -i ./src/styles/tailwind.css -o ./src/styles/tailwind.out.css --postcss",
|
||||
"build-storybook": "NODE_ENV=production STORYBOOK_BUILD=1 yarn build-css && NODE_OPTIONS=--openssl-legacy-provider sb build && cp -r public/locales ./storybook-static/locales",
|
||||
"build-l10n": "nx l10n-merge && nx l10n-bundle && nx l10n-merge-test",
|
||||
"build-react": "SKIP_PREFLIGHT_CHECK=true INLINE_RUNTIME_CHUNK=false NODE_OPTIONS=--openssl-legacy-provider node scripts/build.js",
|
||||
"build-react": "nx build-react-dev && nx build-react-stage && nx build-react-prod",
|
||||
"build-react-dev": "SKIP_PREFLIGHT_CHECK=true INLINE_RUNTIME_CHUNK=false NODE_OPTIONS=--openssl-legacy-provider BUILD_PATH=build/dev node scripts/build.js",
|
||||
"build-react-stage": "SKIP_PREFLIGHT_CHECK=true INLINE_RUNTIME_CHUNK=false NODE_OPTIONS=--openssl-legacy-provider BUILD_PATH=build/stage node scripts/build.js",
|
||||
"build-react-prod": "SKIP_PREFLIGHT_CHECK=true INLINE_RUNTIME_CHUNK=false NODE_OPTIONS=--openssl-legacy-provider BUILD_PATH=build/prod node scripts/build.js",
|
||||
"clean": "rimraf dist",
|
||||
"compile": "tsc --noEmit",
|
||||
"gql-extract": "persistgraphql src ../../configs/gql/allowlist/fxa-settings.json --js --extension=ts ",
|
||||
|
@ -20,7 +23,7 @@
|
|||
"l10n-merge-test": "yarn grunt merge-ftl:test",
|
||||
"legal-prime": "yarn legal:clone fxa-settings",
|
||||
"lint": "eslint . .storybook",
|
||||
"start": "pm2 start pm2.config.js && yarn check:url localhost:3000/settings/static/js/bundle.js",
|
||||
"start": "BUILD_PATH=build/dev pm2 start pm2.config.js && yarn check:url localhost:3000/settings/static/js/bundle.js",
|
||||
"stop": "pm2 stop pm2.config.js",
|
||||
"restart": "pm2 restart pm2.config.js",
|
||||
"delete": "pm2 delete pm2.config.js",
|
||||
|
|
|
@ -1,6 +1,39 @@
|
|||
// This file was created by react-scripts' (create-react-app) eject script.
|
||||
|
||||
'use strict';
|
||||
// Here we determine which builds to create. Webpack will configure assets
|
||||
// to use a specific URL. In our case, for stage and production builds, we
|
||||
// want this be a CDN url, and for dev it can just be the default relative
|
||||
// path.
|
||||
//
|
||||
// This following is controlled by setting the BUILD_TARGETS env. By default
|
||||
// we build 'dev', but if you wanted to build stage and prod assets then
|
||||
// you'd do this: BUILD_TARGTES=stage,prod yarn build
|
||||
const buildTargets = (process.env.BUILD_TARGETS || 'dev').split(',');
|
||||
const buildDirTarget = (process.env.BUILD_PATH || 'build/dev').replace(
|
||||
'build/',
|
||||
''
|
||||
);
|
||||
if (!buildTargets.includes(buildDirTarget)) {
|
||||
console.log(`Skipping ${buildDirTarget} build.`);
|
||||
return;
|
||||
}
|
||||
switch (buildDirTarget) {
|
||||
case 'prod':
|
||||
process.env.PUBLIC_URL = 'https://accounts-cdn.moz.aws.net';
|
||||
break;
|
||||
case 'stage':
|
||||
process.env.PUBLIC_URL = 'https://accounts-cdn.stage.moz.aws.net';
|
||||
break;
|
||||
default:
|
||||
// This is for local development, and will result in everything being relative.
|
||||
process.env.PUBLIC_URL = undefined;
|
||||
break;
|
||||
}
|
||||
console.log(
|
||||
`Building outputs for: ${buildDirTarget} that will be hosted at ${
|
||||
process.env.PUBLIC_URL || '/'
|
||||
}`
|
||||
);
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'production';
|
||||
|
|
Загрузка…
Ссылка в новой задаче