Skip to content
This repository has been archived by the owner on Jun 28, 2021. It is now read-only.

Commit

Permalink
Many changes to get webpack for server and client (#969)
Browse files Browse the repository at this point in the history
* Many changes to get webpack for server and client

* remove uneeded files

* remove webpack and bin

* fix stylelintrc

* remove

* revert moving

* more changes

* more changes

* revert more changes

* revert more changes

* remove compressed

* remove files again

* fix name

* prettierrc

* remore surah

* fix surah files

* add missing file

* working finally

* fix tests

* few package fixes

* build runner

* offline.html working

* supervisord

* comeon

* move package items

* happypack to deps

* move constants to folder

* add bundlesize

* allow audioplayer to work

* try bundlesize command on own

* few more quick updates
  • Loading branch information
mmahalwy committed Apr 28, 2018
1 parent 6a2f5cb commit c4e2d99
Show file tree
Hide file tree
Showing 115 changed files with 6,286 additions and 5,845 deletions.
6 changes: 4 additions & 2 deletions .babelrc
Expand Up @@ -3,8 +3,10 @@
"plugins": [
"transform-runtime",
"transform-decorators-legacy",
"transform-react-display-name",
["system-import-transformer", {"modules": "common"}]
"transform-react-display-name", ["system-import-transformer", {
"modules": "common"
}],
"transform-react-require", "external-helpers", "transform-export-extensions"
],
"env": {
"production": {
Expand Down
8 changes: 4 additions & 4 deletions .circleci/config.yml
Expand Up @@ -15,11 +15,11 @@ jobs:
name: rebuildSass
command: npm rebuild node-sass
- run:
name: buildClient
command: npm run build:client
name: build
command: npm run build
- run:
name: buildServer
command: npm run build:server
name: bundlesize
command: npm run bundlesize
workflows:
version: 2
test_and_build:
Expand Down
11 changes: 11 additions & 0 deletions .prettierrc
@@ -0,0 +1,11 @@
{
"useTabs": false,
"printWidth": 80,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "es5",
"jsxBracketSameLine": false,
"parser": "babylon",
"noSemi": true,
"rcVerbose": true
}
File renamed without changes.
50 changes: 0 additions & 50 deletions bin/server.js

This file was deleted.

26 changes: 0 additions & 26 deletions bin/server.prod.js

This file was deleted.

42 changes: 42 additions & 0 deletions config/components/ClientConfig.js
@@ -0,0 +1,42 @@
import React from 'react';
import PropTypes from 'prop-types';
import serialize from 'serialize-javascript';
import filterWithRules from '../../shared/utils/objects/filterWithRules';
import values from '../values';

// Filter the config down to the properties that are allowed to be included
// in the HTML response.
const clientConfig = filterWithRules(
// These are the rules used to filter the config.
values.clientConfigFilter,
// The config values to filter.
values
);

const serializedClientConfig = serialize(clientConfig);

/**
* A react component that generates a script tag that binds the allowed
* values to the window so that config values can be read within the
* browser.
*
* They get bound to window.__CLIENT_CONFIG__
*/
function ClientConfig({ nonce }) {
return (
<script
type="text/javascript"
nonce={nonce}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: `window.__CLIENT_CONFIG__=${serializedClientConfig}`
}}
/>
);
}

ClientConfig.propTypes = {
nonce: PropTypes.string.isRequired
};

export default ClientConfig;
123 changes: 123 additions & 0 deletions config/index.js
@@ -0,0 +1,123 @@
/**
* Unified Configuration Reader
*
* This helper function allows you to use the same API in accessing configuration
* values no matter where the code is being executed (i.e. browser/node).
*
* e.g.
* import config from '../../config';
* config('welcomeMessage'); // => "Hello World!"
*/

/* eslint-disable no-console */
/* eslint-disable import/global-require */
/* eslint-disable no-underscore-dangle */

// PRIVATES

let configCache;

/**
* This resolves the correct configuration source based on the execution
* environment. For node we use the standard config file, however, for browsers
* we need to access the configuration object that would have been bound to
* the "window" by our "reactApplication" middleware.
*
* @return {Object} The executing environment configuration object.
*/
function resolveConfigForBrowserOrServer() {
if (configCache) {
return configCache;
}

// NOTE: By using the "process.env.BUILD_FLAG_IS_NODE" flag here this block of code
// will be removed when "process.env.BUILD_FLAG_IS_NODE === true".
// If no "BUILD_FLAG_IS_NODE" env var is undefined we can assume that we are running outside
// of a webpack run, and will therefore return the config file.
if (
typeof process.env.BUILD_FLAG_IS_NODE === 'undefined' ||
process.env.BUILD_FLAG_IS_NODE === 'true'
) {
// i.e. running in our server/node process.
// eslint-disable-next-line global-require
configCache = require('./values').default;
return configCache;
}

// To get here we are likely running in the browser.

if (
typeof window !== 'undefined' &&
typeof window.__CLIENT_CONFIG__ === 'object'
) {
configCache = window.__CLIENT_CONFIG__;
} else {
// To get here we must be running in the browser.
console.warn('No client configuration object was bound to the window.');
configCache = {};
}

return configCache;
}

// EXPORT

/**
* This function wraps up the boilerplate needed to access the correct
* configuration depending on whether your code will get executed in the
* browser/node.
*
* i.e.
* - For the browser the config values are available at window.__CLIENT_CONFIG__
* - For a node process they are within the "<root>/config".
*
* To request a configuration value you must provide the repective path. For
* example, f you had the following configuration structure:
* {
* foo: {
* bar: [1, 2, 3]
* },
* bob: 'bob'
* }
*
* You could use this function to access "bar" like so:
* import config from '../../config';
* const value = config('foo.bar');
*
* And you could access "bob" like so:
* import config from '../../config';
* const value = config('bob');
*
* If any part of the path isn't available as a configuration key/value then
* an error will be thrown indicating that a respective configuration value
* could not be found at the given path.
*/
export default function configGet(path) {
const parts = typeof path === 'string' ? path.split('.') : path;

if (parts.length === 0) {
throw new Error(
'You must provide the path to the configuration value you would like to consume.'
);
}
let result = resolveConfigForBrowserOrServer();
for (let i = 0; i < parts.length; i += 1) {
if (result === undefined) {
const errorMessage = `Failed to resolve configuration value at "${parts.join(
'.'
)}".`;
// This "if" block gets stripped away by webpack for production builds.
if (
process.env.BUILD_FLAG_IS_DEV === 'true' &&
process.env.BUILD_FLAG_IS_CLIENT === 'true'
) {
throw new Error(
`${errorMessage} We have noticed that you are trying to access this configuration value from the client bundle (i.e. code that will be executed in a browser). For configuration values to be exposed to the client bundle you must ensure that the path is added to the client configuration filter in the project configuration values file.`
);
}
throw new Error(errorMessage);
}
result = result[parts[i]];
}
return result;
}
91 changes: 91 additions & 0 deletions config/utils/envVars.js
@@ -0,0 +1,91 @@
/**
* Helper for resolving environment specific configuration files.
*
* It resolves .env files that are supported by the `dotenv` library.
*
* Please read the application configuration docs for more info.
*/

import appRootDir from 'app-root-dir';
import dotenv from 'dotenv';
import fs from 'fs';
import path from 'path';

import ifElse from '../../shared/utils/logic/ifElse';
import removeNil from '../../shared/utils/arrays/removeNil';

import { log } from '../../internal/utils';

// PRIVATES

function registerEnvFile() {
const DEPLOYMENT = process.env.DEPLOYMENT;
const envFile = '.env';

// This is the order in which we will try to resolve an environment configuration
// file.
const envFileResolutionOrder = removeNil([
// Is there an environment config file at the app root?
// This always takes preference.
// e.g. /projects/react-universally/.env
path.resolve(appRootDir.get(), envFile),
// Is there an environment config file at the app root for our target
// environment name?
// e.g. /projects/react-universally/.env.staging
ifElse(DEPLOYMENT)(
path.resolve(appRootDir.get(), `${envFile}.${DEPLOYMENT}`)
)
]);

// Find the first env file path match.
const envFilePath = envFileResolutionOrder.find(filePath =>
fs.existsSync(filePath)
);

// If we found an env file match the register it.
if (envFilePath) {
// eslint-disable-next-line no-console
log({
title: 'server',
level: 'special',
message: `Registering environment variables from: ${envFilePath}`
});
dotenv.config({ path: envFilePath });
}
}

// Ensure that we first register any environment variables from an existing
// env file.
registerEnvFile();

// EXPORTED HELPERS

/**
* Gets a string environment variable by the given name.
*
* @param {String} name - The name of the environment variable.
* @param {String} defaultVal - The default value to use.
*
* @return {String} The value.
*/
export function string(name, defaultVal) {
return process.env[name] || defaultVal;
}

/**
* Gets a number environment variable by the given name.
*
* @param {String} name - The name of the environment variable.
* @param {number} defaultVal - The default value to use.
*
* @return {number} The value.
*/
export function number(name, defaultVal) {
return process.env[name] ? parseInt(process.env[name], 10) : defaultVal;
}

export function bool(name, defaultVal) {
return process.env[name]
? process.env[name] === 'true' || process.env[name] === '1'
: defaultVal;
}

0 comments on commit c4e2d99

Please sign in to comment.