webpack advanced application: creating a library

In addition to packaging applications, webpack can also be used to package JavaScript libraries. The following applies to library authors who want to simplify the packaging strategy.


Create a library

Suppose we are writing a small library called my math, which contains addition and subtraction.

The basic project structure may be as follows:

 |- webpack.config.js
 |- package.json
 |- /test // Test library
    |- index.html
 |- /src
   |- index.js

Initialize the project with npm, and then install webpack, webpack CLI and lodash:

npm init -y
npm install --save-dev webpack webpack-cli

src/index.js

export const add = (x, y) => x + y;

export const subtract = (x, y) => x - y;

webpack.config.js

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'myMath.js',
  },
};

In the above example, we will notify webpack to Src / index JS package to dist / mymath JS.


Export library

So far, everything should be the same as a packaged application. Here are the different parts - we need to pass output.library The configuration item exposes the content exported from the portal.

webpack.config.js

  const path = require('path');

  module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'myMath.js',
+     library: "myMath",
    },
  };

We exported myMath so that users can use it through script tags:

test/index.html

<script src="../dist/myMath.js"></script>
<script>
  myMath.add(1, 2);
</script>

Output ES module

This feature is still experimental and not fully supported, so make sure to enable it in advance experiments.outputModule . In addition, you can here Track development progress.

const path = require('path');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  experiments: {
    outputModule: true,
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    // filename: 'myMath.js', / / do not execute filename here
    library: 'myMath',
  },
};

Execute npx webpack

test/index.html

<script type="module">
  import { add } from '../dist/myMath.js'

  console.log(add(1, 2));
</script>

You can see the normal output


Output umd

However, it can only work by being referenced by script tags. It can't run in CommonJS, AMD and node JS, ES module, etc.

For a library author, we hope that it can be used in different environments and ways. Users should be able to use the packaged library through the following:

  • CommonJS module require:

    const myMath = require('myMath');
    // ...
    myMath.add(1, 2);
    
  • AMD module require:

    require(['myMath'], function (myMath) {
      // ...
      myMath.add(1, 2);
    });
    
  • script tag:

    <!DOCTYPE html>
    <html>
      ...
      <script src="https://example.org/myMath.js"></script>
      <script>
        // ...
        // global variable
        myMath.add(1, 2);
        // Properties mounted on window
        window.myMath.subtract(2, 2);
        // ...
      </script>
    </html>
    

We update output Library configuration item, set its type to 'umd':

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'myMath.js',
    library: {
      name: 'myMath',
      type: 'umd',
    },
    globalObject: 'this',
  },
};

output.globalObject

string = 'window'

When the output is library, especially when the libraryTarget is' UMD ', this option will determine which global object to use to mount the library. In order to build UMD in browser and node JS, output. JS should be The globalobject option is set to 'this'. For web like targets, the default is self.

Now webpack will package a library that can be used with CommonJS, AMD, and script tags.


Externalities depend on externalization

When we create a library, we may use some third-party libraries, such as loadsh

npm i loadsh -S

src/index.js

import _ from 'lodash';

export const add = (x, y) => _.add(x, y);

export const subtract = (x, y) => x - y;

Execute npx webpack and you will find that a large file is created. If you look at this file, you will see that lodash is also packaged into the code. In this scenario, we prefer to regard lodash as peer dependency. That is, the consumer should have installed lodash. Therefore, you can give up control of the external library and give control to the consumer using the library.

This can be done using the externals configuration:

webpack.config.js

  const path = require('path');

  module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'myMath.js',
      library: {
        name: "myMath",
        type: "umd"
      },
      globalObject: 'this',
    },
+   externals: {
+     lodash: {
+       commonjs: 'lodash',
+       commonjs2: 'lodash',
+       amd: 'lodash',
+       root: '_',
+     },
+   },
  };

This means that your library needs a dependency called lodash, which must exist and be available in the host environment.

package.json

{
  ...
  "main": "dist/myMath.js",
  ...
}

Publish npm publish

npm (III): release, update and discard of npm package

Tip

To expose the style sheets associated with the library, you should use MiniCssExtractPlugin . You can then use and load these style sheets as you would any other style sheet.

To be continued: [webpack create library] practical chapter

Keywords: Front-end npm Webpack package

Added by xnowandtheworldx on Mon, 20 Dec 2021 15:22:16 +0200