react-universally
Version:
A starter kit for universal react applications.
333 lines (293 loc) • 11.8 kB
JavaScript
/**
* Project Configuration.
*
* NOTE: All file/folder paths should be relative to the project root. The
* absolute paths should be resolved during runtime by our build internal/server.
*/
import * as EnvVars from './utils/envVars';
const values = {
// The configuration values that should be exposed to our client bundle.
// This value gets passed through the /shared/utils/objects/filterWithRules
// util to create a filter object that can be serialised and included
// with our client bundle.
clientConfigFilter: {
// This is here as an example showing that you can expose variables
// that were potentially provivded by the environment
welcomeMessage: true,
// We only need to expose the enabled flag of the service worker.
serviceWorker: {
enabled: true,
},
// We need to expose all the polyfill.io settings.
polyfillIO: true,
// We need to expose all the htmlPage settings.
htmlPage: true,
},
// The host on which the server should run.
host: EnvVars.string('HOST', '0.0.0.0'),
// The port on which the server should run.
port: EnvVars.number('PORT', 1337),
// The port on which the client bundle development server should run.
clientDevServerPort: EnvVars.number('CLIENT_DEV_PORT', 7331),
// This is an example environment variable which is used within the react
// application to demonstrate the usage of environment variables across
// the client and server bundles.
welcomeMessage: EnvVars.string('WELCOME_MSG', 'Hello world!'),
// Disable server side rendering?
disableSSR: false,
// How long should we set the browser cache for the served assets?
// Don't worry, we add hashes to the files, so if they change the new files
// will be served to browsers.
// We are using the "ms" format to set the length.
// @see https://www.npmjs.com/package/ms
browserCacheMaxAge: '365d',
// We use the polyfill.io service which provides the polyfills that a
// client needs, which is far more optimal than the large output
// generated by babel-polyfill.
// Note: we have to keep this seperate from our "htmlPage" configuration
// as the polyfill needs to be loaded BEFORE any of our other javascript
// gets parsed.
polyfillIO: {
enabled: true,
// Reference https://qa.polyfill.io/v2/docs/features for a full list
// of features.
features: [
// The default list.
'default',
// All es6 features.
'es6',
],
},
// Basic configuration for the HTML page that hosts our application.
// We make use of react-helmet to consume the values below.
// @see https://github.com/nfl/react-helmet
htmlPage: {
titleTemplate: 'React, Universally - %s',
defaultTitle: 'React, Universally',
description: 'A starter kit giving you the minimum requirements for a production ready universal react application.',
},
// Content Security Policy (CSP)
// @see server/middleware/security for more info.
cspExtensions: {
childSrc: [],
connectSrc: [],
defaultSrc: [],
fontSrc: ['https://fonts.googleapis.com/css', 'https://fonts.gstatic.com'],
imgSrc: [],
mediaSrc: [],
manifestSrc: [],
objectSrc: [],
scriptSrc: [
// Allow scripts from https://cdn.polyfill.io so that we can import the
// polyfill.
'https://cdn.polyfill.io',
],
styleSrc: [
'https://cdn.rawgit.com/milligram/milligram/master/dist/milligram.min.css',
'https://fonts.googleapis.com/css',
],
},
// Path to the public assets that will be served off the root of the
// HTTP server.
publicAssetsPath: './public',
// Where does our build output live?
buildOutputPath: './build',
// Do you want to included source maps for optimised builds of the client
// bundle?
includeSourceMapsForOptimisedClientBundle: false,
// These extensions are tried when resolving src files for our bundles..
bundleSrcTypes: ['js', 'jsx', 'json'],
// Additional asset types to be supported for our bundles.
// i.e. you can import the following file types within your source and the
// webpack bundling process will bundle them with your source and create
// URLs for them that can be resolved at runtime.
bundleAssetTypes: [
'jpg',
'jpeg',
'png',
'gif',
'ico',
'eot',
'svg',
'ttf',
'woff',
'woff2',
'otf',
],
// What should we name the json output file that webpack generates
// containing details of all output files for a bundle?
bundleAssetsFileName: 'assets.json',
// node_modules are not included in any bundles that target "node" as a
// runtime (e.g.. the server bundle) as including them often breaks builds
// due to thinks like require statements containing expressions..
// However. some of the modules contain files need to be processed by
// one of our Webpack loaders (e.g. CSS). Add any file types to the list
// below to allow them to be processed by Webpack.
nodeExternalsFileTypeWhitelist: [
/\.(eot|woff|woff2|ttf|otf)$/,
/\.(svg|png|jpg|jpeg|gif|ico)$/,
/\.(mp4|mp3|ogg|swf|webp)$/,
/\.(css|scss|sass|sss|less)$/,
],
// Note: you can only have a single service worker instance. Our service
// worker implementation is bound to the "client" and "server" bundles.
// It includes the "client" bundle assets, as well as the public folder assets,
// and it is served by the "server" bundle.
serviceWorker: {
// Enabled?
enabled: true,
// Service worker name
fileName: 'sw.js',
// Paths to the public assets which should be included within our
// service worker. Relative to our public folder path, and accepts glob
// syntax.
includePublicAssets: [
// NOTE: This will include ALL of our public folder assets. We do
// a glob pull of them and then map them to /foo paths as all the
// public folder assets get served off the root of our application.
// You may or may not want to be including these assets. Feel free
// to remove this or instead include only a very specific set of
// assets.
'./**/*',
],
// Offline page file name.
offlinePageFileName: 'offline.html',
},
bundles: {
client: {
// Src entry file.
srcEntryFile: './client/index.js',
// Src paths.
srcPaths: [
'./client',
'./shared',
// The service worker offline page generation needs access to the
// config folder. Don't worry we have guards within the config files
// to ensure they never get included in a client bundle.
'./config',
],
// Where does the client bundle output live?
outputPath: './build/client',
// What is the public http path at which we must serve the bundle from?
webPath: '/client/',
// Configuration settings for the development vendor DLL. This will be created
// by our development server and provides an improved dev experience
// by decreasing the number of modules that webpack needs to process
// for every rebuild of our client bundle. It by default uses the
// dependencies configured in package.json however you can customise
// which of these dependencies are excluded, whilst also being able to
// specify the inclusion of additional modules below.
devVendorDLL: {
// Enabled?
enabled: true,
// Specify any dependencies that you would like to include in the
// Vendor DLL.
//
// NOTE: It is also possible that some modules require specific
// webpack loaders in order to be processed (e.g. CSS/SASS etc).
// For these cases you don't want to include them in the Vendor DLL.
include: [
'react-async-component',
'react',
'react-dom',
'react-helmet',
'react-router-dom',
],
// The name of the vendor DLL.
name: '__dev_vendor_dll__',
},
},
server: {
// Src entry file.
srcEntryFile: './server/index.js',
// Src paths.
srcPaths: ['./server', './shared', './config'],
// Where does the server bundle output live?
outputPath: './build/server',
},
},
additionalNodeBundles: {
// NOTE: The webpack configuration and build scripts have been built so
// that you can add arbitrary additional node bundle configurations here.
//
// A common requirement for larger projects is to add additional "node"
// target bundles (e.g an APi server endpoint). Therefore flexibility has been
// baked into our webpack config factory to allow for this.
//
// Simply define additional configurations similar to below. The development
// server will manage starting them up for you. The only requirement is that
// within the entry for each bundle you create and return the "express"
// listener.
/*
apiServer: {
srcEntryFile: './api/index.js',
srcPaths: [
'./api',
'./shared',
'./config',
],
outputPath: './build/api',
}
*/
},
// These plugin definitions provide you with advanced hooks into customising
// the project without having to reach into the internals of the tools.
//
// We have decided to create this plugin approach so that you can come to
// a centralised configuration folder to do most of your application
// configuration adjustments. Additionally it helps to make merging
// from the origin starter kit a bit easier.
plugins: {
// This plugin allows you to provide final adjustments your babel
// configurations for each bundle before they get processed.
//
// This function will be called once for each for your bundles. It will be
// provided the current webpack config, as well as the buildOptions which
// detail which bundle and mode is being targetted for the current function run.
babelConfig: (babelConfig, buildOptions) => {
// eslint-disable-next-line no-unused-vars
const { target, mode } = buildOptions;
// Example
/*
if (target === 'server' && mode === 'development') {
babelConfig.presets.push('foo');
}
*/
return babelConfig;
},
// This plugin allows you to provide final adjustments your webpack
// configurations for each bundle before they get processed.
//
// I would recommend looking at the "webpack-merge" module to help you with
// merging modifications to each config.
//
// This function will be called once for each for your bundles. It will be
// provided the current webpack config, as well as the buildOptions which
// detail which bundle and mode is being targetted for the current function run.
webpackConfig: (webpackConfig, buildOptions) => {
// eslint-disable-next-line no-unused-vars
const { target, mode } = buildOptions;
// Example:
/*
if (target === 'server' && mode === 'development') {
webpackConfig.plugins.push(new MyCoolWebpackPlugin());
}
*/
// Debugging/Logging Example:
/*
if (target === 'server') {
console.log(JSON.stringify(webpackConfig, null, 4));
}
*/
return webpackConfig;
},
},
};
// This protects us from accidentally including this configuration in our
// client bundle. That would be a big NO NO to do. :)
if (process.env.BUILD_FLAG_IS_CLIENT === 'true') {
throw new Error(
"You shouldn't be importing the `<projectroot>/config/values.js` directly into code that will be included in your 'client' bundle as the configuration object will be sent to user's browsers. This could be a security risk! Instead, use the `config` helper function located at `<projectroot>/config/index.js`.",
);
}
export default values;