Generating the JavaScript Bundle

First, let’s walk through how Gatsby generates the JavaScript runtime that performs rehydration after the initial HTML is loaded, and all client-side work thereafter (such as the instantaneous loading of subsequent pages). There are several files involved in the process.

The entry point is the build-javascript.ts file in Gatsby (located in the src/commands directory), which dynamically generates a Webpack configuration by invoking src/utils/webpack.config.js. Depending on which stage is being handled (build-javascriptbuild-htmldevelop, or develop-html), this can result in significantly different configurations. For example, consider the Webpack configuration generated for the build-javascript stage, reproduced here with comments:

{
  entry: {
    app: `.cache/production-app`
  },
  output: {
    // e.g. app-2e49587d85e03a033f58.js
    filename: `[name]-[contenthash].js`,
    // e.g. component---src-blog-2-js-cebc3ae7596cbb5b0951.js
    chunkFilename: `[name]-[contenthash].js`,
    path: `/public`,
    publicPath: `/`
  },
  target: `web`,
  devtool: `source-map`,
  mode: `production`,
  node: {
    ___filename: true
  },
  optimization: {
    runtimeChunk: {
      // e.g. webpack-runtime-e402cdceeae5fad2aa61.js
      name: `webpack-runtime`
    },
    splitChunks: { 
      chunks: `all`,
      cacheGroups: {
        // disable webpack's default cacheGroup
        default: false,
        // disable webpack's default vendor cacheGroup
        vendors: false,
        // Create a framework bundle that contains React libraries
        // They hardly change so we bundle them together
        framework: {},
        // Big modules that are over 160kb are moved to their own file to
        // optimize browser parsing & execution
        lib: {},
        // All libraries that are used on all pages are moved into a common
        // chunk
        commons: {},
        // When a module is used more than once we create a shared bundle to
        // save user's bandwidth
        shared: {},
        // All CSS is bundled into one stylesheet
        styles: {}
      },
      // Keep maximum initial requests to 25
      maxInitialRequests: 25,
      // A chunk should be at least 20kb before using splitChunks
      minSize: 20000
    },
    minimizers: [
      plugins.minifyJs(),
      plugins.minifyCss(),
    ]
  }
  plugins: [
    // A custom webpack plugin that implements logic to write out 
    // chunk-map.json and webpack.stats.json
    plugins.extractStats(),
  ]
}

The splitChunks portion of this Webpack configuration, which removes loaders, rules, and other output, is the most important part, because it contributes to how code splitting occurs in Gatsby and how the most optimized bundle is generated. Gatsby tries to create generated JavaScript files that are as granular as possible (“granular chunks”) by deduplicating all modules. Once Webpack is finished compiling the bundle, it ends up with a few different bundles, which are accounted for in Table 14-4.

FilenameDescription
app-[contenthash].jsThis bundle is produced from production-app.js and is configured in webpack.config.js.
webpack-runtime-[contenthash].jsThis bundle contains webpack-runtime as a separate bundle (configured in the optimization section) and is usually required with the app bundle.
framework-[contenthash].jsThis bundle contains React and as a separate bundle improves cache hit rate, because the React library is seldom updated as frequently.
commons-[contenthash].jsLibraries used on every Gatsby page are bundled into this file so that they are downloaded only once.
component—[name]-[contenthash].jsThis represents a separate bundle for each page to enable code splitting.

Posted

in

,

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *