Webpack

Ali Arafati

@CitizenOfTheWeb

Webpack

Frontend development

Webpack

ESM & HTTP2

Let's go back

Legacy

 

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

Jose Aguinaga

https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f

How does it work?

Babel?

Webpack Options

module

resolve

plugins

 

...rest

module

module

import content from './example.txt'

console.log(content); // Hey Alice
module.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

resolve

resolve

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

plugins

Html Webpack Plugin

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

ProfilingPlugin

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.debug.ProfilingPlugin({
      outputPath: 'profileEvents.json'
    });
  ],
};

https://webpack.js.org/plugins/profiling-plugin/

webpack.config.js

Webpack Bundle Analyzer

const BundleAnalyzerPlugin = 
    require('webpack-bundle-analyzer')
        .BundleAnalyzerPlugin;
 
module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}

https://www.npmjs.com/package/webpack-bundle-analyzer

webpack.config.js

Code Splitting

caching

faster rebuild

faster load time

more fine-grained control (sourcemaps)

old vs new

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

Performance

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

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

happypack || parallel-webpack || ...

Last remark

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

More

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

Questions

Made with Slides.com