Skip to content

Instantly share code, notes, and snippets.

@bartekus
Last active January 8, 2017 19:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bartekus/b0040ebcce78eeaba87b1a45b943dea1 to your computer and use it in GitHub Desktop.
Save bartekus/b0040ebcce78eeaba87b1a45b943dea1 to your computer and use it in GitHub Desktop.
Webpack-Config + Webpack Validation
'use strict'; // eslint-disable-line strict
/* eslint no-unused-vars: 0 */
const fs = require('fs');
const { resolve } = require('path');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const WebpackToolsPlugin = require('webpack-isomorphic-tools/plugin');
const webpackToolsConfig = require('./webpack.isomorphic.tools');
const Config = require('webpack-config').Config;
const webpackConfig = new Config();
const appConfig = require('../index');
const debug = require('debug');
debug.enable('wh3rk:*');
const log = debug('wh3rk:boot');
// Globals
const NODE_ENV = process.env.NODE_ENV || 'development';
global.__DEV__ = NODE_ENV !== 'production';
global.__PROD__ = NODE_ENV === 'production';
global.__DEBUG__ = __DEV__;
global.__SERVER__ = true;
global.__CLIENT__ = false;
/* Base Webpack Config */
log('Creating webpack configuration...');
module.exports = webpackConfig.merge({
context: appConfig.paths.app,
entry: {
app: appConfig.paths.entryFile,
vendor: appConfig.webpack.entry.vendor,
},
output: {
path: appConfig.paths.dist,
publicPath: appConfig.webpack.output.publicPath,
},
resolve: {
extensions: appConfig.webpack.resolve.extensions,
root: appConfig.paths.root,
modulesDirectories: [
appConfig.paths.modules,
appConfig.paths.app,
],
fallback: appConfig.paths.modules,
alias: {
react: fs.realpathSync(resolve(appConfig.paths.modules, 'react')), // force components to always use this local copy
},
},
externals: {
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true,
'ws': true,
},
node: {
fs: 'empty',
net: 'empty',
tls: 'empty',
dns: 'empty',
},
resolveLoader: {
fallback: appConfig.paths.modules,
},
module: {
noParse: ['ws'],
loaders: [
{
test: /\.json$/,
loader: 'json',
},
{
test: /\.woff(\?.*)?$/,
loader: 'url?' +
'prefix=fonts/&' +
'name=[path][name].[ext]&' +
'limit=10000&' +
'mimetype=application/font-woff',
},
{
test: /\.woff2(\?.*)?$/,
loader: 'url?' +
'prefix=fonts/&' +
'name=[path][name].[ext]&' +
'limit=10000&' +
'mimetype=application/font-woff2',
},
{
test: /\.ttf(\?.*)?$/,
loader: 'url?' +
'prefix=fonts/&' +
'name=[path][name].[ext]&' +
'limit=10000&' +
'mimetype=application/octet-stream',
},
{
test: /\.eot(\?.*)?$/,
loader: 'file?' +
'prefix=fonts/&' +
'name=[path][name].[ext]',
},
{
test: /\.svg(\?.*)?$/,
loader: 'url?' +
'prefix=fonts/&' +
'name=[path][name].[ext]&' +
'limit=10000&' +
'mimetype=image/svg+xml',
},
{
test: /\.(ico)|(jpg)|(png)|(jpeg)|(gif)$/,
loaders: [
'file-loader',
'image-webpack?' +
'optimizationLevel=7&' +
'interlaced=false',
],
},
],
},
postcss: [
cssnano({
sourcemap: true,
autoprefixer: {
add: true,
remove: true,
browsers: ['last 2 versions'],
},
safe: true,
discardComments: {
removeAll: true,
},
}),
],
/*
postcss: [
autoprefixer({
add: true,
remove: true,
browsers: ['last 2 versions'],
}),
],
*/
eslint: {
configFile: resolve(appConfig.paths.root, '.eslintrc.js'),
},
plugins: [
new webpack.DefinePlugin({
__DEV__,
__PROD__,
__SERVER__,
__CLIENT__,
__DEBUG__,
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
template: resolve(appConfig.paths.static, 'index.html'),
hash: true,
favicon: resolve(appConfig.paths.static, 'favicon.ico'),
filename: 'index.html',
inject: 'body',
minify: {
collapseWhitespace: true,
},
appMountId: appConfig.project.appMountId,
// chunksSortMode: 'dependency',
// window: {
// env: {
// apiHost: 'http://myapi.com/api/v1'
// }
// },
title: appConfig.project.name,
mobile: true,
// googleAnalytics: {
// trackingId: 'UA-XXXX-XX',
// pageViewOnLoad: true
// },
}),
new WebpackToolsPlugin(webpackToolsConfig).development(__DEV__),
],
});
const webpack = require('webpack');
const Config = require('webpack-config').Config;
const webpackConfig = new Config();
const appConfig = require('../index');
const debug = require('debug');
debug.enable('wh3rk:*');
const log = debug('wh3rk:dev');
// Globals
const NODE_ENV = process.env.NODE_ENV || 'development';
global.__DEV__ = NODE_ENV !== 'production';
global.__PROD__ = NODE_ENV === 'production';
global.__DEBUG__ = __DEV__;
global.__SERVER__ = true;
global.__CLIENT__ = false;
log('Extending webpack configuration with development settings: ');
log('Adding HMR entry points');
log('Enable HMR development plugin');
module.exports = webpackConfig.extend('config/webpack/webpack.config.base.js').merge({
devtool: appConfig.webpack.dev.devtool,
entry: {
app: [
'react-hot-loader/patch',
'webpack-hot-middleware/client',
appConfig.paths.entryFile,
],
vendor: appConfig.webpack.vendor,
},
output: {
path: appConfig.paths.dist,
publicPath: appConfig.webpack.output.publicPath,
filename: `[name].[${ appConfig.webpack.dev.hash_type }].js`,
chunkFilename: `[id].[${ appConfig.webpack.dev.hash_type }].js`,
sourceMapFilename: '[file].map',
library: 'App',
libraryTarget: 'umd', // others: var, this, commonjs, commonjs2, amd, umd
},
stats: appConfig.webpack.dev.stats,
module: {
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel',
query: {
presets: ['react', ['es2015', { modules: false }], 'stage-0'],
plugins: ['transform-decorators-legacy', 'react-hot-loader/babel'],
},
include: appConfig.paths.app,
},
//{
// test: /\.(css|scss)$/,
// loaders: [
// 'style',
// 'css?' +
// 'modules&' +
// 'localIdentName=[local]__[hash:base64:4]&' +
// 'importLoaders=1&' +
// 'sourceMap',
// 'postcss',
// 'sass?sourceMap',
// ],
//},
// Any .scss file in ./src/... *except* those in ./src/styles/
// are local css modules. the class names and ids will be changed to:
// [name]-[local]-[hash:base64:5]
{
test: /\.scss$/,
include: /src\/(?!styles).+/,
loaders: [
'style',
'css?modules&sourceMap&importLoaders=1&localIdentName=[name]-[local]-[hash:base64:5]',
'postcss',
'sass',
],
},
// Any .scss files in ./src/styles are treated as normal (not local)
// sass files, and so class names and ids will remain as specified
{
test: /\.scss$/,
include: /src\/styles/,
loader: 'style!css?sourceMap!postcss!sass',
},
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'),
__DEV__,
__PROD__,
__SERVER__,
__CLIENT__,
__DEBUG__,
}),
],
});
'use strict'; // eslint-disable-line strict
const WebpackConfig = require('webpack-config');
const validate = require('webpack-validator');
const Joi = require('webpack-validator').Joi;
const environment = WebpackConfig.environment;
const BaseConfig = new WebpackConfig.Config();
environment.setAll({
env: () => process.env.NODE_ENV,
});
const entryWebpackConfig = BaseConfig.extend('config/webpack/webpack.config.[env].js');
// This joi schema will be `Joi.concat`-ed with the internal schema
const webpackValidatorExtension = Joi.object({
// this would just allow the property and doesn't perform any additional validation
DEPENDENCY_TREE: Joi.any(),
});
module.exports = validate(entryWebpackConfig, { schemaExtension: webpackValidatorExtension });
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpack = require('webpack');
const Config = require('webpack-config').Config;
const webpackConfig = new Config();
const appConfig = require('../index');
const debug = require('debug');
debug.enable('wh3rk:*');
const log = debug('wh3rk:prod');
/* Globals */
const NODE_ENV = process.env.NODE_ENV || 'development';
global.__DEV__ = NODE_ENV !== 'production';
global.__PROD__ = NODE_ENV === 'production';
global.__DEBUG__ = __DEV__;
global.__SERVER__ = true;
global.__CLIENT__ = false;
log('Extending webpack configuration with production settings: ');
log('Applying ExtractTextPlugin to CSS loaders.');
log('Adding ExtractText UglifyJs and Dedupe plugins');
module.exports = webpackConfig.extend('config/webpack/webpack.config.base.js').merge({
devtool: 'source-map',
entry: {
app: [appConfig.paths.entryFile],
vendor: appConfig.webpack.entry.vendor,
},
output: {
path: `${ appConfig.paths.dist }/[${ appConfig.webpack.prod.hash_type }]/`,
publicPath: `/[${ appConfig.webpack.prod.hash_type }]/`,
filename: `[name].[${ appConfig.webpack.prod.hash_type }].js`,
chunkFilename: `[id].[${ appConfig.webpack.prod.hash_type }].js`,
sourceMapFilename: '[file].map',
library: 'App',
libraryTarget: 'umd', // others: var, this, commonjs, commonjs2, amd, umd
},
stats: appConfig.webpack.prod.stats,
bail: true,
cache: true,
module: {
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel',
query: {
presets: ['react', ['es2015', { modules: false }], 'stage-0'],
plugins: ['transform-decorators-legacy'],
},
include: appConfig.paths.app,
},
{
test: /\.(css|scss)$/,
loader: ExtractTextPlugin.extract(
{ fallbackLoader: 'style-loader',
loader: 'css?' +
'modules&' +
'localIdentName=[hash:base64:4]&' +
'importLoaders=1&' +
'sourceMap?' +
'postcss?' +
'sass?' +
'sourceMap',
}
),
},
],
},
plugins: [
new ExtractTextPlugin('app.[contenthash:20].css'),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
unused: true,
dead_code: true,
},
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
__DEV__,
__PROD__,
__SERVER__,
__CLIENT__,
__DEBUG__,
}),
],
});
const webpack = require('webpack');
const Config = require('webpack-config');
const webpackConfig = new Config.Config();
const appConfig = require('../index');
const debug = require('debug');
debug.enable('wh3rk:*');
const log = debug('wh3rk:test');
/* Globals */
const NODE_ENV = process.env.NODE_ENV || 'test';
global.__DEV__ = NODE_ENV !== 'production';
global.__PROD__ = NODE_ENV === 'production';
global.__DEBUG__ = __DEV__;
global.__SERVER__ = true;
global.__CLIENT__ = false;
log('Extending webpack configuration with test settings.');
log('...');
log('...');
module.exports = webpackConfig.extend('config/webpack/webpack.config.base.js').merge({
entry: {
app: [appConfig.paths.entryFile],
vendor: appConfig.webpack.vendor,
},
output: {
path: `${ appConfig.paths.dist }/[${ appConfig.webpack.test.hash_type }]/`,
publicPath: `/[${ appConfig.webpack.test.hash_type }]/`,
filename: `[name].[${ appConfig.webpack.test.hash_type }].js`,
chunkFilename: `[id].[${ appConfig.webpack.test.hash_type }].js`,
sourceMapFilename: '[file].map',
library: 'App',
libraryTarget: 'umd', // others: var, this, commonjs, commonjs2, amd, umd
},
stats: appConfig.webpack.test.stats,
module: {
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel',
query: {
presets: ['react', ['es2015', { modules: false }], 'stage-0'],
plugins: ['transform-decorators-legacy'],
},
include: appConfig.paths.app,
},
{
test: /\.(css|scss)$/,
loaders: [
'style',
'css?' +
'modules&' +
'localIdentName=[local]__[hash:base64:4]&' +
'importLoaders=1&' +
'sourceMap',
'postcss',
'sass?sourceMap',
],
},
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('test'),
__DEV__,
__PROD__,
__SERVER__,
__CLIENT__,
__DEBUG__,
}),
],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment