Skip to content

agentschmitt/hard-source-webpack-plugin

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HardSourceWebpackPlugin

Build Status Build status

HardSourceWebpackPlugin is a plugin for webpack to provide an intermediate caching step for modules. In order to see results, you'll need to run webpack twice with this plugin: the first build will take the normal amount of time. The second build will be signficantly faster.

Install with npm install --save hard-source-webpack-plugin or yarn. And include the plugin in your webpack's plugins configuration.

// webpack.config.js
var HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

module.exports = {
  context: // ...
  entry: // ...
  output: // ...
  plugins: [
    new HardSourceWebpackPlugin()
  ]
}

You can optionally set where HardSource writes and reads its cache to and from, and the hash values that determine when it creates new caches.

new HardSourceWebpackPlugin({
  // Either an absolute path or relative to webpack's options.context.
  cacheDirectory: 'node_modules/.cache/hard-source/[confighash]',
  // Either an absolute path or relative to webpack's options.context.
  // Sets webpack's recordsPath if not already set.
  recordsPath: 'node_modules/.cache/hard-source/[confighash]/records.json',
  // Either a string of object hash function given a webpack config.
  configHash: function(webpackConfig) {
    // node-object-hash on npm can be used to build this.
    return require('node-object-hash')({sort: false}).hash(webpackConfig);
  },
  // Either false, a string, an object, or a project hashing function.
  environmentHash: {
    root: process.cwd(),
    directories: [],
    files: ['package-lock.json', 'yarn.lock'],
  },
}),

Options

cacheDirectory

The cacheDirectory is where the cache is written to. The default stores the cache in a directory under node_modules so if node_modules is cleared so is the cache.

The cacheDirectory has a field in it [confighash] that is replaced by the configHash option when webpack is started. The [confighash] field is here to help with changes to the configuration by the developer or by a script. For example if the same webpack configuration is used for the webpack cli tool and then the webpack-dev-server cli tool, they will generate different configuration hashes. webpack-dev-server adds plugins for its reloading features, and the default hash function produces a different value with those plugins added.

recordsPath

webpack produces records for the ids it uses for its internal objects that hard-source writes to disk. The recordsPath option in hard-source is the same option for webpack. Use it to make use of the [confighash] value as it also appears in cacheDirectory so that the records are stored next to the rest of the cache.

configHash

configHash turns a webpack configuration when a webpack instance is started and is used by cacheDirectory and recordsPath to build different caches for different webpack configurations.

Configurations may change how modules are rendered and so change how they appear in the disk cache hard-source writes. It is important to use a different cache per webpack configuration or webpack cli tool. webpack and webpack-dev-server for example needed separate caches, configHash and [confighash] in the cacheDirectory will create separate caches due to the plugins and configuration changes webpack-dev-server makes.

The default value for configHash is

configHash: function(webpackConfig) {
  return require('node-object-hash')({sort: false}).hash(webpackConfig);
}

This uses the npm node-object-hash module with sort set to false to hash the object. node-object-hash hashes as much as it can but may have issue with some plugins or plugins and loaders that load an additional configuration file like a babel rc file or postcss config. In those cases you can depend on node-object-hash and extend what it hashes to best cover those changes.

configHash can also be set to a string or it can be a function that generates a value based on other parts of the environment.

configHash: function() {
  return process.env.NODE_ENV + '-' process.env.BABEL_ENV;
}

environmentHash

When loaders, plugins, other build time scripts, or other dynamic dependencies change, hard-source needs to replace the cache to make sure the otuput is correct. The environmentHash is used to determine this. If the hash is different than a previous build, a fresh cache will be used.

The default object

environmentHash: {
  root: process.cwd(),
  directories: [],
  files: ['package-lock.json', 'yarn.lock']
}

hashes the lock files for npm and yarn. They will both be used if they both exist, or just one if only one exists. If neither file is found, the default will hash package.json and the package.json under node_modules.

You can disable the environmentHash by setting it to false. By doing this you will manually need to delete the cache when there is any dependency environment change.

Troubleshooting

Configuration changes are not being detected

hard-source needs a different cache for each different webpack configuration. The default configHash may not detect all of your options to plugins or other configuration files like .babelrc or postcss.config.js. In those cases a custom configHash is needed hashing the webpack config and those other values that it cannot normally reach.

Hot reloading is not working

webpack-dev-server needs a different cache than webpack or other webpack cli tools. Make sure your cacheDirectory and configHash options are hashing the changes webpack-dev-server makes to your webpack config. The default hard-source values should do this.

Multiple webpack processes at the same time are getting bad results

If you are using multiple webpack instances in separate processes make sure each has its own cache by changing cacheDirectory or configHash.

Rebuilds are slower than the first build during dev-server

This is can be due to module context dependencies. require.context or loaders that watch folders use this webpack feature so webpack rebuilds when files or folders are added or removed from these watched directories. Be careful about using require.context or context aware loaders on folders that contain a lot of items. Both require.context and context loaders depend on those folders recursively. hard-source hashes every file under a require.context or context loader folder to detect when the context has changed and dependent modules are rebuilt.

webpack-dev-server build loops continuously

Make sure you don't have a require.context or context loader on the root of your project. Such a context module means webpack is watching the hard source cache and when the cache is written after a build, webpack will start a new build for that module. This normally does not happen with webpack-dev-server because it writes the built files into memory instead of the disk. hard-source cannot do that since that would defeat its purpose as a disk caching plugin.

Please contribute!

If you encounter any issues or have an idea for hard-source-webpack-plugin could be better, please let us know.