🔥
This commit is contained in:
358
tools/webpack.config.js
Normal file
358
tools/webpack.config.js
Normal file
@@ -0,0 +1,358 @@
|
||||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import extend from 'extend';
|
||||
import AssetsPlugin from 'assets-webpack-plugin';
|
||||
|
||||
const isDebug = !process.argv.includes('--release');
|
||||
const isVerbose = process.argv.includes('--verbose');
|
||||
|
||||
//
|
||||
// Common configuration chunk to be used for both
|
||||
// client-side (client.js) and server-side (server.js) bundles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const config = {
|
||||
context: path.resolve(__dirname, '../src'),
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../build/public/assets'),
|
||||
publicPath: '/assets/',
|
||||
sourcePrefix: ' ',
|
||||
pathinfo: isVerbose,
|
||||
},
|
||||
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, '../src'),
|
||||
],
|
||||
query: {
|
||||
// https://github.com/babel/babel-loader#options
|
||||
cacheDirectory: isDebug,
|
||||
|
||||
// https://babeljs.io/docs/usage/options/
|
||||
babelrc: false,
|
||||
presets: [
|
||||
// Latest stable ECMAScript features
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-preset-latest
|
||||
'latest',
|
||||
// Experimental ECMAScript proposals
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-preset-stage-0
|
||||
'stage-0',
|
||||
// JSX, Flow
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
|
||||
'react',
|
||||
...isDebug ? [] : [
|
||||
// Optimize React code for the production build
|
||||
// https://github.com/thejameskyle/babel-react-optimize
|
||||
'react-optimize',
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
// Externalise references to helpers and builtins,
|
||||
// automatically polyfilling your code without polluting globals.
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-runtime
|
||||
'transform-runtime',
|
||||
...!isDebug ? [] : [
|
||||
// Adds component stack to warning messages
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
|
||||
'transform-react-jsx-source',
|
||||
// Adds __self attribute to JSX which React will use for some warnings
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
|
||||
'transform-react-jsx-self',
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel',
|
||||
include: path.resolve(__dirname, './node_modules/react-icons/md'),
|
||||
query: {
|
||||
presets: ['latest', 'react'],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css/,
|
||||
loaders: [
|
||||
'isomorphic-style-loader',
|
||||
`css-loader?${JSON.stringify({
|
||||
// CSS Loader https://github.com/webpack/css-loader
|
||||
importLoaders: 1,
|
||||
sourceMap: isDebug,
|
||||
// CSS Modules https://github.com/css-modules/css-modules
|
||||
modules: true,
|
||||
localIdentName: isDebug ? '[name]-[local]-[hash:base64:5]' : '[hash:base64:5]',
|
||||
// CSS Nano http://cssnano.co/options/
|
||||
minimize: !isDebug,
|
||||
discardComments: { removeAll: true },
|
||||
})}`,
|
||||
'postcss-loader?pack=default',
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
loader: path.resolve(__dirname, './lib/markdown-loader.js'),
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader',
|
||||
},
|
||||
{
|
||||
test: /\.txt$/,
|
||||
loader: 'raw-loader',
|
||||
},
|
||||
{
|
||||
test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
|
||||
loader: 'file-loader',
|
||||
query: {
|
||||
name: isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
query: {
|
||||
name: isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]',
|
||||
limit: 10000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
resolve: {
|
||||
root: path.resolve(__dirname, '../src'),
|
||||
modulesDirectories: ['node_modules'],
|
||||
extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx', '.json'],
|
||||
},
|
||||
|
||||
// Don't attempt to continue if there are any errors.
|
||||
bail: !isDebug,
|
||||
|
||||
cache: isDebug,
|
||||
debug: isDebug,
|
||||
|
||||
stats: {
|
||||
colors: true,
|
||||
reasons: isDebug,
|
||||
hash: isVerbose,
|
||||
version: isVerbose,
|
||||
timings: true,
|
||||
chunks: isVerbose,
|
||||
chunkModules: isVerbose,
|
||||
cached: isVerbose,
|
||||
cachedAssets: isVerbose,
|
||||
},
|
||||
|
||||
// The list of plugins for PostCSS
|
||||
// https://github.com/postcss/postcss
|
||||
postcss(bundler) {
|
||||
return {
|
||||
default: [
|
||||
// Transfer @import rule by inlining content, e.g. @import 'normalize.css'
|
||||
// https://github.com/jonathantneal/postcss-partial-import
|
||||
require('postcss-partial-import')({ addDependencyTo: bundler }),
|
||||
// Allow you to fix url() according to postcss to and/or from options
|
||||
// https://github.com/postcss/postcss-url
|
||||
require('postcss-url')(),
|
||||
// W3C variables, e.g. :root { --color: red; } div { background: var(--color); }
|
||||
// https://github.com/postcss/postcss-custom-properties
|
||||
require('postcss-custom-properties')(),
|
||||
// W3C CSS Custom Media Queries, e.g. @custom-media --small-viewport (max-width: 30em);
|
||||
// https://github.com/postcss/postcss-custom-media
|
||||
require('postcss-custom-media')(),
|
||||
// CSS4 Media Queries, e.g. @media screen and (width >= 500px) and (width <= 1200px) { }
|
||||
// https://github.com/postcss/postcss-media-minmax
|
||||
require('postcss-media-minmax')(),
|
||||
// W3C CSS Custom Selectors, e.g. @custom-selector :--heading h1, h2, h3, h4, h5, h6;
|
||||
// https://github.com/postcss/postcss-custom-selectors
|
||||
require('postcss-custom-selectors')(),
|
||||
// W3C calc() function, e.g. div { height: calc(100px - 2em); }
|
||||
// https://github.com/postcss/postcss-calc
|
||||
require('postcss-calc')(),
|
||||
// Allows you to nest one style rule inside another
|
||||
// https://github.com/jonathantneal/postcss-nesting
|
||||
require('postcss-nesting')(),
|
||||
// Unwraps nested rules like how Sass does it
|
||||
// https://github.com/postcss/postcss-nested
|
||||
require('postcss-nested')(),
|
||||
// W3C color() function, e.g. div { background: color(red alpha(90%)); }
|
||||
// https://github.com/postcss/postcss-color-function
|
||||
require('postcss-color-function')(),
|
||||
// Convert CSS shorthand filters to SVG equivalent, e.g. .blur { filter: blur(4px); }
|
||||
// https://github.com/iamvdo/pleeease-filters
|
||||
require('pleeease-filters')(),
|
||||
// Generate pixel fallback for "rem" units, e.g. div { margin: 2.5rem 2px 3em 100%; }
|
||||
// https://github.com/robwierzbowski/node-pixrem
|
||||
require('pixrem')(),
|
||||
// W3C CSS Level4 :matches() pseudo class, e.g. p:matches(:first-child, .special) { }
|
||||
// https://github.com/postcss/postcss-selector-matches
|
||||
require('postcss-selector-matches')(),
|
||||
// Transforms :not() W3C CSS Level 4 pseudo class to :not() CSS Level 3 selectors
|
||||
// https://github.com/postcss/postcss-selector-not
|
||||
require('postcss-selector-not')(),
|
||||
// Postcss flexbox bug fixer
|
||||
// https://github.com/luisrudge/postcss-flexbugs-fixes
|
||||
require('postcss-flexbugs-fixes')(),
|
||||
// Add vendor prefixes to CSS rules using values from caniuse.com
|
||||
// https://github.com/postcss/autoprefixer
|
||||
require('autoprefixer')({
|
||||
browsers: [
|
||||
'>1%',
|
||||
'last 4 versions',
|
||||
'Firefox ESR',
|
||||
'not ie < 9', // React doesn't support IE8 anyway
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
//
|
||||
// Configuration for the client-side bundle (client.js)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const clientConfig = extend(true, {}, config, {
|
||||
entry: {
|
||||
client: './client.js',
|
||||
},
|
||||
|
||||
output: {
|
||||
filename: isDebug ? '[name].js' : '[name].[chunkhash:8].js',
|
||||
chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
|
||||
},
|
||||
|
||||
target: 'web',
|
||||
|
||||
plugins: [
|
||||
|
||||
// Define free variables
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
|
||||
'process.env.BROWSER': true,
|
||||
__DEV__: isDebug,
|
||||
}),
|
||||
|
||||
// Emit a file with assets paths
|
||||
// https://github.com/sporto/assets-webpack-plugin#options
|
||||
new AssetsPlugin({
|
||||
path: path.resolve(__dirname, '../build'),
|
||||
filename: 'assets.js',
|
||||
processOutput: x => `module.exports = ${JSON.stringify(x, null, 2)};`,
|
||||
}),
|
||||
|
||||
// Move modules that occur in multiple entry chunks to a new entry chunk (the commons chunk).
|
||||
// http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks: module => /node_modules/.test(module.resource),
|
||||
}),
|
||||
|
||||
...isDebug ? [] : [
|
||||
// Assign the module and chunk ids by occurrence count
|
||||
// Consistent ordering of modules required if using any hashing ([hash] or [chunkhash])
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#occurrenceorderplugin
|
||||
new webpack.optimize.OccurrenceOrderPlugin(true),
|
||||
|
||||
// Search for equal or similar files and deduplicate them in the output
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
|
||||
// Minimize all JavaScript output of chunks
|
||||
// https://github.com/mishoo/UglifyJS2#compressor-options
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
screw_ie8: true, // React doesn't support IE8
|
||||
warnings: isVerbose,
|
||||
unused: true,
|
||||
dead_code: true,
|
||||
},
|
||||
mangle: {
|
||||
screw_ie8: true,
|
||||
},
|
||||
output: {
|
||||
comments: false,
|
||||
screw_ie8: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
|
||||
// Choose a developer tool to enhance debugging
|
||||
// http://webpack.github.io/docs/configuration.html#devtool
|
||||
devtool: isDebug ? 'cheap-module-source-map' : false,
|
||||
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
// https://webpack.github.io/docs/configuration.html#node
|
||||
// https://github.com/webpack/node-libs-browser/tree/master/mock
|
||||
node: {
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty',
|
||||
},
|
||||
});
|
||||
|
||||
//
|
||||
// Configuration for the server-side bundle (server.js)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const serverConfig = extend(true, {}, config, {
|
||||
entry: {
|
||||
server: './server.js',
|
||||
},
|
||||
|
||||
output: {
|
||||
filename: '../../server.js',
|
||||
libraryTarget: 'commonjs2',
|
||||
},
|
||||
|
||||
target: 'node',
|
||||
|
||||
externals: [
|
||||
/^\.\/assets$/,
|
||||
(context, request, callback) => {
|
||||
const isExternal =
|
||||
request.match(/^[@a-z][a-z/.\-0-9]*$/i) &&
|
||||
!request.match(/\.(css|less|scss|sss)$/i);
|
||||
callback(null, Boolean(isExternal));
|
||||
},
|
||||
],
|
||||
|
||||
plugins: [
|
||||
// Define free variables
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
|
||||
'process.env.BROWSER': false,
|
||||
__DEV__: isDebug,
|
||||
}),
|
||||
|
||||
// Do not create separate chunks of the server bundle
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#limitchunkcountplugin
|
||||
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
|
||||
|
||||
// Adds a banner to the top of each generated chunk
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#bannerplugin
|
||||
new webpack.BannerPlugin('require("source-map-support").install();',
|
||||
{ raw: true, entryOnly: false }),
|
||||
],
|
||||
|
||||
node: {
|
||||
console: false,
|
||||
global: false,
|
||||
process: false,
|
||||
Buffer: false,
|
||||
__filename: false,
|
||||
__dirname: false,
|
||||
},
|
||||
|
||||
devtool: isDebug ? 'cheap-module-source-map' : 'source-map',
|
||||
});
|
||||
|
||||
export default [clientConfig, serverConfig];
|
||||
Reference in New Issue
Block a user