Webpack

Ali Arafati

@CitizenOfTheWeb

Webpack

Frontend development

Webpack

ESM & HTTP2

How it feels to learn JavaScript in 2016

@Jose Aguinaga

https://hackernoon.com/d3a717dd577f

The pain

<!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

2010

https://bitsofco.de/async-vs-defer/

<!DOCTYPE html>
<html lang="en">
<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>
<!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

Grunt

Gulp

Modules

var server = require("./server");
var constants = require("./constants");

server.listen(constants.port);

NodeJS

Browser

var jQuery = require("./libs/jQuery.js");

jQuery(function() {
  // do something
})();
<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="stylesheet" href="./bundle.css">
</head>
<body>
  <script src="./bundle.js"></script>
</body>
</html>
index.html
## What was the pain?

* keep dependencies up to date
* order of things
* non-modular
* dead code
* separation of resources
* hard to configure

## new tools

* require.js
* browserify
* rollup
* webpack

How does it work?

import './buggy.js';
import './none-existence.css';
import foo from '!!?none-sense?!!';

console.log(foo?.bar?.baz?.());

Webpack Options

const {
  resolve,
  module,
  plugins,
  ...rest
} = webpackConfiguration;

https://webpack.js.org/configuration/

resolve

https://nodejs.org/api/modules.html

import components from './components';
/.../projects/index.js
/.../projects/components/
/.../projects/components.js
/.../projects/components/package.json
/.../projects/components/index.js

MISS

HIT

MISS

HIT

https://nodejs.org/api/modules.html

import graphql from 'graphql';
/.../projects/index.js
/.../projects/node_modules/graphql/package.json
{
  "main": "lib/index.js",
  "module": "src/index.mjs"
}
/.../projects/node_modules/graphql/lib/index.js
/.../projects/node_modules/graphql/

HIT

HIT

module.exports = {
  resolve: {
    modules: [
      "node_modules",
      path.resolve(__dirname, "app")
    ],
    alias: {
      "react": "/secret-folder/react-evil.js",
    }
  },
};
webpack.config.js

module

module.exports = {
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        include: [
          path.resolve(__dirname, 'app')
        ],
        exclude: [
          path.resolve(__dirname, 'app/demo')
        ],
        loader: 'babel-loader',
        options: {
          presets: ['env'],
        },
      },
    ],
  },
};
webpack.config.js

Loader

plugins

const HtmlWebpackPlugin = 
  require('html-webpack-plugin');

 
module.exports = {
  plugins: [
    new HtmlWebpackPlugin()
  ]
}
webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
                               .BundleAnalyzerPlugin;
 
module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();

moule.exports = smp.wrap({
  // webpack config here
});
const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.debug.ProfilingPlugin({
      outputPath: 'profileEvents.json'
    });
  ],
};
node --inspect-brk ./node_modules/webpack/bin/webpack.js

Debugger listening on ws://127.0.0.1:9229/c624201a-250f-416e-a018-300bbec7be2c
For help see https://nodejs.org/en/docs/inspector

https://webpack.js.org/contribute/debugging/

Code Splitting

https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization/

caching

faster rebuild

faster load time

more fine-grained control (sourcemaps)

import FaceDetection from './lib/face-detection';

export default async (image) => {
  return await FaceDetection.detect(image);
};
export default async (image) => {
  const FaceDetection = await import('./lib/face-detection');

  return await FaceDetection.detect(image);
};
module.exports = {
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendors',
      chunks: ['main'],
      minChunks(module) {
        const context = module.context;
    
        return (
          context && 
          context.includes('node_modules')
        );
      },
    }),
  ],
}
webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          chunks: "all"
          name: "vendors",
          test: /[\\/]node_modules[\\/]/,
        }
      }
    }
  }
}
webpack.config.js

https://webpack.js.org/plugins/split-chunks-plugin/

 

https://medium.com/webpack/be739a861366

@Tobias Koppers

Performance

https://webpack.js.org/configuration/performance/

  • babel
    • transpile whats needed, don't generate
    • cache-loader
  • code splitting
  • sourcemaps
    • only source map the app, not the node modules
    • separate sourcemap files
  • no eval for large projects
  • no eslint-loader for large projects

More..

https://www.youtube.com/watch?v=jUTE7lmrS70

Questions

  • CLI tools
    • react-scripts (create-react-app)
    • angular-cli
    • vue-cli
    • next.js
Made with Slides.com