Webpack series - use of browser caching and Shimming

webpack and browser caching

We use webpack to package our modular application. Webpack will generate a deployable / dist directory, and then place the packaged content in this directory. As long as the contents in the / dist directory are deployed on the server, the client (usually the browser) can access the server's website and its resources. The last step to obtain resources is time-consuming, which is why browsers use a technology called caching. You can hit the cache to reduce network traffic and make the website load faster. However, if we do not change the file name of the resource when deploying the new version, the browser may think that it has not been updated and will use its cached version. Due to the existence of cache, it will be very difficult when you need to get new code.

[contenthash] will create a unique hash based on the resource content. When the resource content changes, [contenthash] will also change.

module.exports = {
    ...
    output: {
     filename: '[name].[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
      clean: true,
    },
};

Shimming's role

Shimming preset global variable

The webpack compiler can identify modules written in accordance with ES2015 module syntax, CommonJS or AMD specifications. However, some third parties (third-party libraries) may reference some global dependencies (such as $) in jQuery). Therefore, these libraries may also create some global variables that need to be exported. These "broken modules" are where shimming (preset dependency) works.

Global dependency is not recommended! The whole idea behind webpack is to make front-end development more modular. That is, it is necessary to write isolated modules with good well contained and independent of implicit dependencies (for example, global variables). Use these features only when necessary.

The lodash used before, for example, changes the module dependency in this application to a global variable dependency. To do this, you need to use the ProvidePlugin plug-in.

After using ProvidePlugin, you can access a variable to obtain a package in each module compiled by webpack. If webpack sees that this variable is used in the module, it will introduce the given package into the final bundle. Let's remove the import statement of lodash and provide it through the plug-in instead:

index.js

 function component() {
   const element = document.createElement('div');
​
   element.innerHTML = _.join(['Hello', 'webpack'], ' ');
​
   return element;
 }
​
 document.body.appendChild(component());

webpack.config.js

const path = require('path');
const webpack = require('webpack');
​
 module.exports = {
   entry: './src/index.js',
   output: {
     filename: 'main.js',
     path: path.resolve(__dirname, 'dist'),
   },
  plugins: [
    new webpack.ProvidePlugin({
      _: 'lodash',
    }),
  ],
};

What we essentially do is tell webpack that we have encountered at least one problem_ Variable, the lodash package is introduced and provided to the modules that need it.

You can also use ProvidePlugin to expose a single export in a module by configuring an "array path" (such as [module, child,... Children?]) Realize this function. Therefore, suppose that no matter where the join method is called, we will only get the join method provided in lodash.

index.js

function component() {
   const element = document.createElement('div');
​
​
   element.innerHTML = join(['Hello', 'webpack'], ' ');
​
   return element;
 }
​
 document.body.appendChild(component());

webpack.config.js

const path = require('path');
 const webpack = require('webpack');
​
 module.exports = {
   entry: './src/index.js',
   output: {
     filename: 'main.js',
     path: path.resolve(__dirname, 'dist'),
   },
   plugins: [
     new webpack.ProvidePlugin({
       join: ['lodash', 'join'],
     }),
   ],
 };

In this way, it can work well with tree shaking to remove other unused exports in the lodash library.

Fine grained Shimming changes this point

this of some modules refers to the module itself rather than the global window object

index.js

console.log(this)

Override this point by using imports loader

Install imports loader

npm install imports-loader --save-dev

webpack.config.js

const path = require('path');
  const webpack = require('webpack');
​
  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: require.resolve('index.js'),
          use: 'imports-loader?this=>window'
        }
      ]
    },
    plugins: [
      new webpack.ProvidePlugin({
        join: ['lodash', 'join']
      })
    ]
  };

Keywords: Javascript Front-end Webpack Cache

Added by tukon on Sat, 15 Jan 2022 05:42:32 +0200