Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack long term caching

Tags:

webpack

Scenario

I'm attempting to use webpack to bundle my vendor scripts separately from my application scripts.

Attempt 1

index.js

var _ = require('lodash');
console.log(_)

webpack.config.js

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

var config = {
  entry: {
    vendor: ['lodash'],
    app: './index.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  plugins: [

    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: Infinity,
    }),

    new HtmlWebpackPlugin({
        filename: 'index.html',
        inject: true
    })
  ]
};

module.exports = config;

results

                         Asset       Size  Chunks             Chunk Names
       app.3437c5da57e0c6671675.js  145 bytes       0  [emitted]  app
    vendor.72c95e21a8d7096d53bc.js     428 kB       1  [emitted]  vendor
                        index.html  232 bytes          [emitted]

Now if I make a change to index.js

index.js

var _ = require('lodash');
console.log('changed index');
console.log(_)

results

                Asset       Size  Chunks             Chunk Names
   app.c724350371b50a9afeb2.js  177 bytes       0  [emitted]  app
vendor.0e76f9c86cbe02606265.js     428 kB       1  [emitted]  vendor
                    index.html  232 bytes          [emitted]

Both hashes change even though I only updated the index file.

The difference between the two vendor files is

vendor.72c95e21a8d7096d53bc.js

script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"app"}[chunkId]||chunkId) + "." + {"0":"3437c5da57e0c6671675"}[chunkId] + ".js";

vendor.0e76f9c86cbe02606265.js

script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"app"}[chunkId]||chunkId) + "." + {"0":"c724350371b50a9afeb2"}[chunkId] + ".js";

Attempt 2

After doing some research I found the article below which explains that webpack generates a chuck manifest that contains the chunk identifiers which is placed in the entry chunk. This explains the diff above. The solution is to extract the chuck manifest to a seperate file.

https://medium.com/@okonetchnikov/long-term-caching-of-static-assets-with-webpack-1ecb139adb95

index.js

var _ = require('lodash');
console.log(_)

webpack.config.js

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ChunkManifestPlugin = require('chunk-manifest-webpack-plugin');

var config = {
  entry: {
    vendor: ['lodash'],
    app: './index.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  plugins: [

    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: Infinity,
    }),

    new ChunkManifestPlugin({
      filename: "manifest.json",
      manifestVariable: "webpackManifest"
    }),

    new HtmlWebpackPlugin({
        filename: 'index.html',
        inject: true
    })
  ]
};

module.exports = config;

results

               Asset       Size  Chunks             Chunk Names
app.3437c5da57e0c6671675.js  145 bytes       0  [emitted]  app
             manifest.json   35 bytes          [emitted]
vendor.72c95e21a8d7096d53bc.js     428 kB       1  [emitted]  vendor

Now if I make a change to index.js

index.js

var _ = require('lodash');
console.log('changed index');
console.log(_)

results

               Asset       Size  Chunks             Chunk Names
app.c724350371b50a9afeb2.js  177 bytes       0  [emitted]  app
             manifest.json   35 bytes          [emitted]
vendor.0e76f9c86cbe02606265.js     428 kB       1  [emitted]  vendor

Once again both hashes change even though I only updated the index file.

This time however, there are no differences between the two vendor files

Questions

Is there a reason why the above scenario is not working or am I fundamentally approaching this problem incorrectly.

Is there is an easier way with webpack to achieve what I'm trying to do, because even if I get the step above working, I'll have to read the manifest and then inject it into my index.html page?

like image 409
kimsagro Avatar asked Sep 08 '15 02:09

kimsagro


People also ask

How long should webpack take?

Depending on the machine on which the build was launched, it tooks between 5 and 12 minutes. It is not possible to have a build that takes so long. webpack is not a slow bundler.

Does webpack has a cache?

Builds are cached in node_modules/. cache/webpack by default but this can be customized using the cacheDirectory , cacheLocation , or name cache options.

Why is webpack so slow?

Over the past eight years, webpack has become increasingly powerful. However, due to the additional packaging process, the building speed is getting slower as the project grows. As a result, each startup takes dozens of seconds (or minutes), followed by a round of build optimization.

What is long term caching?

Long term caching: It is to improve app loading time by keeping parts of the app on the client and avoid re-downloading them every time. Long term caching of your app assets is very important in improving load time.


1 Answers

It seems to be a problem with latest webpack version, please see open issue https://github.com/webpack/webpack/issues/1315

So for now you can't rely on [chunkhash], simplest solution is to use custom hash, something like <script src="vendor.js?v=001">, and change it on backend every time when you releasing.

like image 140
arturkin Avatar answered Sep 20 '22 11:09

arturkin