Skip to content

Instantly share code, notes, and snippets.

@jonvuri
Created March 26, 2017 03:00
Show Gist options
  • Save jonvuri/7bb3d526d87a19e121cda5d1749be9fe to your computer and use it in GitHub Desktop.
Save jonvuri/7bb3d526d87a19e121cda5d1749be9fe to your computer and use it in GitHub Desktop.
/* eslint-env node */
// Node
const fs = require( 'fs' )
const path = require( 'path' )
// Webpack
const webpack = require( 'webpack' )
const CaseSensitivePathsPlugin = require( 'case-sensitive-paths-webpack-plugin' )
const ExtractTextPlugin = require( 'extract-text-webpack-plugin' )
const FaviconsWebpackPlugin = require( 'favicons-webpack-plugin' )
const HtmlWebpackPlugin = require( 'html-webpack-plugin' )
// Helpers
const merge = require( 'webpack-merge' ).smartStrategy( { entry: 'prepend' } )
const jsYaml = require( 'js-yaml' )
const TARGET = process.env.npm_lifecycle_event
// Default config, overridden by any values in a config.yaml in the same directory
const config = {
devServerPort: 3002,
apiUrl: 'http://staging-api/'
}
// eslint-disable-next-line no-restricted-syntax
try {
Object.assign( config, jsYaml.load( fs.readFileSync( 'config.yaml', 'utf8' ) ) )
} catch ( error ) {
// Ignore
}
const PATHS = {
src: path.join( __dirname, 'src' ),
dev: path.join( __dirname, 'dev' ),
dist: path.join( __dirname, 'dist' )
}
const cssIdent = '[path]___[name]__[local]___[hash:base64:5]'
const common = {
entry: [
'babel-polyfill',
'./src/index.jsx'
],
output: {
// Used by plugins to generate URLs (i.e. to fix routing)
publicPath: '/',
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx?$/i,
exclude: /node_modules/,
include: PATHS.src,
use: [
{
loader: 'babel-loader'
}
]
},
{
test: /\.(jpe?g|png|gif|woff)$/i,
use: [
{
loader: 'file-loader',
options: {
hash: 'sha512',
digest: 'hex',
name: '[hash].[ext]'
}
}
]
},
{
test: /\.svg$/i,
use: [
{
loader: 'babel-loader'
},
{
loader: 'react-svg-loader'
}
]
}
]
},
resolve: {
extensions: [ '.js', '.jsx' ],
modules: [ path.resolve( './src' ), 'node_modules' ]
},
plugins: [
new CaseSensitivePathsPlugin(),
new FaviconsWebpackPlugin( './src/favicon.png' ),
new HtmlWebpackPlugin( {
template: path.join( PATHS.src, 'index.html' ),
hash: true,
inject: 'body'
} )
]
}
const dev = merge( common, {
devtool: 'eval-source-map',
entry: [
'react-hot-loader/patch',
`webpack-dev-server/client?http://localhost:${ config.devServerPort }`,
'webpack/hot/only-dev-server'
],
output: {
path: PATHS.dev
},
module: {
rules: [
{
test: /\.sss$/i,
use: [
{
loader: 'style-loader',
options: {
sourceMap: true
}
},
{
loader: 'css-loader',
options: {
sourceMap: true,
modules: true,
importLoaders: 1,
localIdentName: cssIdent
}
},
{
loader: 'postcss-loader'
}
]
},
{
test: /\.css$/i,
use: [
{
loader: 'style-loader',
options: {
sourceMap: true
}
},
{
loader: 'css-loader',
options: {
sourceMap: true,
localIdentName: cssIdent
}
}
]
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin()
],
devServer: {
port: config.devServerPort,
hot: true,
historyApiFallback: true,
stats: 'errors-only',
contentBase: PATHS.dev,
publicPath: '/'
}
} )
const prod = merge( common, {
bail: true,
output: {
path: PATHS.dist
},
module: {
rules: [
{
test: /\.sss$/i,
use: ExtractTextPlugin.extract( {
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: cssIdent,
importLoaders: 1
}
},
{
loader: 'postcss-loader',
}
]
} )
},
{
test: /\.css$/i,
loader: ExtractTextPlugin.extract( {
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
localIdentName: cssIdent
}
}
]
} )
}
]
},
plugins: [
// Tell Webpack and React to use production mode
new webpack.DefinePlugin( {
'process.env': {
NODE_ENV: JSON.stringify( 'production' )
}
} ),
// Plugin docs: https://webpack.github.io/docs/list-of-plugins.html
new webpack.optimize.UglifyJsPlugin( {
sourceMap: true
} ),
new ExtractTextPlugin( {
filename: 'bundle.css',
disable: false,
allChunks: true
} )
]
} )
if ( TARGET === 'build:webpack' ) {
module.exports = prod
} else if ( TARGET === 'start' ) {
module.exports = dev
} else {
throw new Error( 'Webpack called with invalid build target' )
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment