Skip to content

Commit

Permalink
Add production build script (vega#320)
Browse files Browse the repository at this point in the history
* move web pack to config/ add build / start scripts

* Remove unnecessary additions to build system. 
Provide a production build process.

* Remove unneeded address package.

* update redux-logger
  • Loading branch information
vlandham authored and kanitw committed May 18, 2017
1 parent 20cc13f commit b8cd805
Show file tree
Hide file tree
Showing 13 changed files with 947 additions and 88 deletions.
48 changes: 48 additions & 0 deletions config/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';

var fs = require('fs');
var paths = require('./paths');

var NODE_ENV = process.env.NODE_ENV;
if (!NODE_ENV) {
NODE_ENV = 'development';
}

// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration.
const REACT_APP = /^REACT_APP_/i;

function getClientEnvironment(publicUrl) {
const raw = Object.keys(process.env)
.filter(key => REACT_APP.test(key))
.reduce(
(env, key) => {
env[key] = process.env[key];
return env;
},
{
// Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV,
// Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
// This should only be used as an escape hatch. Normally you would put
// images into the `src` and `import` them in code to get their paths.
PUBLIC_URL: publicUrl,
}
);
// Stringify all values so we can feed into Webpack DefinePlugin
const stringified = {
'process.env': Object.keys(raw).reduce(
(env, key) => {
env[key] = JSON.stringify(raw[key]);
return env;
},
{}
),
};

return { raw, stringified };
}

module.exports = getClientEnvironment;
80 changes: 80 additions & 0 deletions config/paths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use strict';

const path = require('path');
const fs = require('fs');
const url = require('url');

// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebookincubator/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
function resolveApp(relativePath) {
return path.resolve(appDirectory, relativePath);
}

// We support resolving modules according to `NODE_PATH`.
// This lets you use absolute paths in imports inside large monorepos:
// https://github.com/facebookincubator/create-react-app/issues/253.

// It works similar to `NODE_PATH` in Node itself:
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders

// We will export `nodePaths` as an array of absolute paths.
// It will then be used by Webpack configs.
// Jest doesn’t need this because it already handles `NODE_PATH` out of the box.

// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421

const nodePaths = (process.env.NODE_PATH || '')
.split(process.platform === 'win32' ? ';' : ':')
.filter(Boolean)
.filter(folder => !path.isAbsolute(folder))
.map(resolveApp);

const envPublicUrl = process.env.PUBLIC_URL;

function ensureSlash(path, needsSlash) {
const hasSlash = path.endsWith('/');
if (hasSlash && !needsSlash) {
return path.substr(path, path.length - 1);
} else if (!hasSlash && needsSlash) {
return `${path}/`;
} else {
return path;
}
}

function getPublicUrl(appPackageJson) {
return envPublicUrl || require(appPackageJson).homepage;
}

// We use `PUBLIC_URL` environment variable or "homepage" field to infer
// "public path" at which the app is served.
// Webpack needs to know it to put the right <script> hrefs into HTML even in
// single-page apps that may serve index.html for nested URLs like /todos/42.
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
function getServedPath(appPackageJson) {
const publicUrl = getPublicUrl(appPackageJson);
const servedUrl = envPublicUrl ||
(publicUrl ? url.parse(publicUrl).pathname : '/');
return ensureSlash(servedUrl, true);
}

// config after eject: we're in ./config/
module.exports = {
dotenv: resolveApp('.env'),
appBuild: resolveApp('dist'),
appBuildDev: resolveApp('/'),
appHtml: resolveApp('index.html'),
appIndexJs: resolveApp('src/index.tsx'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveApp('src/setupTests.js'),
appNodeModules: resolveApp('node_modules'),
nodePaths: nodePaths,
publicUrl: getPublicUrl(resolveApp('package.json')),
servedPath: getServedPath(resolveApp('package.json')),
};
16 changes: 16 additions & 0 deletions config/polyfills.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

if (typeof Promise === 'undefined') {
// Rejection tracking prevents a common issue where React gets into an
// inconsistent state due to an error, but it gets swallowed by a Promise,
// and the user has no idea what causes React's erratic future behavior.
require('promise/lib/rejection-tracking').enable();
window.Promise = require('promise/lib/es6-extensions.js');
}

// fetch() polyfill for making API calls.
require('whatwg-fetch');

// Object.assign() is commonly used with React.
// It will use the native implementation if it's present and isn't buggy.
Object.assign = require('object-assign');
35 changes: 30 additions & 5 deletions webpack.config.js → config/webpack.config.dev.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
var path = require('path');

const webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var WebpackNotifierPlugin = require('webpack-notifier');

const getClientEnvironment = require('./env');
// Get environment variables to inject into our app.
var publicUrl = '';
const env = getClientEnvironment(publicUrl);

module.exports = {
entry: {
bundle: path.resolve(__dirname, 'src/index.tsx'),
bundle: path.resolve(__dirname, '../src/index.tsx'),
vendor: [
// React
'react-css-modules',
Expand All @@ -30,7 +37,11 @@ module.exports = {
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, 'dist'),
path: path.resolve(__dirname, '../dist'),
// Add /* filename */ comments to generated require()s in the output.
pathinfo: true,
// There are also additional JS chunk files if you use code splitting.
chunkFilename: 'static/js/[name].chunk.js',
publicPath: '/dist/'
},

Expand All @@ -40,7 +51,7 @@ module.exports = {
devtool: 'source-map',

devServer: {
contentBase: __dirname,
contentBase: path.resolve(__dirname, '../'),
compress: true,
port: 9000
},
Expand Down Expand Up @@ -85,7 +96,7 @@ module.exports = {
options: {
sourceMap: true,
includePaths: [
path.resolve(__dirname, "node_modules/normalize-scss/sass")
path.resolve(__dirname, "../node_modules/normalize-scss/sass")
]
}
}]
Expand Down Expand Up @@ -119,10 +130,24 @@ module.exports = {
"react-dom": "ReactDOM"
},
plugins: [
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
new webpack.DefinePlugin(env.stringified),

// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebookincubator/create-react-app/issues/240
new CaseSensitivePathsPlugin(),
new ExtractTextPlugin({
filename: "style.css",
disable: false
}),
new WebpackNotifierPlugin()
]
],
// Turn off performance hints during development because we don't do any
// splitting or minification in interest of speed. These warnings become
// cumbersome.
performance: {
hints: false,
},
};
Loading

0 comments on commit b8cd805

Please sign in to comment.