Skip to content

Instantly share code, notes, and snippets.

@killercup
Created September 14, 2014 12:28
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save killercup/73d7f9d59a8706ee234d to your computer and use it in GitHub Desktop.
Save killercup/73d7f9d59a8706ee234d to your computer and use it in GitHub Desktop.
A Gulp config for compiling CoffeeScript and Less using Webpack with a custom vendor.js and Hot Module Replacement for Less and React.js

My React Frontend Build Script

This is a Gulp config for compiling CoffeeScript and Less using Webpack with a custom vendor.js and Hot Module Replacement for Less and React.js classes.

Also, this does not require any globally installed npm modules and can be run using npm run watch or npm run compile.

You can add configure some build parameters using the constants ENV and PATHS.

# # Frontend Build Process
path = require('path')
gulp = require('gulp')
gutil = require('gulp-util')
plumber = require('gulp-plumber')
webpack = require("webpack")
# ## CONSTS
PATHS =
app:
src: './src/'
entry: './src/index.coffee'
dest: path.resolve './build'
styleguide:
src: './src/'
entry: './src/styleguide.coffee'
dest: './build'
libs:
entry: './src/vendor.js'
name: 'vendor.js'
dest: './build'
LIBS = require(PATHS.libs.entry)
ENTRIES =
app: "#{PATHS.app.entry}"
styleguide: "#{PATHS.styleguide.entry}"
vendor: LIBS
# ## Helpers
process.env.NODE_ENV or= 'development'
is_production = process.env.NODE_ENV is 'production'
is_development = process.env.NODE_ENV is 'development'
ENV =
name: process.env.NODE_ENV
compress: is_production
watch: is_development
debug: is_development
debug_stats: true
bundleCSS: is_production
dev_server: is_development
dev_port: 3000
log = (task, level) ->
return (_msg) ->
if level is 'err'
msg = gutil.colors.red(_msg)
else
msg = _msg
gutil.log(gutil.colors.cyan("[#{task}]"), msg)
# ## Processes
compile = ({env, entries}) ->
config =
entry: entries
output:
filename: "[name].js"
path: PATHS.app.dest
devtool: 'source-map'
module:
loaders: [
{ test: /\.coffee$/, loader: "react-hot!coffee-loader" }
]
resolve:
extensions: ['', '.js', '.coffee', '.css', '.less']
plugins: [
new webpack.DefinePlugin
"process.env":
NODE_ENV: JSON.stringify(env.name or "development")
new webpack.optimize.CommonsChunkPlugin('vendor', PATHS.libs.name, Infinity)
]
if env.bundleCSS
ExtractTextPlugin = require("extract-text-webpack-plugin")
config.module.loaders.push
test: /\.(less|css)$/
loader: ExtractTextPlugin.extract('css-loader!autoprefixer-loader!less-loader')
config.plugins.push new ExtractTextPlugin("app.css", allChunks: true)
else
config.module.loaders.push
test: /\.(less|css)$/
loader: 'style-loader!css-loader!autoprefixer-loader!less-loader'
if env.compress
config.plugins = config.plugins.concat [
# new webpack.optimize.DedupePlugin()
new webpack.optimize.OccurenceOrderPlugin(true)
# new webpack.optimize.AggressiveMergingPlugin(moveToParents: true)
new webpack.optimize.UglifyJsPlugin()
]
if env.dev_server
config.plugins.push new webpack.HotModuleReplacementPlugin()
config.entry.hot = [
"webpack-dev-server/client?http://localhost:#{env.dev_port}"
"webpack/hot/dev-server"
]
return webpack(config)
compileStuff = ({env, entries, watch}, callback) ->
notify = log('webpack', 'info')
compiler = compile({env, entries})
STATS_SETTINGS =
chunks: false
colors: true
warnings: false
children: false
cb = (err, stats) ->
notify stats.toString STATS_SETTINGS
if env.debug_stats
json_stats = JSON.stringify stats.toJson(), null, 2
require('fs').writeFileSync('webpack-stats.json', json_stats)
throw new gutil.PluginError("webpack", err) if err
callback() unless watch
if watch
if env.dev_server
DevServer = require("webpack-dev-server")
server = new DevServer compiler,
contentBase: PATHS.app.dest
hot: true
watchDelay: 100
stats: STATS_SETTINGS
server.listen env.dev_port, ->
notify "Dev server started on http://localhost:#{env.dev_port}/"
else
compiler.watch 200, cb
else
compiler.run cb
# ## Tasks
gulp.task 'clean', ->
gulp.src("#{PATHS.app.dest}/**/*", read: false)
.pipe require('gulp-rimraf')()
gulp.task 'copy:assets', ->
gulp.src("#{PATHS.app.src}/**/*.html")
.pipe gulp.dest PATHS.app.dest
gulp.task 'copy:assets:watch', ['copy:assets'], ->
gulp.watch("#{PATHS.app.src}/**/*.html", ['copy:assets'])
gulp.task 'magic:compile', (callback) ->
compileStuff {
env: ENV
entries: ENTRIES
}, callback
gulp.task 'magic:watch', (callback) ->
compileStuff {
env: ENV
entries: ENTRIES
watch: true
}, callback
gulp.task 'gzip', ->
gulp.src("#{PATHS.app.dest}/*.{js,html,css}")
.pipe require('gulp-gzip')(gzipOptions: { level: 9 })
.pipe gulp.dest(PATHS.app.dest)
gulp.task 'default', (cb) ->
require('run-sequence')('clean',
['copy:assets', 'magic:compile']
'gzip'
cb
)
gulp.task 'watch', (cb) ->
require('run-sequence')('clean',
['copy:assets:watch', 'magic:watch']
cb
)
{
"name": "react-ef",
"version": "0.0.0",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "gulp --require coffee-script/register",
"compile": "NODE_ENV=production gulp --require coffee-script/register",
"watch": "gulp watch --require coffee-script/register"
},
"author": "Pascal Hertleif <killercup@gmail.com> (http://pascalhertleif.de/)",
"license": "MIT",
"dependencies": {
"lodash": "^2.4.1",
"react": "^0.11.0",
"react-prop-schema": "^0.2.0"
},
"devDependencies": {
"autoprefixer-loader": "^1.0.0",
"coffee-loader": "^0.7.2",
"coffee-script": "^1.8.0",
"css-loader": "^0.8.0",
"extract-text-webpack-plugin": "0.3.0",
"file-loader": "^0.7.2",
"gulp": "^3.8.8",
"gulp-coffee": "^2.2.0",
"gulp-gzip": "0.0.8",
"gulp-plumber": "^0.6.5",
"gulp-rimraf": "^0.1.0",
"gulp-util": "^2.2.19",
"less": "^1.7.5",
"less-loader": "^0.7.7",
"normalize.css": "^3.0.1",
"react-hot-loader": "^0.4.3",
"run-sequence": "^0.3.6",
"style-loader": "^0.8.0",
"webpack": "^1.4.0-beta4",
"webpack-dev-server": "^1.6.4"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment