src/roc/builder/index.js
import 'source-map-support/register';
import fs from 'fs';
import path from 'path';
import { getAbsolutePath } from 'roc';
import { createBuilder as createBuilderBase } from 'roc-web';
import { getSettings, appendSettings } from 'roc';
/**
* Creates a builder.
*
* @param {!string} target - a target: should be either "client" or "server"
* @param {rocBuilder} rocBuilder - A rocBuilder to base everything on.
* @param {!string} [resolver=roc-web-react/lib/helpers/get-resolve-path] - Path to the resolver for the server side
* {@link getResolvePath}
* @returns {rocBuilder}
*/
export default function createBuilder(target, rocBuilder, resolver = 'roc-web-react/lib/helpers/get-resolve-path') {
const allowedTargets = ['server', 'client'];
if (allowedTargets.indexOf(target) === -1) {
throw new Error(`Invalid target, must be one of ${allowedTargets}. Was instead ${target}.`);
}
let settings = getSettings('build');
const DEV = (settings.mode === 'dev');
const SERVER = (target === 'server');
const CLIENT = (target === 'client');
const newEntry = {
...settings.entry
};
if (!newEntry[target] && CLIENT) {
newEntry[target] = require.resolve('../../src/default/client');
} else if (!newEntry[target] && SERVER) {
newEntry[target] = require.resolve('../../src/default/server');
}
appendSettings({build: {entry: newEntry}});
settings = getSettings('build');
// Update reference to internal base styles
if (settings.assets.length > 0) {
const updatedAssets = settings.assets.map((asset) => {
const matches = /^roc-web-react\/(.*)/.exec(asset);
if (matches && matches[1]) {
return require.resolve(`../../${matches[1]}`);
}
return asset;
});
appendSettings({build: {assets: updatedAssets}});
}
settings = getSettings('build');
let { buildConfig, builder } = createBuilderBase(target, {}, resolver);
if (SERVER) {
buildConfig.externals = [].concat([
{
'roc-web-react/lib/helpers/read-stats': true,
'roc-web-react/lib/helpers/my-path': true
}
], buildConfig.externals);
}
if (CLIENT) {
buildConfig.plugins.push(
new builder.IgnorePlugin(/^roc$/)
);
}
if (CLIENT && DEV) {
buildConfig.module.loaders.forEach(loader => {
if (loader.loader === 'babel-loader') {
loader.query = {
cacheDirectory: true,
plugins: [require.resolve('babel-plugin-react-transform')],
extra: {
'react-transform': {
transforms: [{
transform: require.resolve('react-transform-hmr'),
imports: [require.resolve('react')],
locals: ['module']
}, {
transform: require.resolve('react-transform-catch-errors'),
imports: [require.resolve('react'), require.resolve('redbox-react')]
}]
}
}
};
}
});
}
buildConfig.resolveLoader.root.push(path.join(__dirname, '../../node_modules'));
buildConfig.resolve.fallback.push(
path.join(__dirname, '../../node_modules')
);
if (settings.routes) {
const routes = getAbsolutePath(settings.routes);
buildConfig.plugins.push(
new builder.DefinePlugin({
REACT_ROUTER_ROUTES: JSON.stringify(routes)
})
);
}
const fileExists = (filepath) => {
filepath = getAbsolutePath(filepath);
try {
return fs.statSync(filepath).isFile();
} catch (error) {
return false;
}
};
const hasReducers = !!(settings.reducers && fileExists(settings.reducers));
const hasMiddlewares = !!(settings.reduxMiddlewares && fileExists(settings.reduxMiddlewares));
const hasClientLoading = !!(settings.clientLoading && fileExists(settings.clientLoading));
if (hasReducers) {
const reducers = getAbsolutePath(settings.reducers);
buildConfig.plugins.push(
new builder.DefinePlugin({
REDUX_REDUCERS: JSON.stringify(reducers)
})
);
}
if (hasMiddlewares) {
const middlewares = getAbsolutePath(settings.reduxMiddlewares);
buildConfig.plugins.push(
new builder.DefinePlugin({
REDUX_MIDDLEWARES: JSON.stringify(middlewares)
})
);
}
if (hasClientLoading) {
const clientLoading = getAbsolutePath(settings.clientLoading);
buildConfig.plugins.push(
new builder.DefinePlugin({
ROC_CLIENT_LOADING: JSON.stringify(clientLoading)
})
);
}
buildConfig.plugins.push(
new builder.DefinePlugin({
USE_DEFAULT_REDUX_REDUCERS: settings.useDefaultReducers,
USE_DEFAULT_REDUX_MIDDLEWARES: settings.useDefaultReduxMiddlewares,
USE_DEFAULT_REACT_ROUTER_ROUTES: settings.useDefaultRoutes,
HAS_REDUX_REDUCERS: hasReducers,
HAS_REDUX_MIDDLEWARES: hasMiddlewares,
HAS_CLIENT_LOADING: hasClientLoading
})
);
return {
buildConfig,
builder
};
}