Skip to content

Instantly share code, notes, and snippets.

@mnpenner
Last active February 5, 2018 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnpenner/d09beb0c243311d2f5f512d0899114c0 to your computer and use it in GitHub Desktop.
Save mnpenner/d09beb0c243311d2f5f512d0899114c0 to your computer and use it in GitHub Desktop.
"devDependencies": {
"autoprefixer": "^6.7.6",
"babel-core": "^6.26.0",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.5",
"babel-plugin-check-es2015-constants": "^6.8.0",
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-syntax-flow": "^6.13.0",
"babel-plugin-syntax-trailing-function-commas": "^6.13.0",
"babel-plugin-transform-async-to-generator": "^6.8.0",
"babel-plugin-transform-async-to-module-method": "^6.8.0",
"babel-plugin-transform-class-constructor-call": "^6.8.0",
"babel-plugin-transform-class-properties": "^6.11.5",
"babel-plugin-transform-decorators": "^6.13.0",
"babel-plugin-transform-es2015-arrow-functions": "^6.8.0",
"babel-plugin-transform-es2015-block-scoped-functions": "^6.8.0",
"babel-plugin-transform-es2015-block-scoping": "^6.26.0",
"babel-plugin-transform-es2015-classes": "^6.14.0",
"babel-plugin-transform-es2015-computed-properties": "^6.8.0",
"babel-plugin-transform-es2015-destructuring": "^6.9.0",
"babel-plugin-transform-es2015-for-of": "^6.8.0",
"babel-plugin-transform-es2015-function-name": "^6.9.0",
"babel-plugin-transform-es2015-literals": "^6.8.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
"babel-plugin-transform-es2015-object-super": "^6.8.0",
"babel-plugin-transform-es2015-parameters": "^6.11.4",
"babel-plugin-transform-es2015-shorthand-properties": "^6.8.0",
"babel-plugin-transform-es2015-spread": "^6.8.0",
"babel-plugin-transform-es2015-sticky-regex": "^6.8.0",
"babel-plugin-transform-es2015-template-literals": "^6.8.0",
"babel-plugin-transform-es2015-typeof-symbol": "^6.8.0",
"babel-plugin-transform-es2015-unicode-regex": "^6.11.0",
"babel-plugin-transform-es3-member-expression-literals": "^6.8.0",
"babel-plugin-transform-es3-property-literals": "^6.8.0",
"babel-plugin-transform-es5-property-mutators": "^6.8.0",
"babel-plugin-transform-exponentiation-operator": "^6.8.0",
"babel-plugin-transform-export-extensions": "^6.8.0",
"babel-plugin-transform-flow-strip-types": "^6.14.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-react-constant-elements": "^6.9.1",
"babel-plugin-transform-react-inline-elements": "^6.8.0",
"babel-plugin-transform-react-remove-prop-types": "^0.3.2",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-polyfill": "^6.26.0",
"babel-preset-react": "^6.11.1",
"babel-runtime": "^6.26.0",
"blueimp-file-upload": "^9.19.1",
"bootstrap": "^3.3.7",
"bundle-loader": "^0.5.5",
"chunk-manifest-webpack-plugin": "^1.1.2",
"classnames": "^2.2.5",
"core-js": "^2.5.1",
"css-loader": "^0.26.2",
"datatables.net": "^1.10.16",
"datatables.net-dt": "^1.10.16",
"eslint": "^3.7.1",
"eslint-codeframe-formatter": "^1.0.2",
"eslint-loader": "^1.9.0",
"eslint-plugin-no-unused-vars-rest": "^1.0.4",
"eslint-plugin-react": "^6.2.0",
"exports-loader": "^0.6.4",
"expose-loader": "^0.7.4",
"extract-text-webpack-plugin": "^3.0.2",
"fancybox": "^2.1.8",
"file-loader": "^0.8.5",
"form-capacitor": "^0.1.16",
"highcharts": "^5.0.14",
"immutability-helper2": "^2.5.0",
"immutable": "^3.8.2",
"immutable-devtools": "0.0.7",
"imports-loader": "^0.7.1",
"jquery": "^1.12.4",
"jquery-expander": "^1.6.1",
"jquery-migrate": "^1.4.1",
"jquery-ui": "~1.10",
"jquery-ui-touch-punch": "^0.2.3",
"jquery-validation": "^1.17.0",
"jquery.cookie": "^1.4.1",
"jquery.taps": "0.0.3",
"jquery.transit": "^0.9.12",
"jwt-decode": "^2.1.0",
"less": "^2.7.3",
"less-loader": "^2.2.2",
"loader-utils": "^1.0.2",
"lodash": "^4.17.4",
"lodash3": "^3.10.1",
"marked": "^0.3.6",
"memory-fs": "^0.4.1",
"moment": "^2.19.2",
"numeral": "^1.5.3",
"optimist": "^0.6.1",
"postcss-loader": "^1.3.2",
"postcss-opacity": "^4.0.0",
"prop-types": "^15.6.0",
"pubsub-js": "^1.5.7",
"raw-loader": "^0.5.1",
"react": "^15.6.2",
"react-addons-shallow-compare": "^15.6.2",
"react-dnd": "^2.4.0",
"react-dnd-html5-backend": "^2.3.0",
"react-dom": "^15.6.2",
"react-hot-loader": "^1.3.0",
"react-redux": "^5.0.6",
"recompose": "^0.25.1",
"redux": "^3.7.2",
"regenerator": "^0.8.46",
"reselect": "^2.5.4",
"sanitize-filename": "^1.6.0",
"script-loader": "^0.7.2",
"select2": "^3.5.1",
"select2-bootstrap-css": "^1.4.6",
"selectize": "^0.12.2",
"sizzle": "^2.3.3",
"socket.io-client": "^1.4.8",
"sprintf-js": "^1.0.3",
"strip-loader": "^0.1.2",
"style-loader": "^0.13.2",
"supports-color": "^3.1.2",
"through2": "^2.0.1",
"timezone-js": "^0.4",
"underscore.string": "^3.3.4",
"url-loader": "^0.5.8",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.5",
"webpack-error-notification": "^0.1.7"
}
/* eslint-env node */
"use strict";
process.noDeprecation = true; // https://github.com/webpack/loader-utils/issues/56#issuecomment-281967053
const webpack = require('webpack');
const fs = require('fs');
const path = require('path');
const _ = require('lodash');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ChunkManifestPlugin = require('chunk-manifest-webpack-plugin');
let wxConfig = fs.existsSync('.config.json') ? require('./.config.json') : {};
let wxEnv = _.get(process.env, 'NODE_ENV', _.get(wxConfig, 'env', 'live'));
let debug = _.get(wxConfig, 'debug', wxEnv === 'dev');
let stdEnv = wxEnv;
function concat() {
return _.reduce(arguments, function(a, b) {
if(_.isEmpty(b)) {
return a;
}
return a.concat(_.isArray(b) ? b : [b]);
}, []);
}
switch(wxEnv) {
case 'dev':
case 'development':
stdEnv = 'development';
break;
case 'live':
case 'prod':
case 'production':
case 'ie':
case 'demo':
stdEnv = 'production';
break;
default:
throw new Error(`Unsupported environment: ${wxEnv}`);
}
let nodeModulesDir = path.resolve(__dirname, 'node_modules');
let publicDir = path.resolve(__dirname, 'www');
let publicAssetsDir = path.resolve(publicDir, 'assets');
let assetsDir = path.resolve(__dirname, 'assets');
let nodeModule = _.partial(path.join, nodeModulesDir);
let script = _.partial(path.join, assetsDir, 'scripts');
let isDevServer = path.basename(require.main.filename) === 'webpack-dev-server.js';
let cssSourceMaps = false; // I can't get this to work. !isDevServer;
let cssLoaders = [
{
loader: 'css-loader',
options: {
sourceMap: cssSourceMaps,
root: publicDir,
localIdentName: '[name]_[local]--[hash:base64:5]',
importLoaders: 2,
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: cssSourceMaps ? 'inline' : false,
}
}
];
let lessLoader = {
loader: 'less-loader',
options: {
sourceMap: cssSourceMaps, // https://github.com/webpack-contrib/less-loader#sourcemaps
strictMath: true,
strictUnits: true,
}
};
const webpackMerge = _.partialRight(_.assignWith, function(a, b) {
if(_.isArray(a) && _.isArray(b)) {
return b.concat(a);
}
if(_.isPlainObject(a) && _.isPlainObject(b)) {
return webpackMerge(a, b);
}
return b;
});
const vendorDirs = [
'node_modules',
'vendor',
].map(p => path.resolve(__dirname, p) + path.sep);
function isVendorModule(module) {
return module.context && vendorDirs.some(d => module.context.startsWith(d));
}
let webpackConfig = {
target: 'web',
context: __dirname,
entry: {
main: [
script('lib/autofocus-polyfill'),
script('lib/matches-polyfill'),
'core-js/es6', // IE10 does not have Array.find and does not read <!-- conditional comments -->
'core-js/stage/4',
path.join(__dirname, 'assets/main'),
],
print: [
path.join(__dirname, 'assets/stylesheets/print'),
],
ie8: [
'core-js/es5',
],
},
output: {
path: publicAssetsDir,
pathinfo: debug, // Include comments with information about the modules.
publicPath: '/assets/',
crossOriginLoading: 'anonymous', // Cross-origin loading is enabled. When using anonymous no credentials will be send with the request.
},
resolve: {
modules: [
assetsDir,
...vendorDirs,
],
alias: {
'jquery-ui/ui/widget': nodeModule('jquery-ui/widget.js'),
},
extensions: ['.jsx', '.js', '.less', '.css'],
},
node: {
__filename: true,
__dirname: true,
fs: "empty"
},
amd: {
jQuery: true
},
module: {
rules: [
{
test: /\.jsx?$/,
include: assetsDir,
loader: 'babel-loader',
options: {
cacheDirectory: `${__dirname}/cache/babel`,
forceEnv: stdEnv,
}
},
{
test: /\.(jpe?g|png|gif|svg)($|\?)/i,
loader: 'url-loader', // Inline images if they're less than 2 KiB
options: {
limit: 2048,
name: '[name]-[sha1:hash:hex:10].[ext]',
}
},
{
test: /\.(eot|ttf|woff2?|htc)($|\?)/i,
loader: 'file-loader',
options: {
name: '[name]-[sha1:hash:hex:10].[ext]',
},
},
],
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
timezoneJS: 'timezone-js',
React: 'react',
_: 'lodash',
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(stdEnv), // Every other lib expects "live" to be called "production". In particular, this will make React smaller
},
}),
{
apply: function(compiler) {
compiler.plugin('done', function(stats, done) {
let assets = {};
_.forOwn(stats.compilation.namedChunks, (chunk, name) => {
assets[name] = chunk.files;
});
fs.writeFile('webpack.stats.json', JSON.stringify({
assetsByChunkName: assets,
publicPath: stats.compilation.outputOptions.publicPath
}), done);
});
}
},
]
};
if(isDevServer) {
const devServerPort = 5584;
const publicPath = webpackConfig.output.publicPath;
webpackMerge(webpackConfig, {
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader',
...cssLoaders,
lessLoader
],
},
{
test: /\.css$/,
use: [
'style-loader',
...cssLoaders,
],
},
],
},
entry: {
main: [
'webpack-dev-server/client?http://0.0.0.0:' + devServerPort,
],
},
plugins: [
],
devServer: {
port: devServerPort,
hot: false,
inline: false,
historyApiFallback: false,
stats: {
assets: false,
children: false,
chunkModules: false,
chunks: false,
colors: true,
errorDetails: true,
errors: true,
hash: false,
publicPath: false,
reasons: true,
source: false,
timings: true,
version: false,
warnings: true,
},
watchOptions: {
aggregateTimeout: 250,
poll: 50,
ignored: /node_modules/
},
host: '0.0.0.0',
lazy: false, // No watching, compiles on request (cannot be combined with --hot).
quiet: false, // Display nothing to the console
noInfo: true, // Display no info to console (only warnings and errors)
disableHostCheck: true, // Fixes "Invalid Host header" https://github.com/webpack/webpack-dev-server/issues/882
headers: {
'Access-Control-Allow-Origin': '*', // Fixes "Access to Script at 'http://xxx:5584/assets/chunk-ab037d3e682ee7449db0.js' from origin 'http://example.com' has been blocked by CORS policy"
}
},
output: {
publicPath: `http://${wxConfig.server}:${devServerPort}${publicPath}`,
filename: '[name].bundle.js',
chunkFilename: 'chunk.[id].js',
},
bail: false,
});
} else { // not dev-server
webpackMerge(webpackConfig, {
output: {
filename: '[name].[chunkhash].js',
chunkFilename: 'chunk.[chunkhash].js',
},
plugins: [
new ExtractTextPlugin('[name]-[contenthash].css'),
],
module: {
rules: [
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [...cssLoaders, lessLoader],
}),
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: cssLoaders,
}),
},
],
},
bail: true,
});
}
switch(wxEnv) {
case 'dev':
webpackMerge(webpackConfig, {
devtool: debug ? 'source-map' : 'eval',
});
break;
case 'ie':
// This might make it a smidgin easier to debug Internet Explorer
webpackMerge(webpackConfig, {
devtool: false,
plugins: [
new webpack.optimize.UglifyJsPlugin({
output: {
beautify: true,
comments: true,
screw_ie8: false,
},
compress: {
booleans: false,
cascade: false,
conditionals: false,
dead_code: true,
drop_debugger: true,
hoist_funs: false,
hoist_vars: true,
if_return: false,
join_vars: false,
loops: false,
negate_iife: false,
properties: false,
screw_ie8: false,
sequences: false,
unused: true,
warnings: false,
},
mangle: false,
sourceMap: false,
}),
],
});
break;
default:
case 'demo':
case 'live':
case 'production':
webpackMerge(webpackConfig, {
devtool: 'source-map',
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin({
output: {
beautify: debug,
screw_ie8: false,
},
compress: { // http://lisperator.net/uglifyjs/compress, http://davidwalsh.name/compress-uglify
warnings: false,
drop_console: !debug,
screw_ie8: false,
},
mangle: false, // mangle:true can break IE8 even with screw_ie8 set to false!
sourceMap: true,
}),
// These can't be enabled until this is resolved: https://github.com/webpack/extract-text-webpack-plugin/issues/115
new webpack.optimize.MinChunkSizePlugin({minChunkSize: 16384}),
new webpack.optimize.AggressiveMergingPlugin({
minSizeReduce: 1.25,
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'main',
children: false,
minChunks: isVendorModule,
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'main', // pull common dependencies into "main" bundle
children: true, // only check children of "main" for dependencies
minChunks: (module, count) => {
return count >= 5 && !isVendorModule(module);
},
async: true, // seems to make the main chunk slightly bigger (0.1 KB) and the other chunks smaller (0.9 KB)
}),
// I think we need *either* HashedModuleIdsPlugin or ChunkManifestPlugin to avoid all the files changing.
// HashedModuleIdsPlugin is simpler, and the hashes appear to be very short anyway
new webpack.HashedModuleIdsPlugin(), // added in webpack 2.0 (https://github.com/webpack/docs/wiki/roadmap)
new ChunkManifestPlugin({
filename: path.relative(publicAssetsDir, `${__dirname}/webpack.manifest.json`),
manifestVariable: "__WEBPACK_MANIFEST__"
}),
],
module: {
rules: [
{
enforce: 'pre',
test: /\.jsx?$/,
loader: 'eslint-loader',
include: assetsDir,
options: {
cache: false,
quiet: true, // process and report errors only and ignore warnings if this option is set to true; https://github.com/MoOx/eslint-loader#quiet-default-false
failOnError: true,
}
},
{
test: /\.jsx?$/,
loader: 'strip-loader',
options: {
strip: [
// https://developer.mozilla.org/en/docs/Web/API/console
'console.assert',
'console.count',
'console.dir',
'console.dirxml',
'console.group',
'console.groupCollapsed',
'console.groupEnd',
'console.info',
'console.log',
'console.profile',
'console.profileEnd',
'console.table',
'console.time',
'console.timeEnd',
'console.timeStamp',
// warn, trace and error are kept
]
},
}
]
},
});
break;
}
module.exports = webpackConfig;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment