Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Configuration: A Webpack Story

Configuration: A Webpack Story

Fabian Buentello

May 23, 2019
Tweet

More Decks by Fabian Buentello

Other Decks in Programming

Transcript

  1. ABOUT ME ▸ Fabian Buentello ▸ Twitter: @initFabian ▸ Senior

    Frontend Developer at Dragos ▸ Former iOS Developer
  2. ▸ 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’
  3. 13 module.exports = { entry: './src/js/app.js', module: { rules: [

    {!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] };
  4. 17

  5. 24 JS Modules Loaders { test: /\.js$/, exclude: /node_modules/, loader:

    "babel-loader", options: { presets:[ '@babel/env', '@babel/preset-react' ] } } bundle.js
  6. 26 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:

    'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } bundle.js styleLoader(cssLoader(sassLoader(input)))
  7. 27 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:

    'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } bundle.js styleLoader(cssLoader(sassLoader(input)))
  8. 28 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:

    'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } bundle.js styleLoader(cssLoader(sassLoader(input)))
  9. 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)))
  10. 30 JS Modules Loaders { test: /\.(scss|css)$/, use: [ {loader:

    'style-loader'}, {loader: 'css-loader'}, {loader: 'sass-loader'}, ], } <style> !!" !$style> bundle.js
  11. 32 JS Modules Loaders { test: /\.js$/, exclude: /node_modules/, loader:

    "babel-loader", options: { presets:[ '@babel/env', '@babel/preset-react' ] } } bundle.js
  12. BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [

    {!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] };
  13. BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [

    {!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; ENTRY
  14. BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [

    {!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; OUTPUT
  15. 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
  16. BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [

    {!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS
  17. 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
  18. 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!!" }); } }
  19. 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!!" }); } }
  20. 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!!" }); } }
  21. 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!!" }); } }
  22. 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!!" }); } }
  23. 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!!" }); } }
  24. 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!!" }); } }
  25. BREAKDOWN: module.exports = { entry: './src/js/app.js', module: { rules: [

    {!!"}, {!!"}, {!!"}, {!!"} ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html' }) ] }; PLUGINS
  26. 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') );
  27. 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') );
  28. 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') );
  29. 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
  30. 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'
  31. 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({ !!" });
  32. 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)
  33. 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