Change how CDN_HOST is passed down to make assets build reproducible (#14381)
* Change how CDN_HOST is passed down to make assets build reproducible * Change webpacker/webpack configuration to dynamically load publicPath based on meta header * Fix embedded layout missing the cdn-host meta header
This commit is contained in:
parent
53b22d247f
commit
4c45b43cb8
16 changed files with 46 additions and 24 deletions
|
@ -1,8 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import unicodeMapping from '../features/emoji/emoji_unicode_mapping_light';
|
import unicodeMapping from '../features/emoji/emoji_unicode_mapping_light';
|
||||||
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
const assetHost = process.env.CDN_HOST || '';
|
|
||||||
|
|
||||||
export default class AutosuggestEmoji extends React.PureComponent {
|
export default class AutosuggestEmoji extends React.PureComponent {
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import classNames from 'classnames';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import detectPassiveEvents from 'detect-passive-events';
|
||||||
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
|
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
|
||||||
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
|
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
|
||||||
|
@ -25,7 +26,6 @@ const messages = defineMessages({
|
||||||
flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' },
|
flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const assetHost = process.env.CDN_HOST || '';
|
|
||||||
let EmojiPicker, Emoji; // load asynchronously
|
let EmojiPicker, Emoji; // load asynchronously
|
||||||
|
|
||||||
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
|
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { autoPlayGif } from '../../initial_state';
|
import { autoPlayGif } from '../../initial_state';
|
||||||
import unicodeMapping from './emoji_unicode_mapping_light';
|
import unicodeMapping from './emoji_unicode_mapping_light';
|
||||||
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
import Trie from 'substring-trie';
|
import Trie from 'substring-trie';
|
||||||
|
|
||||||
const trie = new Trie(Object.keys(unicodeMapping));
|
const trie = new Trie(Object.keys(unicodeMapping));
|
||||||
|
|
||||||
const assetHost = process.env.CDN_HOST || '';
|
|
||||||
|
|
||||||
// Convert to file names from emojis. (For different variation selector emojis)
|
// Convert to file names from emojis. (For different variation selector emojis)
|
||||||
const emojiFilenames = (emojis) => {
|
const emojiFilenames = (emojis) => {
|
||||||
return emojis.map(v => unicodeMapping[v].filename);
|
return emojis.map(v => unicodeMapping[v].filename);
|
||||||
|
|
|
@ -15,6 +15,7 @@ import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_pick
|
||||||
import AnimatedNumber from 'mastodon/components/animated_number';
|
import AnimatedNumber from 'mastodon/components/animated_number';
|
||||||
import TransitionMotion from 'react-motion/lib/TransitionMotion';
|
import TransitionMotion from 'react-motion/lib/TransitionMotion';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
|
@ -153,8 +154,6 @@ class Content extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const assetHost = process.env.CDN_HOST || '';
|
|
||||||
|
|
||||||
class Emoji extends React.PureComponent {
|
class Emoji extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import GIFV from 'mastodon/components/gifv';
|
||||||
import { me } from 'mastodon/initial_state';
|
import { me } from 'mastodon/initial_state';
|
||||||
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
|
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
|
||||||
import tesseractWorkerPath from 'tesseract.js/dist/worker.min.js';
|
import tesseractWorkerPath from 'tesseract.js/dist/worker.min.js';
|
||||||
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
|
@ -50,8 +51,6 @@ const removeExtraLineBreaks = str => str.replace(/\n\n/g, '******')
|
||||||
.replace(/\n/g, ' ')
|
.replace(/\n/g, ' ')
|
||||||
.replace(/\*\*\*\*\*\*/g, '\n\n');
|
.replace(/\*\*\*\*\*\*/g, '\n\n');
|
||||||
|
|
||||||
const assetHost = process.env.CDN_HOST || '';
|
|
||||||
|
|
||||||
class ImageLoader extends React.PureComponent {
|
class ImageLoader extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
10
app/javascript/mastodon/utils/config.js
Normal file
10
app/javascript/mastodon/utils/config.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import ready from '../ready';
|
||||||
|
|
||||||
|
export let assetHost = '';
|
||||||
|
|
||||||
|
ready(() => {
|
||||||
|
const cdnHost = document.querySelector('meta[name=cdn-host]');
|
||||||
|
if (cdnHost) {
|
||||||
|
assetHost = cdnHost.content || '';
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,3 +1,4 @@
|
||||||
|
import './public-path';
|
||||||
import loadPolyfills from '../mastodon/load_polyfills';
|
import loadPolyfills from '../mastodon/load_polyfills';
|
||||||
import { start } from '../mastodon/common';
|
import { start } from '../mastodon/common';
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import './public-path';
|
||||||
import { delegate } from '@rails/ujs';
|
import { delegate } from '@rails/ujs';
|
||||||
import ready from '../mastodon/ready';
|
import ready from '../mastodon/ready';
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import './public-path';
|
||||||
import loadPolyfills from '../mastodon/load_polyfills';
|
import loadPolyfills from '../mastodon/load_polyfills';
|
||||||
import { start } from '../mastodon/common';
|
import { start } from '../mastodon/common';
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import './public-path';
|
||||||
import ready from '../mastodon/ready';
|
import ready from '../mastodon/ready';
|
||||||
|
|
||||||
ready(() => {
|
ready(() => {
|
||||||
|
|
21
app/javascript/packs/public-path.js
Normal file
21
app/javascript/packs/public-path.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Dynamically set webpack's loading path depending on a meta header, in order
|
||||||
|
// to share the same assets regardless of instance configuration.
|
||||||
|
// See https://webpack.js.org/guides/public-path/#on-the-fly
|
||||||
|
|
||||||
|
function removeOuterSlashes(string) {
|
||||||
|
return string.replace(/^\/*/, '').replace(/\/*$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatPublicPath(host = '', path = '') {
|
||||||
|
let formattedHost = removeOuterSlashes(host);
|
||||||
|
if (formattedHost && !/^http/i.test(formattedHost)) {
|
||||||
|
formattedHost = `//${formattedHost}`;
|
||||||
|
}
|
||||||
|
const formattedPath = removeOuterSlashes(path);
|
||||||
|
return `${formattedHost}/${formattedPath}/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cdnHost = document.querySelector('meta[name=cdn-host]');
|
||||||
|
|
||||||
|
// eslint-disable-next-line camelcase, no-undef, no-unused-vars
|
||||||
|
__webpack_public_path__ = formatPublicPath(cdnHost ? cdnHost.content : '', process.env.PUBLIC_OUTPUT_PATH);
|
|
@ -1,3 +1,4 @@
|
||||||
|
import './public-path';
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
import escapeTextContentForBrowser from 'escape-html';
|
||||||
import loadPolyfills from '../mastodon/load_polyfills';
|
import loadPolyfills from '../mastodon/load_polyfills';
|
||||||
import ready from '../mastodon/ready';
|
import ready from '../mastodon/ready';
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import './public-path';
|
||||||
import loadPolyfills from '../mastodon/load_polyfills';
|
import loadPolyfills from '../mastodon/load_polyfills';
|
||||||
import { start } from '../mastodon/common';
|
import { start } from '../mastodon/common';
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
- if cdn_host?
|
- if cdn_host?
|
||||||
%link{ rel: 'dns-prefetch', href: cdn_host }/
|
%link{ rel: 'dns-prefetch', href: cdn_host }/
|
||||||
|
%meta{ name: 'cdn-host', content: cdn_host }/
|
||||||
|
|
||||||
- if storage_host?
|
- if storage_host?
|
||||||
%link{ rel: 'dns-prefetch', href: storage_host }/
|
%link{ rel: 'dns-prefetch', href: storage_host }/
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
- if cdn_host?
|
- if cdn_host?
|
||||||
%link{ rel: 'dns-prefetch', href: cdn_host }/
|
%link{ rel: 'dns-prefetch', href: cdn_host }/
|
||||||
|
%meta{ name: 'cdn-host', content: cdn_host }/
|
||||||
|
|
||||||
- if storage_host?
|
- if storage_host?
|
||||||
%link{ rel: 'dns-prefetch', href: storage_host }/
|
%link{ rel: 'dns-prefetch', href: storage_host }/
|
||||||
|
|
|
@ -11,30 +11,17 @@ const settings = safeLoad(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env
|
||||||
const themePath = resolve('config', 'themes.yml');
|
const themePath = resolve('config', 'themes.yml');
|
||||||
const themes = safeLoad(readFileSync(themePath), 'utf8');
|
const themes = safeLoad(readFileSync(themePath), 'utf8');
|
||||||
|
|
||||||
function removeOuterSlashes(string) {
|
|
||||||
return string.replace(/^\/*/, '').replace(/\/*$/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatPublicPath(host = '', path = '') {
|
|
||||||
let formattedHost = removeOuterSlashes(host);
|
|
||||||
if (formattedHost && !/^http/i.test(formattedHost)) {
|
|
||||||
formattedHost = `//${formattedHost}`;
|
|
||||||
}
|
|
||||||
const formattedPath = removeOuterSlashes(path);
|
|
||||||
return `${formattedHost}/${formattedPath}/`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = {
|
const output = {
|
||||||
path: resolve('public', settings.public_output_path),
|
path: resolve('public', settings.public_output_path),
|
||||||
publicPath: formatPublicPath(env.CDN_HOST, settings.public_output_path),
|
publicPath: `/${settings.public_output_path}/`,
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
settings,
|
settings,
|
||||||
themes,
|
themes,
|
||||||
env: {
|
env: {
|
||||||
CDN_HOST: env.CDN_HOST,
|
|
||||||
NODE_ENV: env.NODE_ENV,
|
NODE_ENV: env.NODE_ENV,
|
||||||
|
PUBLIC_OUTPUT_PATH: settings.public_output_path,
|
||||||
},
|
},
|
||||||
output,
|
output,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue