Webpack
Ali Arafati
@CitizenOfTheWeb
Webpack
Frontend development
Webpack
ESM & HTTP2
## What was the pain?
* Keep dependencies up to date
* Order of things
* non-modular
* risk of dead code
* hard to configure
## Birth of new tools
* require.js
* browserify
* webpack<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="./jquery-ui.css">
<link rel="stylesheet" href="./main.css">
<link rel="stylesheet" href="./form.css">
</head>
<body>
<script src="./jQuery.js"></script>
<script src="./main-app.js"></script>
<script src="./fancy-sidenav.js"></script>
<script src="./form-validator.js"></script>
</body>
</html>index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!--Inject CSS-->
<!--End Inject CSS-->
</head>
<body>
<div id="root"></div>
<!--Inject JS-->
<!--End Inject JS-->
</body>
</html>index.html
https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f
module
resolve
plugins
...rest
import content from './example.txt'
console.log(content); // Hey Alicemodule.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
include: [
path.resolve(__dirname, 'app')
],
exclude: [
path.resolve(__dirname, 'app/demo')
],
loader: 'babel-loader',
options: {
presets: ['es2015'],
},
},
],
},
};module.exports = {
module: {
rules: [
{
test: /\.txt$/,
use: {
loader: path.resolve(
__dirname,
"./scripts/loader.js"
),
options: {
name: "Alice"
}
}
}
]
}
};Hey [name]!import { getOptions } from 'loader-utils';
export default function loader(source) {
const options = getOptions(this);
const content = source
.replace(/\[name\]/g, options.name);
return (
`export default ${JSON.stringify(content)}`
);
}https://webpack.js.org/configuration/
https://webpack.js.org/contribute/writing-a-loader/
webpack.config.js
webpack.config.js
example.txt
boo.js
loader.js
module.exports = {
resolve: {
modules: [
"node_modules",
path.resolve(__dirname, "app")
],
alias: {
"module": "new-module",
}
},
};// absolute imports
import sidenav from 'components/sidenav';
// relative imports
import sidenav from '../../../components';
https://webpack.js.org/configuration/
https://nodejs.org/api/modules.html
webpack.config.js
index.js
const HtmlWebpackPlugin =
require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin()
]
}https://webpack.js.org/plugins/html-webpack-plugin/
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>webpack.config.js
dist/index.html
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.debug.ProfilingPlugin({
outputPath: 'profileEvents.json'
});
],
};https://webpack.js.org/plugins/profiling-plugin/
webpack.config.js
const BundleAnalyzerPlugin =
require('webpack-bundle-analyzer')
.BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}https://www.npmjs.com/package/webpack-bundle-analyzer
webpack.config.js
caching
faster rebuild
faster load time
more fine-grained control (sourcemaps)
module.exports = {
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
chunks: ['main'],
minChunks(module) {
const context = module.context;
return (
context &&
context.includes('node_modules')
);
},
}),
],
}module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
chunks: "all"
name: "vendors",
test: /[\\/]node_modules[\\/]/,
}
}
}
}
}https://webpack.js.org/plugins/split-chunks-plugin/
Tobias Koppers https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
- It can result in more code being downloaded than needed.
- It’s inefficient on async chunks.
- It’s difficult to use.
- The implementation is difficult to understand.
webpack.config.js
webpack.config.js
https://webpack.js.org/configuration/performance/
happypack || parallel-webpack || ...
https://www.youtube.com/watch?v=jUTE7lmrS70