Christopher Bloom, @illepic
cbloom@phase2technology.com
Follow along: github.com/illepic/webpack-intro
Every project we build must juggle dozens, hundreds, even thousands of frontend assets, combined in different ways and dependent on each other in complex relationships.
Today’s websites are evolving into web apps:
More and more JavaScript is in a page.
You can do more stuff in modern browsers.
Fewer full page reloads → even more code in a page.
As a result there is a lot of code on the client side!
A big code base needs to be organized. Module systems offer the option to split your code base into modules.
Many of the things we build are actually SPAs where a content management system (Drupal) acts as our asset pipeline, minifier, and initial loader. Like:
Juggling when/how these assets load can be tricky.
The good news is that we've naturally built Webpack already kinda!
Using Grunt/Gulp
A little differently.
On every project.
smart-slider.js
import sliderLibrary from 'big-ass-slider';
import {adclicks} from '../components/analytics-library-we-wrote';
require('./slider-custom-styles.scss');
export default class slider {
return sliderLibrary.render().onClick( () => {adclicks.fire();});
}
import $ from 'jquery';
import ourSlider from '../components/smart-slider';
$('#should-i-use-a-slider').html(ourSlider());
elegant-product-page.js
/* Minified jQuery library in ES5 */
/* Minified slider library in ES5 */
/* Minified adclick library in ES5 */
$('#should-i-use-a-slider').html(ourSlider());
Resulting bundle.js
/* Minified Bootstrap css */
.custom-slider { background: blue; }
.custom-slider--adclicks { color: red; }
Resulting bundle.css
npm init
npm install webpack webpack-cli --save-dev
touch index.js
Create webpack.config.js
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: __dirname
}
};
Run it
A
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: __dirname
}
};
Starting point to figure out how to bundle
The resulting bundle of all our code
"Where we are right now"
We haven't written any js yet, why do we now have a bundle.js file?
1. Toss in an index.html that references bundle.js
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<img id="doit" src="https://i.imgur.com/2EXEB4s.png"/>
<script src="bundle.js"></script>
</body>
</html>
2. Let's install jQuery because why not
npm install jquery --save
3. Write js that looks familiar: index.js
var $ = require('jquery');
$(document).ready(function() {
$('#doit').click(function() {
alert("DON'T LET YOUR DREAMS BE DREAMS");
});
});
4. Now webpack it
B
1. Write ES6 module syntax: components/doit.js
2. Require and use in index.js
C
1. Install "style loaders"
npm install style-loader css-loader --save-dev
2. Add the "loaders" for css to webpack.config.js.
Processes from bottom to top:
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
},
]
}
import $ from 'jquery';
import './doit.css';
export default {
labeoufFlex() {
$(document).ready(() => {
// ...
3. Require css files from within js:
components/doit.js.
D
4. Run `webpack`
1. Install sass-loader
npm install node-sass sass-loader --save-dev
2. Add the sass-loader to webpack.config.js
// ...
{
test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader' },
]
},
import $ from 'jquery';
import './doit.scss';
export default {
labeoufFlex() {
$(document).ready(() => {
//...
3. Require scss files from within js, run `webpack`
E
Webpack does generate standalone CSS files with the extract-text-webpack plugin
1. Install webpack-dev-server
npm install webpack-dev-server --save-dev
2. We'll run via npm, add to package.json:
// ...
"scripts": {
...
"wds": "webpack-dev-server"
},
// ...
devServer: {
historyApiFallback: true,
hot: true,
inline: true,
progress: true,
contentBase: path.resolve(__dirname),
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
// ...
3. Update webpack.config.js
4. Run `npm wds`
5. Visit localhost:8080/webpack-dev-server/
6. Change files
F
module.exports = {
entry: {
pageA: path.resolve(__dirname, 'pageA'),
pageB: path.resolve(__dirname, 'pageB'),
},
output: {
path: path.join(__dirname, "js"),
filename: "[name].bundle.js",
chunkFilename: "[id].chunk.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'commons',
minChunks: 2,
}),
]
};
1. Update webpack.config.js
2. See file structure here:
https://github.com/illepic/webpack-intro/tree/master/pres/G
F
http://bensmithett.com/smarter-css-builds-with-webpack/