This is an opinionated webpack configuration with smart defaults. It can help speed up the initial project setup time so you can focus on developing what's unique about your project.
This project is published as a scoped package. Use the following to install and save it as a dependency.
npm i --save @urban/webpack-config
webpack-config
specifies many of its dependencies as peerDependencies
in order to give the consumer of this package flexibility to decide which version to use. For instance, you might want to use React 0.13.x instead of version React 0.14.x.
In npm version 3.x.x
, peerDependencies
are no longer installed by default. In order to install the latest versions of this packages peerDependencies
, please run the following command.
npm i --save autoprefixer babel-loader css-loader extract-text-webpack-plugin file-loader json-loader postcss-loader style-loader url-loader webpack
webpack is a module bundler. It takes JavaScript modules with dependencies (i.e. other JavaScript files, CSS, images, ...) and generates static assets representing those modules for the browser. It's similar to Browserify but has a configuration based API.
-
Loaders
- babel - Transpiles ES2015 and ES2016 code into vanilla ES5 using Babel.
- css - Loads css file with resolved imports and returns css code (enables CSS Moduels).
- postcss - A fast CSS parser written in JavaScript.
- autoprefixer - Plugin to parse CSS and add vendor prefixes to CSS rules using values form Can I Use.
- file - Emits the file into the output folder and returns the (relative) url.
- json - Loads file as JSON.
- style - Add exports of a module as style to DOM (enabled in development).
- url - The url loader works like the file loader, but can return a Data Url if the file is smaller than a limit.
-
Plugins
- DedupePlugin - Reduces file size by removing duplicate files.
- DefinePlulgin - Inlines variables (
__DEV__
and__PRERELEASE__
) into the code which allows a minification pass to remove dead-code. - ExtractTextPlugin - Moves required CSS into a separate CSS output file (enabled in production).
- HotModuleReplacementPlugin - Enables Hot Module Replacement (enabled in development).
- NoErrorsPlugin - Prevents the output when an error occurs.
- OccurenceOrderPlugin - Assign the module and chunk ids by occurrence count making ids predictable and reduces the total file size.
- UglifyJs - Minimize all JavaScript output of chunks (enabled in production).
There are several different ways to invoke webpack
from the command line.
webpack
for building once for developmentwebpack -d
to switch loaders to debug mode, include source maps and output path infowebpack -p
for building once with minification and occurence order pluginswebpack --watch
for continuous incremental build (can combine with-d
or-p
)
To use this module, create a webpack.config.babel.js
file at the root of your project with the following content.
// webpack.config.babel.js
import getConfig = '@urban/webpack-config'
export default getConfig({
context: __dirname,
entry: './src/index.js',
output: {
path: './public/'
}
})
Next, add the following to the npm run
scripts within your package.json
file.
"scripts": {
"start": "webpack-dev-server -d",
"build": "NODE_ENV=production webpack -p"
}
You can now run your project in development with hot module replacement by typing npm start
in the terminal from the root directory. To view the results, open a browser to http://localhost:8080/webpack-dev-server/.
If you'd like to build the static assets for your project, type npm run build
into the terminal to generate all files into the public
directory. Then type open ./public/index.html
to view in your default browser.
In order to help in developing new features, the __DEV__
and __PRERELEASE__
global variables are made available to your code.
if (__DEV__) {
console.log('Debug info.')
}
if (__PRERELEASE__) {
console.log('Prerelease info.')
}
You can modify their default values by passing environment flags at build time. For instance, by building with BUILD_DEV=1 BUILD_PRERELEASE=0 webpack
from terminal, it will result in the following.
if (true) {
console.log('Debug info.')
}
if (false) {
console.log('Prerelease info.')
}
And with dead-code elimination through minification, it will result in the following.
console.log('Debug info.')
There are two different ways the configuration can be modified.
First, by adding additional options to the configuration object
passed into the getConfig
method. The will then by automatically merged with the defaults and even overriding them where possible.
import getConfig = '@urban/webpack-config'
// by adding additional, initial webpack config options
const config = {
context: __dirname,
entry: './src/index.js',
output: {
path: './public/'
// ...more output options (e.g. libraryTarget: 'umd')
},
// ...more output options (e.g. libraryTarget: 'umd')
resolve: {
modulesDirectories: ['src', 'node_modules']
}
}
// then export to webpack
export default getConfig(config)
Second, by manually merging or overriding the output of the getConfig
method.
import getConfig = '@urban/webpack-config'
// minimum initial webpack config options
const config = getConfig({
context: __dirname,
entry: './src/index.js',
output: {
path: './public/'
}
})
// by manually mergin or overriding config options
export default {
...config
output: {
...config.options
// ...more output options (e.g. libraryTarget: 'umd')
},
// ...more options or overrides
plugins: [
...config.plugins,
// ...additional plugins
]
}
To change the default Babel settings, create a file at the root of your project called .babelrc
that contains the options you'd like.
See babelrc for more information.
{
"presets": ["es2015", "stage-0"],
}
To change the default Autoprefixer settings, create a file at the root of your project called browserslist
that contains the options you'd like.
See Browserslist docs for queries, browser names, config format, and default value.
# Browsers that we support
> 1%
Last 2 versions
IE 8 # sorry
Each JavaScript module should require all it's dependencies, including styles. This is the "webpack way".
To require your styles from a JavaScript file, add the following. Be sure to include the extension: .css
in your path.
import './path/to/styles.css'
By default CSS exports all classNames
to the global selector scope. This means every selector has the potential of introducing unintended side effects by targeting unwanted elements or clashing with other selectors. However, with CSS Modules you can mitigate this issue and expose your CSS to JavaScript.
With the CSS Module syntax, the css-loader
replaces the className
with unique identifiers. For example, if you had a CSS file located at ./path/to/styles.css
with the following.
.className { color: green; }
.subClass p { color: blue; }
It would be transformed into the following.
.path-to-styles__className___23_aKvs-b8bW2Vg3fwHozO { color: green; }
.path-to-styles__subClass___13LGdX8RMStbBE9w-t0gZ1 p { color: blue; }
The identifiers are then available to your JavaScript module and can accessed with the following.
import { className, subClass } from './path/to/styles.css'
To make debugging easier, local classNames
use the [path][name]__[local]___[hash:base64:5]
format. Also, when authoring CSS, camelcasing className
is recommended because they are easier to use in the importing JavaScript module.
For more information on CSS Modules, please see Local scope, Composing CSS classes and Importing local class names.
Note: CSS Module syntax is enabled by default for all files with the .css
extension.
Autoprefixer is a post-process CSS transpiler that lets you write CSS without having to worry about vendor prefixing rules.
Note: Autoprefixer is enabled by default for all files with the .css
extension through cssnext
.
Inspired by:
The MIT License (MIT). Copyright (c) Urban Faubion.