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

Enable configuration file and webpack config file #87

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@ arch-cli serve

your application is now running on <http://localhost:3000>.

## Configuration

Arch is configurable by environment variables or a `arch.config.js` / `arch.config.ls` file in your project root.

Hardcoded config (passed to arch.server) takes precedence over environment variables.

##### List of configuration options

| option | env variable | description | default |
|-------------|----------------------------|---------------------------------------------------------|-----------------------------------|
| appPath | arch_app_path | absolute path to app directory ** | your app's package.json directory |
| archPath | arch_arch_path | absolute path to arch directory ** | arch's package.json directory |
| bundle | arch_bundle | handle bundling of js in arch | true in development |
| debug | arch_debug | show debug output | false |
| environment | arch_environment, NODE_ENV | environment for arch to target | development |
| minify | arch_minify | minify client output | true in production |
| public | arch_public | asset path (relative to app path) | 'dist' |
| port | arch_port, ARCH_PORT* | port to listen on | 3000 |
| watch | arch_watch | watch for fs changes and reload server + rebuild client | true in development |

<sub> * Will be deprecated </sub>
<sub> ** You probably never need to touch this </sub>

## Documentation

Arch doesn't have a website yet, but you can [read the
Expand Down
2 changes: 1 addition & 1 deletion lib/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
cursor = require('./cursor');
dom = require('./dom');
routes = require('./routes');
serverRendering = require('./server-rendering');
serverRendering = require('./server/server-rendering');
unescape = require('lodash/string/unescape');
domUtils = require('./virtual-dom-utils');
span = dom.span;
Expand Down
74 changes: 19 additions & 55 deletions lib/bundler.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,25 @@
(function(){
var webpack, path, webpackDevServer, ref$, Obj, keys;
var webpack, path, webpackDevServer, fs, deepExtend, archWebpackConfig, ref$, Obj, keys;
webpack = require('webpack');
path = require('path');
webpackDevServer = require('webpack-dev-server');
fs = require('fs');
deepExtend = require('deep-extend');
archWebpackConfig = require('./webpack.config');
ref$ = require('prelude-ls'), Obj = ref$.Obj, keys = ref$.keys;
exports.bundle = function(paths, watch, changed){
var entry, browserEnv, config, bundler, lastBuild, server;
entry = require.resolve(paths.app.abs);
browserEnv = clone$(process.env);
browserEnv.ARCH_ENV = 'browser';
browserEnv = Obj.map(JSON.stringify)(
browserEnv);
config = {
entry: ['./' + path.basename(entry)],
context: path.dirname(entry),
output: {
libraryTarget: 'var',
library: 'Application',
path: path.join(paths.app.abs, paths['public']),
filename: 'app.js'
},
resolve: {
root: path.join(paths.app.abs, 'node_modules'),
fallback: path.join(paths.arch.abs, 'node_modules'),
extensions: ['', '.ls', '.js', '.jsx']
},
resolveLoader: {
root: path.join(paths.arch.abs, 'node_modules'),
fallback: path.join(paths.app.abs, 'node_modules')
},
plugins: [new webpack.DefinePlugin({
'process.env': browserEnv
})],
module: {
preLoaders: [
{
test: /\.ls$/,
loader: 'livescript-loader',
exclude: /node_modules/
}, {
test: /\.(?:js|jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/
}
],
loaders: [],
postLoaders: []
},
devtool: 'source-map'
};
if (process.env.NODE_ENV === 'production') {
exports.bundle = function(options, changed){
var baseConf, userConf, config, bundler, lastBuild, server;
baseConf = archWebpackConfig(options);
userConf = {};
try {
userConf = require(path.join(options.appPath, 'webpack.config.js'));
} catch (e$) {}
config = deepExtend(baseConf, userConf);
if (options.minify) {
config.plugins.push(new webpack.optimize.DedupePlugin());
config.plugins.push(new webpack.optimize.UglifyJsPlugin());
}
if (watch) {
if (options.watch) {
config.entry.unshift('webpack/hot/dev-server');
config.entry.unshift('webpack-dev-server/client?http://localhost:3001');
config.output.publicPath = 'http://localhost:3001/';
Expand All @@ -66,7 +32,7 @@
config.plugins.push(new webpack.NoErrorsPlugin());
}
bundler = webpack(config);
if (watch) {
if (options.watch) {
lastBuild = null;
bundler.plugin('done', function(stats){
var diff;
Expand All @@ -83,7 +49,7 @@
});
server = new webpackDevServer(bundler, {
filename: 'app.js',
contentBase: path.join(paths.app.abs, paths['public']),
contentBase: path.join(options.appPath, options['public']),
hot: true,
quiet: true,
noInfo: false,
Expand All @@ -93,14 +59,12 @@
}
});
return server.listen(3001, 'localhost');
} else {
} else if (options.bundle) {
return bundler.run(function(err, stats){
return console.log('Bundled app.js');
});
} else {
return console.warn("Built-in watch and bundle disabled. Compile your own client bundle!");
}
};
function clone$(it){
function fun(){} fun.prototype = it;
return new fun;
}
}).call(this);
6 changes: 6 additions & 0 deletions lib/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(function(){
var rc, defaultConfig;
rc = require('rc');
defaultConfig = require('./default-config');
module.exports = rc('arch', defaultConfig);
}).call(this);
149 changes: 149 additions & 0 deletions lib/default-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
(function(){
var path, fs, ref$, filter, map, first, join, keys, parsers, parser, fpathRegex, filterConfigs, merge, initialConf, config, defaultConfig;
path = require('path');
fs = require('fs');
ref$ = require('prelude-ls'), filter = ref$.filter, map = ref$.map, first = ref$.first, join = ref$.join, keys = ref$.keys;
/* Map of parsers which take a file path and parse functions*/
parsers = {
js: function(it){
return require(it);
},
ls: function(it){
return require(it);
}
};
parser = function(fname){
return parsers[path.extname(fname).slice(1)](fname);
};
fpathRegex = new RegExp("arch.config.(?:" + join('|')(
keys(
parsers)) + ")$");
filterConfigs = function(it){
return fpathRegex.test(it);
};
merge = function(x, xs){
return import$(x, xs);
};
initialConf = {
appPath: process.env.arch_app_path || path.resolve('.'),
archPath: process.env.arch_arch_path || path.dirname(require.resolve('../package.json')),
bundle: process.env.arch_bundle || true,
debug: process.env.arch_debug || false,
environment: process.env.arch_environment || process.env.NODE_ENV || 'development',
minify: process.env.arch_minify || process.env.NODE_ENV === 'production',
'public': process.env.arch_public || 'dist',
port: process.env.ARCH_PORT || process.env.arch_port || 3000,
watch: process.env.arch_watch || process.env.NODE_ENV !== 'production'
};
config = null;
defaultConfig = function(){
var files, confFiles, config;
if (config) {
return config;
}
files = fs.readdirSync(path.dirname('.'));
confFiles = filter(filterConfigs, map(function(it){
return path.resolve('.', it);
}, files));
if (confFiles.length > 1) {
console.error('Multiple configs found. Please have one arch.config.ls or arch.config.js');
config = initialConf;
} else if (deepEq$(confFiles.length, 1, '===')) {
config = merge(initialConf, parser(first(confFiles)));
} else {
config = initialConf;
}
return config;
};
defaultConfig.parsers = parsers;
module.exports = defaultConfig;
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
function deepEq$(x, y, type){
var toString = {}.toString, hasOwnProperty = {}.hasOwnProperty,
has = function (obj, key) { return hasOwnProperty.call(obj, key); };
var first = true;
return eq(x, y, []);
function eq(a, b, stack) {
var className, length, size, result, alength, blength, r, key, ref, sizeB;
if (a == null || b == null) { return a === b; }
if (a.__placeholder__ || b.__placeholder__) { return true; }
if (a === b) { return a !== 0 || 1 / a == 1 / b; }
className = toString.call(a);
if (toString.call(b) != className) { return false; }
switch (className) {
case '[object String]': return a == String(b);
case '[object Number]':
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
case '[object Date]':
case '[object Boolean]':
return +a == +b;
case '[object RegExp]':
return a.source == b.source &&
a.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
}
if (typeof a != 'object' || typeof b != 'object') { return false; }
length = stack.length;
while (length--) { if (stack[length] == a) { return true; } }
stack.push(a);
size = 0;
result = true;
if (className == '[object Array]') {
alength = a.length;
blength = b.length;
if (first) {
switch (type) {
case '===': result = alength === blength; break;
case '<==': result = alength <= blength; break;
case '<<=': result = alength < blength; break;
}
size = alength;
first = false;
} else {
result = alength === blength;
size = alength;
}
if (result) {
while (size--) {
if (!(result = size in a == size in b && eq(a[size], b[size], stack))){ break; }
}
}
} else {
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
return false;
}
for (key in a) {
if (has(a, key)) {
size++;
if (!(result = has(b, key) && eq(a[key], b[key], stack))) { break; }
}
}
if (result) {
sizeB = 0;
for (key in b) {
if (has(b, key)) { ++sizeB; }
}
if (first) {
if (type === '<<=') {
result = size < sizeB;
} else if (type === '<==') {
result = size <= sizeB
} else {
result = size === sizeB;
}
} else {
first = false;
result = size === sizeB;
}
}
}
stack.pop();
return result;
}
}
}).call(this);
10 changes: 10 additions & 0 deletions lib/get-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(function(){
var rc, defaultConfig, deepExtend;
rc = require('rc');
defaultConfig = require('./default-config');
deepExtend = require('deep-extend');
module.exports = function(opts){
opts == null && (opts = {});
return rc('arch', deepExtend(defaultConfig, opts));
};
}).call(this);
2 changes: 1 addition & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
global.React = require('react/addons');
path = require('path');
dom = require('./dom');
serverRendering = require('./server-rendering');
serverRendering = require('./server/server-rendering');
createComponent = function(spec){
return dom(React.createClass(spec));
};
Expand Down
15 changes: 15 additions & 0 deletions lib/paths.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
(function(){
var path, paths;
path = require('path');
paths = {
app: {
abs: path.resolve('.'),
rel: path.relative(__dirname, path.resolve('.'))
},
arch: {
abs: path.dirname(require.resolve("../package.json")),
rel: path.relative(path.resolve('.'), path.dirname(require.resolve("../package.json")))
}
};
module.exports = paths;
}).call(this);
4 changes: 2 additions & 2 deletions lib/server/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
stringifyState = exports.stringifyState;
bundlePath = options.environment === 'development'
? "http://localhost:3001/app.js"
: "/" + options.paths['public'] + "/app.js";
: "/" + options['public'] + "/app.js";
archBody = __template({
'public': options.paths['public'],
'public': options['public'],
bundle: bundlePath,
body: body,
state: stringifyState(appState)
Expand Down
Loading