Skip to content

Commit

Permalink
added support for sass/scss (#1); moved public/src/js to public/src/s…
Browse files Browse the repository at this point in the history
…cripts; added bootstrap (#3); add watching to styles and assets and index.html;
  • Loading branch information
bericp1 committed Dec 26, 2014
1 parent 21fea98 commit c5f8fbf
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 28 deletions.
41 changes: 28 additions & 13 deletions README.md
Expand Up @@ -8,12 +8,13 @@ A simple, opinionated project boilerplate/seed.

| Library | Purpose |
| ------------------------------------------------------- | ------------------------------------- |
| [React](http://facebook.github.io/react/) | View-controller layer |
| [React](http://facebook.github.io/react/) | View-controller layer |
| [Reflux](https://github.com/spoike/refluxjs) | Uni-directional dataflow architecture |
| [react-router](https://github.com/rackt/react-router/) | Declarative routing |
| [browserify](http://browserify.org/) | CommonJS module system |
| [es5-shim](https://github.com/es-shims/es5-shim) | Support for non-ES5 clients |
| [jquery](http://jquery.com/) | For its utility methods (I'm *sorry*) |
| sass/scss | A CSS preprocessor |

### Back-end

Expand All @@ -30,6 +31,8 @@ A simple, opinionated project boilerplate/seed.
| [gulp-uglify](https://www.npmjs.com/package/gulp-uglify) | [Production] uglify js source |
| [gulp-util](https://github.com/gulpjs/gulp-util) | Logging in gulp, etc. |
| [gulp-concat](https://github.com/wearefractal/gulp-concat) | Concat'ing vendor scripts |
| [gulp-sass](https://www.npmjs.com/package/gulp-sass) | For processing sass/scss into css |
| [gulp-cssmin](https://www.npmjs.com/package/gulp-cssmin) | [Production] minify css |
| [browserify](http://browserify.org/) | Bundling front-end CommonJS modules |
| vinyl-source-stream | Make Browserify usable with gulp |
| [reactify](https://github.com/andreypopp/reactify/) | A React/JSX transform for browserify |
Expand All @@ -39,31 +42,41 @@ A simple, opinionated project boilerplate/seed.

### `$ gulp browserify`

Bundles `public/src/app.js` with browserify and places it in
Bundles `public/src/scripts/app.js` with browserify and places it in
`public/dist/app.js`.

### `$ gulp sass`

Processes `public/src/styles/app.scss` into CSS and places it in
`public/dist/app.css`. This means that all styles will be compiled into one
file (minified in production) and must be `@import`ed somewhere down the line
starting form `app.scss`. **Partials (`_*.scss`) are your friends.**

### `$ gulp serve` or `$ gulp dev`

1. runs `['vendor', 'copy']`
2. bundles `public/src/app.js` with browserify to `public/dist/app.js`
1. runs `['vendor', 'copy', 'sass']`
2. bundles `public/src/scripts/app.js` with browserify to `public/dist/app.js`
3. starts the server (`server.js`)
4. fires up watchify which will rebundle on changes to any bundled files.
Watchify uses a caching system to make this a comparatively efficient
operation.
5. watches for changes to `public/src/styles/**/*.*` and runs `sass` task
6. watches for changes to static files (`public/src/{index.html,assets/}`)
and runs `copy` task

### `$ gulp vendor`

Concats all vendor scripts specified in `config.build[NODE_ENV].vendor` into
Concats all vendor scripts specified in `config.build.vendor.js` into
`public/dist/vendor.js`

### `$ gulp copy`

Copies `public/{index.html,assets}` recursively to `public/dist` as is.
Copies `public/src/{index.html,assets}` recursively to `public/dist` as is.

### `$ gulp build`

Should be used for building front end into public/dist where the server will
serve from. Alias for `['copy', 'browserify']`.
serve from. Alias for `['copy', 'browserify', 'sass']`.

## Structure/Architecture

Expand All @@ -76,7 +89,9 @@ serve from. Alias for `['copy', 'browserify']`.
│  └─ src : front-end code
│  ├─ assets : static files; no build processing
│  ├─ index.html : app entry; usually no need to edit
│ └─ js : all CommonJS modules for front-end
│ ├─ styles : all sass/scss styles for the frontend
| | └─app.scss : entry for styles; use @import here
│ └─ scripts : all CommonJS modules for front-end
│  ├─ app.js : entry; exports root view-controller
│  └─ [app-component] : a component of the app
│    ├─ index.js : entry point; exports view-controller
Expand All @@ -93,17 +108,17 @@ view-controllers, all tied together with `Reflux`, a library-backed
app architecture that relies on uni-directional data-flow and convention over
configuration.

The entry point for the front end (`public/src/app.js`) should...
The entry point for the front end (`public/src/scripts/app.js`) should...

- Build and render the root `Application` React view-controller
- `require` each app component from their subdirs
- describe the `react-router` routes
- render the base application

See the example: [app.js](public/src/js/app.js).
See the example: [app.js](public/src/scripts/app.js).

Each app component should...
- be separated into its own subdir within `public/src/js/`
- be separated into its own subdir within `public/src/scripts/`
- be designated/named by the purpose it serves
- have its own Reflux actions/stores and React view-controller(s)
- React view-controllers can live in separate `*.jsx` files or be rendered
Expand All @@ -112,8 +127,8 @@ Each app component should...
- and actions in `*-actions.js` or simply `actions.js`
- export via `module.exports` in its `index.js` its root React view-controller

See either example: [react-example](public/src/js/react-example) or
[reflux-example](public/src/js/reflux-example)
See either example: [react-example](public/src/scripts/react-example) or
[reflux-example](public/src/scripts/reflux-example)

### Back-end

Expand Down
32 changes: 23 additions & 9 deletions config.js
@@ -1,7 +1,15 @@
module.exports = {
build: {
// Will be concated and included in index.html before app bundle
vendor: []
vendor: {
// Will be concated and included in index.html before app bundle.
js: [],
// Will be included as an includePath for @import statements
scss: [
// Bootstrap is included by default and can be used with
// `@import "bootstrap"`
'./node_modules/bootstrap-sass/assets/stylesheets'
]
}
},
server: {
// Port to run on. Overridden by PORT env variable or port passed as an
Expand All @@ -11,19 +19,25 @@ module.exports = {
// Merges into config if NODE_ENV is development
development: {
build: {
vendor: [
'./node_modules/es5-shim/es5-shim.js',
'./node_modules/jquery/dist/jquery.js'
]
vendor: {
js: [
'./node_modules/es5-shim/es5-shim.js',
'./node_modules/jquery/dist/jquery.js',
'./node_modules/bootstrap/dist/js/bootstrap.js'
]
}
}
},
// Merges into config if NODE_ENV is production
production: {
build: {
vendor: [
vendor: {
js: [
'./node_modules/es5-shim/es5-shim.min.js',
'./node_modules/jquery/dist/jquery.min.js'
]
'./node_modules/jquery/dist/jquery.min.js',
'./node_modules/bootstrap/dist/js/bootstrap.min.js'
]
}
}
}
};
39 changes: 33 additions & 6 deletions gulpfile.js
Expand Up @@ -3,6 +3,8 @@ var gulp = require('gulp'),
gutil = require('gulp-util'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
sass = require('gulp-sass'),
cssmin = require('gulp-cssmin'),

// For Browserify compat
buffer = require('vinyl-buffer'),
Expand All @@ -27,9 +29,9 @@ config = moulder(config, environment).build;
// Concat vendor scripts (described in config)
gulp.task('vendor', function(){

if(config.vendor.length === 0) return;
if(config.vendor.js.length === 0) return;

return gulp.src(config.vendor)
return gulp.src(config.vendor.js)
.pipe(concat('vendor.js'))
.pipe(gulp.dest('./public/dist'));

Expand All @@ -42,7 +44,7 @@ var bundler = browserify({
});

// Add the entry module to the bundler
bundler.add('./public/src/js/app.js');
bundler.add('./public/src/scripts/app.js');

// Actually use bundler to perform bundling
// Can be called indefinitely throughout bulid
Expand All @@ -66,16 +68,41 @@ gulp.task('browserify', ['vendor'], function(){

});

// Task to compile scss to css
gulp.task('sass', function(){
var pipeline = gulp.src('./public/src/styles/app.scss')
.pipe(sass({
includePaths: config.vendor.scss || []
}))
.on('error', function(err){
gutil.log('Error in sass build:');
gutil.log(err);
});

if(environment === 'production')
pipeline.pipe(cssmin());

return pipeline.pipe(gulp.dest('./public/dist'));
});

// Wraps bundler with watchify to watch changes to bundled
// files and rebundles as necessary. Also starts `server.js`.
gulp.task('serve', ['vendor', 'copy'], function(){
// files, watches sass scripts, watches statics to copy and
// starts `server.js`.
gulp.task('serve', ['vendor', 'copy', 'sass'], function(){

bundler = watchify(bundler);
bundler.on('update', function(){
bundle(bundler);
gutil.log('Rebundling...');
});

gulp.watch('./public/src/styles/**/*.*', ['sass']);

gulp.watch(
['./public/src/index.html', './public/src/assets/**/*.*'],
['copy']
);

require('./server')({logger:gutil.log});

return bundle(bundler);
Expand All @@ -97,5 +124,5 @@ gulp.task('copy', function(){
});

// For deployment. Makes front-end ready to serve from `public/dist`
gulp.task('build', ['copy', 'browserify']);
gulp.task('build', ['copy', 'browserify', 'sass']);
gulp.task('default', ['build']);
4 changes: 4 additions & 0 deletions package.json
Expand Up @@ -10,12 +10,16 @@
"license": "MIT",
"dependencies": {
"body-parser": "^1.10.0",
"bootstrap": "^3.3.1",
"bootstrap-sass": "^3.3.1",
"browserify": "^7.0.3",
"es5-shim": "^4.0.5",
"express": "^4.10.6",
"extend": "^2.0.0",
"gulp": "^3.8.10",
"gulp-concat": "^2.4.2",
"gulp-cssmin": "^0.1.6",
"gulp-sass": "^1.2.4",
"gulp-uglify": "^1.0.2",
"gulp-util": "^3.0.1",
"jquery": "^2.1.3",
Expand Down
1 change: 1 addition & 0 deletions public/src/index.html
Expand Up @@ -2,6 +2,7 @@
<html>
<head>
<title>Web App</title>
<link type="text/css" rel="stylesheet" href="app.css">
</head>
<body>
<div id="app-root"></div>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions public/src/styles/app.scss
@@ -0,0 +1 @@
@import 'bootstrap';

0 comments on commit c5f8fbf

Please sign in to comment.