Last active
May 30, 2017 23:42
-
-
Save notafunction/93e29c2b475113753ddf6d5bf53513b9 to your computer and use it in GitHub Desktop.
Tree-shaking Webpack 2 configuration for React projects.
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
| const webpack = require('webpack'); | |
| const path = require('path'); | |
| const ExtractTextPlugin = require('extract-text-webpack-plugin'); | |
| const HtmlWebpackPlugin = require('html-webpack-plugin'); | |
| const PreloadWebpackPlugin = require('preload-webpack-plugin'); | |
| const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); | |
| const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin'); | |
| const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin'); | |
| const host = process.env.HOST || 'localhost'; | |
| const port = process.env.PORT || '3000'; | |
| const sourcePath = path.join(__dirname, 'src'); | |
| const buildPath = path.join(__dirname, 'build'); | |
| const stats = { | |
| assets: true, | |
| children: false, | |
| chunks: false, | |
| hash: false, | |
| modules: false, | |
| publicPath: false, | |
| timings: true, | |
| version: false, | |
| warnings: true, | |
| colors: { | |
| green: '\u001b[32m', | |
| }, | |
| }; | |
| module.exports = function(env) { | |
| const nodeEnv = env && env.prod ? 'production' : 'development'; | |
| const isProd = env === 'production'; | |
| const serviceWorkerBuild = env && env.sw; | |
| // Define common plugins | |
| const plugins = [ | |
| new webpack.DefinePlugin({ | |
| 'process.env': { NODE_ENV: JSON.stringify(nodeEnv) } | |
| }), | |
| new webpack.optimize.CommonsChunkPlugin({ | |
| async: true, | |
| children: true, | |
| minChunks: 2, | |
| }), | |
| new HtmlWebpackPlugin({ | |
| template: path.join(__dirname, 'src', 'index.ejs'), | |
| inject: true, | |
| production: isProd, | |
| minify: isProd && { | |
| removeComments: true, | |
| collapseWhitespace: true, | |
| removeRedundantAttributes: true, | |
| useShortDoctype: true, | |
| removeEmptyAttributes: true, | |
| removeStyleLinkTypeAttributes: true, | |
| keepClosingSlash: true, | |
| minifyJS: true, | |
| minifyCSS: true, | |
| minifyURLs: true, | |
| }, | |
| }), | |
| new ScriptExtHtmlWebpackPlugin({ | |
| defaultAttribute: 'async', | |
| }), | |
| new PreloadWebpackPlugin(), | |
| ]; | |
| if (isProd) { | |
| // Production plugins | |
| plugins.push( | |
| // minify remove some of the dead code | |
| new UglifyJSPlugin({ | |
| compress: { | |
| warnings: false, | |
| screw_ie8: true, | |
| conditionals: true, | |
| unused: true, | |
| comparisons: true, | |
| sequences: true, | |
| dead_code: true, | |
| evaluate: true, | |
| if_return: true, | |
| join_vars: true, | |
| }, | |
| }) | |
| ); | |
| // Define css loaders | |
| cssLoader = ExtractTextPlugin.extract({ | |
| fallback: 'style-loader', | |
| use: [ | |
| { | |
| loader: 'css-loader', | |
| options: { | |
| module: true, // css-loader 0.14.5 compatible | |
| modules: true, | |
| localIdentName: '[hash:base64:5]', | |
| }, | |
| }, | |
| { | |
| loader: 'sass-loader', | |
| options: { | |
| outputStyle: 'collapsed', | |
| sourceMap: true, | |
| includePaths: [sourcePath], | |
| }, | |
| }, | |
| ], | |
| }); | |
| } else { | |
| // Development plugins | |
| plugins.push( | |
| // make hot reloading work | |
| new webpack.HotModuleReplacementPlugin(), | |
| // show module names instead of numbers in webpack stats | |
| new webpack.NamedModulesPlugin(), | |
| // don't spit out any errors in compiled assets | |
| new webpack.NoEmitOnErrorsPlugin() | |
| ); | |
| cssLoader = [ | |
| { | |
| loader: 'style', | |
| }, | |
| { | |
| loader: 'css', | |
| options: { | |
| module: true, | |
| localIdentName: '[path][name]-[local]', | |
| }, | |
| }, | |
| { | |
| loader: 'sass', | |
| options: { | |
| outputStyle: 'expanded', | |
| sourceMap: false, | |
| includePaths: [sourcePath], | |
| }, | |
| }, | |
| ]; | |
| } | |
| // Service worker cache | |
| if (serviceWorkerBuild) { | |
| plugins.push( | |
| new SWPrecacheWebpackPlugin({ | |
| cacheId: 'portfolio', | |
| filename: 'sw.js', | |
| maximumFileSizeToCacheInBytes: 800000, | |
| mergeStaticsConfig: true, | |
| minify: true, | |
| runtimeCaching: [ | |
| { | |
| handler: 'cacheFirst', | |
| urlPattern: /(.*?)/, | |
| }, | |
| ], | |
| }) | |
| ); | |
| } | |
| const entryPoint = isProd | |
| ? path.join(__dirname, 'src', 'entry.js') | |
| : [ | |
| // Activate HMR for react | |
| 'react-hot-loader/patch', | |
| // bundle the client for webpack-dev-server | |
| // and connect to the provided endpoint | |
| `webpack-dev-server/client?http://${host}:${port}`, | |
| // bundle the client for hot reloading | |
| // only- means to only hot reload for successful updates | |
| 'webpack/hot/only-dev-server', | |
| // the entry point of our app | |
| path.join(__dirname, 'src', 'entry.js'), | |
| ]; | |
| return { | |
| devtool: isProd ? 'source-map' : 'cheap-module-source-map', | |
| context: sourcePath, | |
| entry: { | |
| main: entryPoint, | |
| }, | |
| output: { | |
| path: buildPath, | |
| publicPath: '/', | |
| filename: '[name]-[hash:8].js', | |
| chunkFilename: '[name]-[chunkhash:8].js', | |
| }, | |
| module: { | |
| rules: [ | |
| // Static assets loader | |
| { | |
| test: /\.(html|svg|jpe?g|png|ttf|woff2?)$/, | |
| include: sourcePath, | |
| use: { | |
| loader: 'file', | |
| options: { | |
| name: 'static/[name]-[hash:8].[ext]' | |
| }, | |
| }, | |
| }, | |
| // Sass loader | |
| { | |
| test: /\.scss$/, | |
| include: sourcePath, | |
| use: cssLoader, | |
| }, | |
| // Js/jsx loader | |
| { | |
| test: /\.jsx?$/, | |
| include: sourcePath, | |
| use: ['babel'] | |
| } | |
| ] | |
| }, | |
| resolve: { | |
| extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'], | |
| modules: [path.resolve(__dirname, 'node_modules'), sourcePath] | |
| }, | |
| plugins, | |
| performance: isProd && { | |
| maxAssetSize: 300000, | |
| maxEntryPointSize: 300000, | |
| hints: 'warning' | |
| }, | |
| stats: stats, | |
| devServer: { | |
| contentBase: sourcePath, | |
| publicPath: '/', | |
| historyApiFallback: true, | |
| port: port, | |
| host: host, | |
| hot: !isProd, | |
| compress: isProd, | |
| stats: stats | |
| }, | |
| }; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment