Various slightly opinionated shared webpack configurations to help you survive. Particularly useful with tools like webpack-merge.
- Webpack Configs
- Why?
- Requirements
- Installation
- Usage
- Shared Configuration Parts
devServer(options?: DevServer)
javascript(options?: {include?, exclude?, options?})
javascript.lint(options?: {include?, exclude?, options?})
javascript.sourcemap()
typescript(options?: {include?, exclude?, options?})
typescript.sourcemap()
typescript.hmr(options?: {include?, exclude?, options?, tsOptions?})
style(options: {test, include, exclude})
- Contribution
- License
- Specifically for my lazy self use case to not repeat common config over and over again.
- Maybe for you who have similarly use case as mine.
- More composed build.
- Node JS >= 6 LTS
- Webpack >= 2.2.0
with npm
npm install -D webpack webpack-merge webpack-configs
with yarn
yarn add -D webpack webpack-configs
This will not include any loader dependencies used in the shared configurations. You will have to install them separately.
const shared = require('webpack-configs');
// dev server
shared.devServer(options);
// javascript with babel-loader
shared.javascript(options);
// javascript linting with eslint-loader
shared.javascript.lint(options);
// style loaders
shared.style(options)
.use(shared.style.css({importLoaders: 1}))
.use(shared.style.post());
These configurations are best used with webpack-merge
.
// webpack.config.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const shared = require('webpack-configs');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const common = merge([
{
entry: {
app: PATHS.app,
},
output: {
path: PATHS.build,
filename: '[name].js',
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack demo',
}),
],
},
]);
function production() {
return merge([
common,
shared.javascript.lint({ include: PATHS.app }),
]);
}
function development() {
return merge([
common,
{
plugins: [
new webpack.NamedModulesPlugin(),
],
},
shared.devServer(),
shared.javascript.lint({
include: PATHS.app,
options: {
emitWarning: true,
},
}),
]);
}
module.exports = function(env) {
if (env === 'production') {
return production();
}
return development();
};
See more about composing webpack configuration in this SurviveJS page.
Returns webpack configuration which include devServer
and webpack.HotModuleReplacementPlugin
.
- [optional]
options
- DevServer options with some defaults set belowhost
- useprocess.env.HOST
if set, or webpack defaults otherwise ('localhost'
)port
- useprocess.env.PORT
if set, or webpack defaults otherwise (8080
)historyApiFallback
- defaults totrue
stats
- defaults to'errors-only'
publicPath
- defaults to'/'
contentBase
- defaults topublic
dir relative toprocess.cwd()
hotOnly
- defaults tofalse
hot
- defaults tofalse
shared.devServer() ===
{
devServer: {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8080,
historyApiFallback: true,
stats: 'errors-only',
publicPath: '/',
contentBase: `${process.cwd()}/public`,
hotOnly: true,
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
}
Returns webpack configuration which include module.rules
with babel-loader
.
NOTES: You must add babel-loader
dependency to use this.
- [optional]
options
- Rule Config to be applied
shared.javascript({include: path.resolve(__dirname, 'src')}) ===
{
module: {
rules: [{
test: /\.js(x?)$/,
loader: 'babel-loader',
include: './src'
}]
}
}
Returns webpack configuration which include module.rules
with eslint-loader
.
NOTES: You must add eslint-loader
dependency to use this.
- [optional]
options
- Rule Config to be applied
shared.javascript.lint({include: path.resolve(__dirname, 'src')}) ===
{
module: {
rules: [{
test: /\.js(x?)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: './src'
}]
}
}
Add sourcemap loader support as mentioned in Webpack + Typescript Guide
shared.javascript.sourcemap() ===
{
module: {
rules: [{
test: /\.js(x?)$/,
enforce: 'pre',
use: 'source-map-loader'
}]
}
}
Returns webpack configuration which include module.rules
with awesome-typescript-loader
.
NOTES: You must add awesome-typescript-loader
dependency to use this.
- [optional]
options
- Rule Config to be applied
shared.typescript({include: path.resolve(__dirname, 'src')}) ===
{
module: {
rules: [{
test: /\.ts(x?)$/,
loader: 'awesome-typescript-loader',
include: './src'
}]
},
plugins: [
new require('awesome-typescript-loader').CheckerPlugin(),
new require('awesome-typescript-loader').TsConfigPathsPlugin()
]
}
Add sourcemap loader support as mentioned in Webpack + Typescript Guide
shared.typescript.sourcemap() ===
{
module: {
rules: [{
test: /\.ts(x?)$/,
enforce: 'pre',
use: 'source-map-loader'
}]
}
}
Add React Hot Loader 3 into typescript build pipeline.
shared.typescript.hmr() ===
{
module: {
rules: [{
test: /\.ts(x?)$/,
use: [
'react-hot-loader/webpack',
{
loader: 'awesome-typescript-loader',
options: tsOptions,
}
],
}]
}
}
Returns webpack configuration which include module.rules
with style-loader
.
NOTES: You must add style-loader
dependency to use this.
- required
options
- Rule Config to be applied - methods:
use(loader, options?)
- Chainstyle-loader
with other commonly used style related loaders.- required
loader
- The loader to use, e.g'css-loader'
. Or one of predefined loaders described below. - [optional] options - Options passed to the loader.
- required
extract(options?)
- Transform the configuration to useextract-text-webpack-plugin
. More info below.- [optional] options - Options passed to instantiate the
extract-text-webpack-plugin
.
- [optional] options - Options passed to instantiate the
shared.style({test: /\.css$/}) ===
{
module: {
rules: [{
test: /\.css$/,
use: ['style-loader']
}]
}
}
You can chain with other shared style config below to make a use
style loaders chain, e.g. with prepocessor loader.
NOTES: The order of chain call matters.
shared.style({test: /\.css$/}).use(shared.style.css());
Below are the list of available method to chain
Chain style-loader
with css-loader
.
NOTES: You must add css-loader
dependency to use this.
- [optional]
options
- Options forcss-loader
shared.style({test: /\.css$/}).use(shared.style.css({modules: true})) ===
{
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}]
}
}
Chain style-loader
, css-loader
, with postcss-loader
.
NOTES: You must add postcss-loader
dependency to use this.
NOTES: Because the loader chain matters, you must call this after including css-loader
.
- [optional]
options
- [Options](https://github.com/postcss/postcss-loader#options forpostcss-loader
shared.style({test: /\.css$/})
.use(shared.style.css({modules: true}))
.use(shared.style.post()) ===
{
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
},
'postcss-loader'
]
}]
}
}
Chain style-loader
, css-loader
, with less-loader
.
NOTES: You must add less-loader
dependency to use this.
NOTES: Because the loader chain matters, you must call this after including css-loader
.
- [optional]
options
- Options forless-loader
shared.style({test: /\.css$/})
.use(shared.style.css({modules: true}))
.use(shared.style.less()) ===
{
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
},
'less-loader'
]
}]
}
}
Chain style-loader
, css-loader
, with sass-loader
.
NOTES: You must add sass-loader
dependency to use this.
NOTES: Because the loader chain matters, you must call this after including css-loader
.
- [optional]
options
- Options forsass-loader
shared.style({test: /\.css$/})
.use(shared.style.css({modules: true}))
.use(shared.style.sass()) ===
{
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
},
'sass-loader'
]
}]
}
}
You can call the extract
method as the last chain to transform the configuration
to use extract-text-webpack-plugin
instead. This will also include the plugin instance
in plugins
webpack array.
// You can use styleConfig in other config, e.g for development and test
const styleConfig = shared.style({test: /\.css$/})
.use(shared.style.css({modules: true}))
.use(shared.style.post())
.use(shared.style.sass())
// Then for a specific build config, you want it to use `extract-text-webpack-plugin`
const extracted = styleConfig.extract({filename: '[name].[contenthash].css'}) ===
{
module: {
rules: [{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
},
'postcss-loader',
'sass-loader'
]
})
}]
},
// plugins included
plugins: [
new ExtractTextPlugin({filename: '[name].[contenthash].css'})
]
}
The included shared configs are non exhaustive, if you have some configurations you want to share please drop an issue.
MIT