Skip to content

Instantly share code, notes, and snippets.

@solarsailer
Last active July 31, 2017 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save solarsailer/036759a15c2515e674756cbc10151ce0 to your computer and use it in GitHub Desktop.
Save solarsailer/036759a15c2515e674756cbc10151ce0 to your computer and use it in GitHub Desktop.
webpack configuration for Sass, Autoprefixer, CSS, CSS Modules and ES6+

Structure

📄 webpack.config.js
📄 package.json
📁 scripts/
  📄 manifest.js
  📄 index.js
📁 stylesheets/
  📄 main.scss
// JS entry point.
import './index.js'
// Global CSS entry point.
// Import this after everything else:
// This will put the CSS Modules at the end of the file.
import '../stylesheets/main.scss'
{
"author": {
"name": "Matthieu Oger",
"url": "solarsailer.net"
},
"scripts": {
"start": "webpack-dev-server --inline",
"build:dev": "webpack",
"build:prod": "webpack -p --env.production",
"test": "standard | snazzy"
},
"dependencies": {
"normalize.css": "^5.0.0",
"preact": "^8.2.1"
},
"devDependencies": {
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-es2016": "^6.24.1",
"babel-preset-es2017": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^2.1.2",
"node-sass": "^4.5.3",
"postcss-loader": "^2.0.6",
"sass-loader": "^6.0.6",
"snazzy": "^7.0.0",
"standard": "^10.0.2",
"webpack": "^3.0.0",
"webpack-dev-server": "^2.5.0"
},
"standard": {
},
"babel": {
"plugins": [
[
"transform-react-jsx",
{
"pragma": "h"
}
]
]
}
}
const path = require('path')
const autoprefixer = require('autoprefixer')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// -------------------------------------------------------------
// Constants.
// -------------------------------------------------------------
// http://browserl.ist/?q=last+3+versions%2C+not+ie+%3C+9%2C+iOS+%3E%3D+9%2C+Safari+%3E%3D+9%2C+Android+%3E%3D+4
const BROWSERS_SUPPORT = [
'last 3 versions',
'not ie < 9',
'iOS >= 9',
'Safari >= 9',
'Android >= 4'
]
// -------------------------------------------------------------
// CSS rules.
// -------------------------------------------------------------
// Loaders.
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: true
}
}
const cssModulesLoader = {
loader: 'css-loader',
options: {
sourceMap: true,
// e.g.: name__3UzfJ
modules: true,
localIdentName: '[local]__[hash:base64:5]'
}
}
const autoprefixerLoader = {
loader: 'postcss-loader', // For autoprefixer.
options: {
sourceMap: true,
plugins: [
autoprefixer({browsers: BROWSERS_SUPPORT})
]
}
}
const sassLoader = {
loader: 'sass-loader',
options: {
sourceMap: true
}
}
// Rulesets.
// If a CSS file contains the `.module` extension, we will pass it to the
// "CSS Modules" rules. Otherwise, it'll just be a global stylesheet.
//
// "CSS Modules" is a spec that pre/postfix CSS rules with a custom hash to
// make them local to an element.
// https://github.com/css-modules/css-modules
const cssRules = {
test: /\.scss$/,
exclude: /\.module\.scss$/,
use: ExtractTextPlugin.extract({
use: [
cssLoader,
autoprefixerLoader,
sassLoader
]
})
}
const cssModulesRules = {
test: /\.module\.scss$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
use: [
cssModulesLoader,
autoprefixerLoader,
sassLoader
]
})
}
// -------------------------------------------------------------
// Babel rules.
// -------------------------------------------------------------
const babelRules = {
test: /\.js$/,
exclude: [
path.resolve(__dirname, 'node_modules')
],
use: [{
loader: 'babel-loader',
options: {
presets: [
'es2015',
'es2016',
'es2017',
'react'
],
plugins: [
'transform-object-rest-spread'
]
}
}]
}
// -------------------------------------------------------------
// Helpers.
// -------------------------------------------------------------
function getFolderPath () {
return path.resolve(__dirname, 'dist')
}
function getExt (ext, isProd = false) {
return isProd ? '.min' + ext : ext
}
// -------------------------------------------------------------
// Module.
// -------------------------------------------------------------
module.exports = (env = {}) => {
const isProd = env.production
const config = {
entry: `./scripts/manifest.js`,
output: {
filename: 'js/site' + getExt('.js', isProd),
path: getFolderPath()
},
module: {
rules: [
cssModulesRules,
cssRules,
babelRules
]
},
plugins: [
new ExtractTextPlugin('css/site' + getExt('.css', isProd))
],
devtool: 'source-map',
devServer: {
port: 8084,
stats: 'errors-only'
}
}
return config
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment