Created
January 15, 2015 20:42
-
-
Save lettertwo/e35b7a57151b65a80c1d to your computer and use it in GitHub Desktop.
Example of Webpack config for building an isomorphic JS app for both client and server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
path = require 'path' | |
webpack = require 'webpack' | |
fs = require 'fs' | |
ExtractTextPlugin = require 'extract-text-webpack-plugin' | |
ProgressPlugin = require 'webpack/lib/ProgressPlugin' | |
flag = require 'node-env-flag' | |
settings = require './src/settings' | |
scriptExportsLoader = path.join __dirname, 'script-exports-loader' | |
getEnv = (varName, required = false) -> | |
process.env[varName] ? if required | |
throw new Error "Missing required env var #{ varName }" | |
createConfig = (buildId, isDev, isServer, progressCallback) -> | |
throw new Error 'Missing build id!' unless buildId | |
publicPath = | |
if flag process.env.COMPILE_USING_CDN_URL, not isDev | |
"#{ settings.cdnUrl }/#{ settings.assetDirVersion }/" | |
else | |
'/assets/' | |
fileLoader = 'file?name=[path][name].[hash].[ext]&context=src' | |
cache: true | |
bail: not isDev | |
debug: isDev | |
isDev: isDev | |
target: if isServer then 'node' else 'web' | |
# We don't build source maps by default because they are very expensive. | |
# For example, a *rebuild* (from cache) takes ~10s with source maps, | |
# but only ~2s without. | |
devtool: if not isDev and isServer then 'source-map' | |
recordsPath: path.join __dirname, '.webpackrecords' | |
entry: | |
if isServer | |
server: ['./src/server'] | |
else | |
cbbootstrap: './src/componentbrowser/cbbootstrap' | |
rcmain: './src/rcmain' | |
node: if isServer | |
# Don't mock node stuff for the node build | |
console: false | |
process: false | |
global: false | |
buffer: false | |
__filename: false | |
__dirname: false | |
output: | |
path: path.join __dirname, 'built', 'assets' | |
publicPath: publicPath | |
filename: if isServer then '../[name].js' else "[name].#{ buildId }.js" | |
chunkFilename: if isServer then '[id].js' else '[chunkhash].js' | |
libraryTarget: if isServer then 'commonjs2' | |
# Exclude all modules in the "node_modules" directory for the server build | |
externals: if isServer then do -> | |
fs.readdirSync path.resolve('node_modules') | |
.filter (dir) -> | |
# There are exceptions that we actually do want in the build... | |
[ | |
/^gsap-react-plugin(?:$|\/)/ | |
/^react-forms(?:$|\/)/ | |
].every (exclude) -> not exclude.test dir | |
.map (dir) -> ///^#{ dir }(?:$|\/)/// | |
module: | |
loaders: [ | |
{test: /\/component-index\.js$/, loader: "component-example?includeExamples=#{ isDev }"} | |
{test: /\/console-polyfill\/.*\.js$/, loader: 'imports?this=>window'} | |
{test: /\/react\/react\.js$/, loader: 'expose?React'} # Expose React so devtools can find it | |
{test: /\/bower_components\/jquery.parallaxin\/jquery.parallaxin\.js$/, loader: 'imports?$=jquery&jQuery=jquery&this=>window'} | |
{test: /\/queueup\.js$/, loader: 'imports?Promise=es6-promise'} | |
# GreenSock Deps | |
{test: /\/vendor\/greensock\/TweenLite\.js$/, loader: "#{ scriptExportsLoader }?com.greensock.TweenLite"} | |
{test: /\/vendor\/greensock\/TimelineLite\.js$/, loader: "imports?TweenLite=greensock/TweenLite!#{ scriptExportsLoader }?com.greensock.TimelineLite"} | |
{test: /\/vendor\/greensock\/easing\/EasePack\.js$/, loader: "imports?TweenLite=greensock/TweenLite!#{ scriptExportsLoader }?com.greensock.easing"} | |
{test: /\/vendor\/greensock\/plugins\/CSSPlugin\.js$/, loader: 'imports?TweenLite=greensock/TweenLite'} | |
{test: /\/gsap-react-plugin\/gsap-react-plugin\.js$/, loader: "imports?TweenLite=greensock/TweenLite!#{ scriptExportsLoader }"} | |
{test: /\/bower_components\/raven-js\/dist\/raven\.js$/, loader: 'imports?this=>window'} | |
{test: /\.coffee$/, loader: 'coffee'} | |
{test: /\.litcoffee$/, loader: 'coffee?literate'} | |
{test: /\.(?:svg|ico|eot|ttf|woff|pdf)$/, loader: fileLoader} | |
{ | |
test: /\.(?:jpg|jpeg|png|gif)$/ | |
loaders: ['image-webpack?progressive=true&interlaced=true', fileLoader] | |
} | |
{test: /\.json$/, loader: 'json'} | |
{test: /\/node_modules\/react-forms\/.*\.js$/, loader: 'jsx-loader?harmony'} | |
{ | |
test: /\.less$/ | |
loader: | |
if isServer then 'null' | |
else do -> | |
browsers = ['last 2 versions', 'Explorer >= 9'] | |
ExtractTextPlugin.extract "css!autoprefixer?#{ JSON.stringify {browsers} }!less" | |
} | |
] | |
resolveLoader: | |
root: [ | |
path.join __dirname, 'src', 'componentbrowser', 'node_loaders' | |
] | |
extensions: ['', '.js', '.coffee'] | |
resolve: | |
root: [ | |
path.join __dirname, 'bower_components' | |
path.join __dirname, 'vendor' | |
] | |
alias: | |
'jquery.parallaxin': 'jquery.parallaxin/jquery.parallaxin' | |
'es6-promise': 'es6-promise/dist/promise-1.0.0.js' | |
raven: 'raven-js/dist/raven' | |
'TweenLite': 'greensock/TweenLite' | |
extensions: ['', '.litcoffee', '.coffee', '.json', '.js'] | |
plugins: do -> | |
plugins = [] | |
# Show progress of the build | |
if progressCallback | |
plugins.push new ProgressPlugin (pct, msg) -> progressCallback pct, msg | |
plugins.push new webpack.NewWatchingPlugin() | |
plugins.push new webpack.PrefetchPlugin 'react' | |
# Export stats for webpack analyse tool (off by default) | |
# http://webpack.github.io/analyse/ | |
# unless isServer then plugins.push -> | |
# @plugin 'done', (stats) -> | |
# fs.writeFileSync path.join(__dirname, 'built', 'stats.json'), | |
# JSON.stringify stats.toJson | |
# chunkModules: true | |
# Exclude moment.js languages. | |
plugins.push new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) | |
# Find bower components | |
plugins.push new webpack.ResolverPlugin([ | |
new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin('bower.json', ['main']) | |
], ['normal', 'loader']) | |
unless isServer | |
plugins.push new ExtractTextPlugin "[name].#{ buildId }.css" | |
# FIXME: Add this back! It gets rid of lodash duplication. Unfortunately, | |
# the code it adds errors in builds created by watch-mode after the | |
# first build. See https://github.com/webpack/webpack/issues/583 | |
# plugins.push new webpack.optimize.DedupePlugin | |
plugins.push new webpack.optimize.OccurenceOrderPlugin true | |
# Put libraries into production mode. Note that you must *also* set the | |
# `NODE_ENV` environment variable on the server since we're not including | |
# everything in the build. | |
plugins.push new webpack.DefinePlugin | |
'process.env.NODE_ENV': | |
JSON.stringify if isDev then 'development' else 'production' | |
'process.env.RC_API_URL': JSON.stringify getEnv('RC_API_URL') or | |
'//www.rockefellercenter.com/api/v2/' | |
'process.env.SENTRY_BROWSER_DSN': | |
JSON.stringify getEnv 'SENTRY_BROWSER_DSN', not isDev | |
'process.env.COMPILE_USING_CDN_URL': process.env.COMPILE_USING_CDN_URL | |
__ASSET_PATH__: JSON.stringify publicPath | |
__BUILD_ID__: JSON.stringify buildId | |
__BUILD_TIME__: JSON.stringify new Date().toISOString() | |
__BUILD_USER__: JSON.stringify process.env.USER ? 'unknown' | |
unless isDev or isServer | |
plugins.push new webpack.optimize.UglifyJsPlugin() | |
plugins | |
module.exports = (buildId, isDev, serverCallback, browserCallback) -> | |
[ | |
createConfig buildId, isDev, true, serverCallback | |
createConfig buildId, isDev, false, browserCallback | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How fast did this run?
(I'm looking to optimize my Webpack config)