Share
Embed
Configuration: A Webpack Story
Fabian Buentello
May 23, 2019
Transcript
86 slides
-
ABOUT ME ▸ Fabian Buentello ▸ Twitter: @initFabian ▸ Senior
Frontend Developer at Dragos ▸ Former iOS Developer -
task readFrom('path/to/src') doSomething() moveTo('path/to/dist') task readFrom('path/to/src') doSomething() moveTo('path/to/dist') task readFrom('path/to/src')
doSomething() moveTo('path/to/dist') task readFrom('path/to/src') doSomething() moveTo('path/to/dist') -
▸ Created by Tobias Koppers (@wSokra) ▸ Created: 2012 OSCON
2014: How Instagram.com Works; Pete Hunt Fun Fact: Webpack is actually a fork of ‘modules-webmake’ -
13 module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; -
24 JS Modules Loaders { test: /\.js$/, exclude: /node_modules/, loader:
"babel-loader", options: { presets:[ '@babel/env', '@babel/preset-react' ] } } bundle.js -
26 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:
'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } bundle.js styleLoader(cssLoader(sassLoader(input))) -
27 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:
'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } bundle.js styleLoader(cssLoader(sassLoader(input))) -
28 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:
'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } bundle.js styleLoader(cssLoader(sassLoader(input))) -
29 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:
'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } <style> !!" !$style> bundle.js styleLoader(cssLoader(sassLoader(input))) -
30 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:
'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } <style> !!" !$style> bundle.js -
32 JS Modules Loaders { test: /\.js$/, exclude: /node_modules/, loader:
"babel-loader", options: { presets:[ '@babel/env', '@babel/preset-react' ] } } bundle.js -
34 JS Modules Loaders { test: /\.(eot|woff|woff2|ttf|svg)$/, use: [ {
loader: 'url-loader' } ] } bundle.js -
35 JS Modules Loaders { test: /\.(eot|woff|woff2|ttf|svg)$/, use: [ {
loader: 'url-loader' } ] } bundle.js -
38 JS Modules Loaders dist { test: /\.(png|svg|jpg|gif)$/, use: [
'file-loader' ] } bundle.js -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; ENTRY -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; OUTPUT -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; WEBPACK DEV SEVER $ npm install webpack-dev-server --save-dev -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS entryOption run watchRun beforeCompile compile done Compilation Lifecycle -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS class ExampleWebpackPlugin { apply(compiler) { compiler.hooks.emit.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.run.tap('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.done.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); } } -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS class ExampleWebpackPlugin { apply(compiler) { compiler.hooks.emit.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.run.tap('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.done.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); } } -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS class ExampleWebpackPlugin { apply(compiler) { compiler.hooks.emit.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.run.tap('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.done.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); } } -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS class ExampleWebpackPlugin { apply(compiler) { compiler.hooks.emit.tapAsync(‘ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.run.tap('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.done.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); } } -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS class ExampleWebpackPlugin { apply(compiler) { compiler.hooks.emit.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.run.tap('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.done.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); } } -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS class ExampleWebpackPlugin { apply(compiler) { compiler.hooks.emit.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.run.tap('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.done.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); } } -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS class ExampleWebpackPlugin { apply(compiler) { compiler.hooks.emit.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.run.tap('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); compiler.hooks.done.tapAsync('ExampleWebpackPlugin', (!!") !% { !& some code gets executed!!" }); } } -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS !& app.js !!" render( <App!', document.getElementById('root') ); -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS !& app.js !!" render( <App!', document.getElementById('root') ); -
BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [
{!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS !!!( src/index.html !!) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> !$head> <body> <div id="root">!$div> !$body> !$html> !& app.js !!" render( <App!', document.getElementById('root') ); -
GOOD PRACTICE ▸ Keep build system up-to-dated ▸ Configuration files
are not programs ▸ Separate configurations by environment ▸ DRY can hurt you, use webpack-merge wisely ▸ Keep configurations together ▸ Get rid of .babelrc ▸ Avoid configurations in npm scripts if possible: webpack !*hot !*progress !*mode development !*config webpack.dev.js -
NOTABLE PLUGINS ▸ Case Sensitive Paths !& src/components/header.js import Header
from './components/Header' -
NOTABLE PLUGINS ▸ Case Sensitive Paths !& src/components/header.js import Header
from './components/Header' -
NOTABLE PLUGINS ▸ Case Sensitive Paths var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var webpackConfig = { plugins: [ new CaseSensitivePathsPlugin() !& other plugins !!" ] !& other webpack config !!" } !& src/components/header.js import Header from './components/Header' -
MEASURE: 70 SPEED MEASURE PLUGIN $ npm install speed-measure-webpack-plugin --save-dev
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); const smp = new SpeedMeasurePlugin(); const webpackConfig = smp.wrap({ !!" }); -
SPEED TIPS ▸ Avoid anything that has the word “minimize”
▸ Use ‘style-loader’ ▸ Split node_modules into a vendor bundle(splitChunks) ▸ Use Hot Module Replacement(HMR) -
import { hot } from 'react-hot-loader/root'; const App = !+
!, export default hot(App); -
MEASURE: 75 SIZE "package": "webpack !*config webpack.production.js", "package:profile": "webpack !*config
webpack.production.js !*profile !*json > stats.json", stats.json $ npm run package:profile