Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change how CDN_HOST is passed down to make assets build reproducible #14381

Merged
merged 3 commits into from Oct 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions app/javascript/mastodon/components/autosuggest_emoji.js
@@ -1,8 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import unicodeMapping from '../features/emoji/emoji_unicode_mapping_light';

const assetHost = process.env.CDN_HOST || '';
import { assetHost } from 'mastodon/utils/config';

export default class AutosuggestEmoji extends React.PureComponent {

Expand Down
Expand Up @@ -7,6 +7,7 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import detectPassiveEvents from 'detect-passive-events';
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
import { assetHost } from 'mastodon/utils/config';

const messages = defineMessages({
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
Expand All @@ -25,7 +26,6 @@ const messages = defineMessages({
flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' },
});

const assetHost = process.env.CDN_HOST || '';
let EmojiPicker, Emoji; // load asynchronously

const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
Expand Down
3 changes: 1 addition & 2 deletions app/javascript/mastodon/features/emoji/emoji.js
@@ -1,11 +1,10 @@
import { autoPlayGif } from '../../initial_state';
import unicodeMapping from './emoji_unicode_mapping_light';
import { assetHost } from 'mastodon/utils/config';
import Trie from 'substring-trie';

const trie = new Trie(Object.keys(unicodeMapping));

const assetHost = process.env.CDN_HOST || '';

// Convert to file names from emojis. (For different variation selector emojis)
const emojiFilenames = (emojis) => {
return emojis.map(v => unicodeMapping[v].filename);
Expand Down
Expand Up @@ -15,6 +15,7 @@ import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_pick
import AnimatedNumber from 'mastodon/components/animated_number';
import TransitionMotion from 'react-motion/lib/TransitionMotion';
import spring from 'react-motion/lib/spring';
import { assetHost } from 'mastodon/utils/config';

const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
Expand Down Expand Up @@ -153,8 +154,6 @@ class Content extends ImmutablePureComponent {

}

const assetHost = process.env.CDN_HOST || '';

class Emoji extends React.PureComponent {

static propTypes = {
Expand Down
Expand Up @@ -20,6 +20,7 @@ import GIFV from 'mastodon/components/gifv';
import { me } from 'mastodon/initial_state';
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
import tesseractWorkerPath from 'tesseract.js/dist/worker.min.js';
import { assetHost } from 'mastodon/utils/config';

const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
Expand Down Expand Up @@ -50,8 +51,6 @@ const removeExtraLineBreaks = str => str.replace(/\n\n/g, '******')
.replace(/\n/g, ' ')
.replace(/\*\*\*\*\*\*/g, '\n\n');

const assetHost = process.env.CDN_HOST || '';

class ImageLoader extends React.PureComponent {

static propTypes = {
Expand Down
10 changes: 10 additions & 0 deletions app/javascript/mastodon/utils/config.js
@@ -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 change: 1 addition & 0 deletions app/javascript/packs/about.js
@@ -1,3 +1,4 @@
import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
import { start } from '../mastodon/common';

Expand Down
1 change: 1 addition & 0 deletions app/javascript/packs/admin.js
@@ -1,3 +1,4 @@
import './public-path';
import { delegate } from '@rails/ujs';
import ready from '../mastodon/ready';

Expand Down
1 change: 1 addition & 0 deletions app/javascript/packs/application.js
@@ -1,3 +1,4 @@
import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
import { start } from '../mastodon/common';

Expand Down
1 change: 1 addition & 0 deletions app/javascript/packs/error.js
@@ -1,3 +1,4 @@
import './public-path';
import ready from '../mastodon/ready';

ready(() => {
Expand Down
21 changes: 21 additions & 0 deletions app/javascript/packs/public-path.js
@@ -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 change: 1 addition & 0 deletions app/javascript/packs/public.js
@@ -1,3 +1,4 @@
import './public-path';
import escapeTextContentForBrowser from 'escape-html';
import loadPolyfills from '../mastodon/load_polyfills';
import ready from '../mastodon/ready';
Expand Down
1 change: 1 addition & 0 deletions app/javascript/packs/share.js
@@ -1,3 +1,4 @@
import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
import { start } from '../mastodon/common';

Expand Down
1 change: 1 addition & 0 deletions app/views/layouts/application.html.haml
Expand Up @@ -6,6 +6,7 @@

- if cdn_host?
%link{ rel: 'dns-prefetch', href: cdn_host }/
%meta{ name: 'cdn-host', content: cdn_host }/

- if storage_host?
%link{ rel: 'dns-prefetch', href: storage_host }/
Expand Down
1 change: 1 addition & 0 deletions app/views/layouts/embedded.html.haml
Expand Up @@ -6,6 +6,7 @@

- if cdn_host?
%link{ rel: 'dns-prefetch', href: cdn_host }/
%meta{ name: 'cdn-host', content: cdn_host }/

- if storage_host?
%link{ rel: 'dns-prefetch', href: storage_host }/
Expand Down
17 changes: 2 additions & 15 deletions config/webpack/configuration.js
Expand Up @@ -11,30 +11,17 @@ const settings = safeLoad(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env
const themePath = resolve('config', 'themes.yml');
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 = {
path: resolve('public', settings.public_output_path),
publicPath: formatPublicPath(env.CDN_HOST, settings.public_output_path),
publicPath: `/${settings.public_output_path}/`,
};

module.exports = {
settings,
themes,
env: {
CDN_HOST: env.CDN_HOST,
NODE_ENV: env.NODE_ENV,
PUBLIC_OUTPUT_PATH: settings.public_output_path,
},
output,
};