Last active
April 21, 2018 01:03
-
-
Save dtothefp/7769a27293cf771dbd60fe46dcc99c3c to your computer and use it in GitHub Desktop.
This file contains 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
import path from 'path'; | |
import webpack from 'webpack'; | |
import MiniCssExtractPlugin from 'mini-css-extract-plugin'; | |
import UglifyJsPlugin from 'uglifyjs-webpack-plugin'; | |
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; | |
import Dotenv from 'dotenv-webpack'; | |
import HardSourceWebpackPlugin from 'hard-source-webpack-plugin'; | |
import { BundleStatsPlugin } from './plugins/BundleStatsPlugin'; | |
import { LoadableStatsPlugin } from './plugins/LoadableStatsPlugin'; | |
import generateStats from './generate-stats'; | |
import statsOptions from './stats-options'; | |
import svgoLoader from './loaders/svgo-loader'; | |
import defineEnv from './define-env-config'; | |
import { babelLoaderOptions } from './loaders/babel-loader'; | |
/** | |
* This is the Webpack configuration file for local development. It contains | |
* local-specific configuration such as the React Hot Loader, as well as: | |
* | |
* - The entry point of the application | |
* - Where the output file should be | |
* - Which loaders to use on what files to properly transpile the source | |
* | |
* For more information, see: http://webpack.github.io/docs/configuration.html | |
* @param {Object} config global task config | |
* @return {Object} webpack client config | |
*/ | |
export default function(config) { | |
const { | |
assetDest, | |
cssModuleTest, | |
cssGlobalTest, | |
envVars, | |
src, | |
dest, | |
cwd, | |
base, | |
dllManifestFile, | |
experimental, | |
statOutput, | |
jsonDir, | |
makeConfigHash, | |
makeLoaders, | |
progressBar, | |
splitChunks, | |
excludeJsRe, | |
env, | |
quick, | |
library, | |
visualize, | |
chunkStatsFile, | |
stats, | |
entry: {js}, | |
} = config; | |
const isDev = env === `development`; | |
const minimize = !isDev && !quick; | |
// TODO: add CDN path here depending upon TRAVIS_BRANCH | |
const publicPath = envVars.PUBLIC_PATH; | |
// TODO: webpack hashing is messed up, when it gets fixed remove this timestamp | |
const timestamp = new Date().getTime(); | |
const assetEntries = { | |
css: { | |
development: `[name].css`, | |
production: `[name]-[chunkhash]-${timestamp}.css`, | |
}, | |
js: { | |
development: `[name].js`, | |
production: `[name]-[chunkhash]-${timestamp}.js`, | |
}, | |
}; | |
const cssLoader = ({modules} = {}) => { | |
const options = { | |
importLoaders: 1, | |
minimize, | |
}; | |
if (modules) { | |
Object.assign(options, { | |
modules: true, | |
localIdentName: `[name]__[local]___[hash:base64:5]`, | |
}); | |
} | |
return { | |
loader: `css-loader`, | |
options, | |
}; | |
}; | |
const postcssLoader = { | |
loader: `postcss-loader`, | |
options: { | |
config: { | |
path: base(`postcss.config.js`), | |
}, | |
}, | |
}; | |
const makeStyleLoaders = ({modules} = {}) => { | |
const loaders = [ cssLoader({modules}), postcssLoader ]; | |
if (modules && isDev) { | |
loaders.unshift(`style-loader?singleton`); | |
} | |
return makeLoaders(loaders); | |
}; | |
const devPlugins = [ | |
new HardSourceWebpackPlugin({ | |
configHash: makeConfigHash(), | |
environmentHash: { | |
root: process.cwd(), | |
directories: [], | |
files: [`yarn.lock`], | |
}, | |
}), | |
new webpack.HotModuleReplacementPlugin(), | |
new webpack.NamedModulesPlugin(), | |
new webpack.DllReferencePlugin({ | |
manifest: cwd(dest, dllManifestFile), | |
}), | |
new webpack.WatchIgnorePlugin([ | |
/node_modules/, | |
]), | |
]; | |
const output = { | |
library, | |
libraryExport: `default`, | |
path: cwd(dest + assetDest), | |
filename: assetEntries.js[env], | |
publicPath, | |
}; | |
const prodPlugins = [ | |
// TEST: scope hoisting | |
// https://medium.com/webpack/brief-introduction-to-scope-hoisting-in-webpack-8435084c171f | |
new webpack.optimize.ModuleConcatenationPlugin(), | |
new webpack.optimize.OccurrenceOrderPlugin(), | |
]; | |
const plugins = [ | |
new Dotenv({ | |
path: `./.env`, | |
safe: false, | |
}), | |
new webpack.DefinePlugin( | |
defineEnv({target: `client`, config}) | |
), | |
new MiniCssExtractPlugin({ | |
filename: assetEntries.css[env], | |
}), | |
progressBar, | |
]; | |
const entry = [ | |
`./${src}/${js}`, | |
]; | |
if (visualize) { | |
plugins.push( | |
new BundleAnalyzerPlugin({statsOptions}) | |
); | |
} else if (stats) { | |
plugins.push( | |
new BundleStatsPlugin({ | |
filename: cwd(dest, `bundle-stats.json`), | |
}) | |
); | |
} else { | |
plugins.push(...[ | |
generateStats(config), | |
new LoadableStatsPlugin({ | |
filename: cwd(dest, chunkStatsFile), | |
}), | |
]); | |
} | |
const extractLoader = MiniCssExtractPlugin.loader; | |
const extractCss = (loaders) => isDev ? loaders : [ extractLoader, ...loaders ]; | |
const jsonExtractLoader = { | |
type: `javascript/auto`, | |
test: /\.json$/, | |
use: [ | |
{ | |
loader: path.resolve(__dirname, `loaders`, `json-loader.js`), | |
options: { | |
outputPath: cwd(dest, jsonDir), | |
name: `[path][name].[ext]`, | |
}, | |
}, | |
], | |
}; | |
const devLoaders = []; | |
if (experimental) { | |
devLoaders.push(jsonExtractLoader); | |
} | |
const loaders = [ | |
{ | |
test: /\.jsx?$/, | |
exclude: /node_modules/, | |
enforce: `pre`, | |
use: makeLoaders({ | |
loader: `eslint-loader`, | |
options: { | |
cache: true, | |
}, | |
}), | |
}, | |
{ | |
test: /\.jsx?$/, | |
exclude: excludeJsRe, | |
use: makeLoaders({ | |
loader: `babel-loader`, | |
options: babelLoaderOptions({env, target: `client`}), | |
}), | |
}, | |
{ | |
test: cssModuleTest, | |
use: extractCss(makeStyleLoaders({modules: true})), | |
}, | |
{ | |
test: cssGlobalTest, | |
use: [ extractLoader, ...makeStyleLoaders() ], | |
}, | |
{ | |
test: /\/images\/.*\.svg$/, | |
exclude: /assets-spa\/images\/.*\.svg$/, | |
use: [ | |
`file-loader`, | |
svgoLoader(`file`), | |
], | |
}, | |
{ | |
test: /\.svg$/, | |
exclude: /\/images\/.*\.svg$/, | |
use: [ | |
`svg-react-loader`, | |
svgoLoader(`inline`), | |
], | |
}, | |
]; | |
let devtool; | |
if (isDev) { | |
plugins.unshift(...devPlugins); | |
loaders.push(...devLoaders); | |
devtool = `cheap-module-eval-source-map`; | |
} else { | |
plugins.push(...prodPlugins); | |
devtool = `source-map`; | |
} | |
return { | |
devtool, | |
entry: { | |
main: entry, | |
}, | |
output, | |
resolve: { | |
extensions: [ `.js`, `.jsx`, `.css` ], | |
alias: { | |
actions: cwd(src, `actions`), | |
analytics: cwd(src, `analytics`), | |
classnames: `classnames`, | |
pages: cwd(src, `pages`), | |
react: `react`, | |
'react-redux': `react-redux`, | |
utils: cwd(src, `utils`), | |
sheets: cwd(`node_modules`, `sheets`, `lib`), | |
}, | |
modules: [ | |
cwd(src), | |
base(`node_modules`), | |
`node_modules`, | |
], | |
}, | |
mode: env, | |
performance: { | |
hints: false, | |
}, | |
cache: true, | |
plugins, | |
module: { | |
rules: loaders, | |
}, | |
optimization: { | |
minimize, | |
minimizer: [ | |
new UglifyJsPlugin({ | |
parallel: true, | |
sourceMap: true, | |
uglifyOptions: { | |
output: { | |
comments: false, | |
}, | |
compress: { | |
warnings: false, | |
}, | |
}, | |
}), | |
], | |
splitChunks, | |
}, | |
stats: isDev ? `none` : statOutput, | |
node: { | |
fs: `empty`, | |
__dirname: false, | |
}, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment