[Laracasts.com] Webpack for Everyone [ENG, 2017]
Looks like that video for free:
https://laracasts.com/series/webpack-for-everyone
MySRC (many branches):
https://bitbucket.org/marley-nodejs/webpack-for-everyone/
Prepare Environment
$ mkdir -p /projects/js/webpack/webpack-for-everyone/
$ docker run -it \
-p 80:8080 -p 1337:1337 -p 3000:3000 -p 4000:4000 -p 5000:5000 -p 6000:6000 -p 7000:7000 -p 8000:8000 -p 9000:9000 \
--name webpack-for-everyone \
-v /projects/js/webpack/webpack-for-everyone/:/project \
node \
/bin/bash
# apt-get update
# apt-get install -y vim git
01-Zero-Config-Webpack-Compilation
# cd /project
# npm init -y
$ npm i -g webpack
-- ("webpack": "^2.6.1")
# npm install --save-dev webpack
# mkdir -p src
# vi src/main.js
alert('main');
# vi index.html
<html>
<head>
<title></title>
</head>
<body>
<h1>Hello World!</h1>
<script src="dist/bundle.js"></script>
</body>
</html>
# vi package.json
"scripts": {
"build": "webpack src/main.js dist/bundle.js",
"watch": "npm run build -- --watch"
},
# npm run build
# npm run watch
02-A-Dedicated-Configuration-File
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
# vi package.json
"scripts": {
"build": "webpack",
"watch": "npm run build -- --watch"
},
# npm run build
# npm run watch
03-Modules-Are-Just-Files
# vi src/main.js
import notification from './Notification';
notification.log('here we go');
notification.announce('here we go as an alert');
# vi src/Notification.js
function announce (message) {
alert(message);
}
function log (message) {
console.log(message);
}
export default {
announce: announce,
log: log
};
# npm run watch
04-Loaders-Are-Transformers
# npm install --save-dev css-loader
# npm install --save-dev style-loader
# vi src/main.js
require('./main.css');
# vi src/main.css
# vi src/main.css
body {
background: red;
}
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
# npm run build
05-ES2015-Compilation-With-Babel
http://babeljs.io/docs/setup/#installation
# npm install --save-dev babel-loader babel-core
http://babeljs.io/docs/plugins/
# npm install --save-dev babel-cli babel-preset-es2015
# echo '{ "presets": ["es2015"] }' > .babelrc
# vi src/main.js
class Form {
constructor(){
alert('Yay Form classes are great no matter what JS developers say!');
let numbers = [5, 10, 15].map(number => number * 2);
console.log(numbers);
}
}
new Form();
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
}
};
# npm run build
06-Minification-and-Environments
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# vi package.json
"scripts": {
"dev": "webpack",
"prod": "NODE_ENV=production webpack",
"watch": "npm run build -- --watch"
},
# npm run dev
# npm run prod
07-Sass-Compilation
# npm install --save-dev sass-loader node-sass
# vi src/main.js
require('./main.scss');
# vi src/main.scss
$primary: green;
body {
background: $primary;
}
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# npm run dev
08-Extract-CSS-To-A-Dedicated-File
https://github.com/webpack-contrib/extract-text-webpack-plugin
# npm install --save-dev extract-text-webpack-plugin
https://webpack.js.org/plugins/loader-options-plugin/
# vi src/main.js
alert('empty');
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: {
app: ['./src/main.js',
'./src/main.scss']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
new ExtractTextPlugin('[name].css'),
new webpack.LoaderOptionsPlugin({
minimize: inProduction
})
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# npm run dev
# npm run prod
09-The-Relative-CSS-Url-Conundrum
https://github.com/webpack-contrib/css-loader
# npm install --save-dev file-loader
# vi src/main.scss
.test {
background: url('./images/cat.jpg');
}
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: {
app: ['./src/main.js',
'./src/main.scss']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
loader: 'file-loader',
options: {
name: 'images/[name].[hash].[ext]'
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
new ExtractTextPlugin('[name].css'),
new webpack.LoaderOptionsPlugin({
minimize: inProduction
})
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# npm run dev
10-Strip-Unused-CSS-Automatically
https://github.com/webpack-contrib/purifycss-webpack
# npm i -D purifycss-webpack purify-css
# vi index.html
<html>
<head>
<title></title>
</head>
<body>
<h1>Hello World!</h1>
<div class="two">Hello</div>
<script src="dist/bundle.js"></script>
</body>
</html>
# vi src/main.scss
.one {
background: red;
}
.two {
background: green;
}
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const PurifyCSSPlugin = require('purifycss-webpack');
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: {
app: ['./src/main.js',
'./src/main.scss']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
loader: 'file-loader',
options: {
name: 'images/[name].[hash].[ext]'
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
new ExtractTextPlugin('[name].css'),
new PurifyCSSPlugin({
// paths: glob.sync(path.join(__dirname, 'app/*.html')),
paths: glob.sync(path.join(__dirname, 'index.html')),
minimize: inProduction
}),
new webpack.LoaderOptionsPlugin({
minimize: inProduction
})
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# npm run dev
11-File-Hashing
# npm install jquery -D
https://github.com/johnagan/clean-webpack-plugin
# npm install --save-dev clean-webpack-plugin
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const PurifyCSSPlugin = require('purifycss-webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: {
app: ['./src/main.js',
'./src/main.scss'],
vendor: ['jquery']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
loader: 'file-loader',
options: {
name: 'images/[name].[hash].[ext]'
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new ExtractTextPlugin('[name].css'),
new PurifyCSSPlugin({
// paths: glob.sync(path.join(__dirname, 'app/*.html')),
paths: glob.sync(path.join(__dirname, 'index.html')),
minimize: inProduction
}),
new webpack.LoaderOptionsPlugin({
minimize: inProduction
})
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# npm run dev
12-Webpack-Manifests
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const PurifyCSSPlugin = require('purifycss-webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: {
app: ['./src/main.js',
'./src/main.scss'],
vendor: ['jquery']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
loader: 'file-loader',
options: {
name: 'images/[name].[hash].[ext]'
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new ExtractTextPlugin('[name].css'),
new PurifyCSSPlugin({
// paths: glob.sync(path.join(__dirname, 'app/*.html')),
paths: glob.sync(path.join(__dirname, 'index.html')),
minimize: inProduction
}),
new webpack.LoaderOptionsPlugin({
minimize: inProduction
}),
function(){
this.plugin('done', stats => {
require('fs').writeFileSync(
path.join(__dirname, 'dist/mainfest.json'),
JSON.stringify(stats.toJson().assetsByChunkName)
);
});
}
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# npm run dev
13-Automatic-Image-Optimization
https://github.com/thetalecrafter/img-loader
# npm install --save-dev img-loader
# vi webpack.config.js
var webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const PurifyCSSPlugin = require('purifycss-webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
var inProduction = (process.env.NODE_ENV === 'production');
module.exports = {
entry: {
app: ['./src/main.js',
'./src/main.scss'],
vendor: ['jquery']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.css$/,
use: 'css-loader'
},
{
test: /\.s[ac]ss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
loaders: [
{
loader: 'file-loader',
options: {
name: 'images/[name].[hash].[ext]'
}
},
'img-loader'
]
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" }
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new ExtractTextPlugin('[name].css'),
new PurifyCSSPlugin({
// paths: glob.sync(path.join(__dirname, 'app/*.html')),
paths: glob.sync(path.join(__dirname, 'index.html')),
minimize: inProduction
}),
new webpack.LoaderOptionsPlugin({
minimize: inProduction
}),
function(){
this.plugin('done', stats => {
require('fs').writeFileSync(
path.join(__dirname, 'dist/mainfest.json'),
JSON.stringify(stats.toJson().assetsByChunkName)
);
});
}
]
};
if (inProduction){
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
# npm run dev