Search code examples
javascriptwebpackbabel-loader

How to compile a js file as library using webpack and babel


Hi how do I compile a single js class file as library using webpack to generate an output that can be included in script tag

<script src='demo/demo.js'></script>

and also an output that can be import

import demo from 'demo'


Solution

  • If you want to use the demo library in different environments such as AMD, CommonJS, Nodejs. You need to use output.library option with its type set to 'umd'.

    Besides, we need to set output.globalObject to option to 'this'

    When targeting a library, especially the libraryTarget is 'umd', this option indicates what global object will be used to mount the library. To make UMD build available on both browsers and Node.js, set output.globalObject option to 'this'.

    An example:

    demo/src/demo.js:

    export class Demo {
      sayHello() {
        console.log("hello!");
      }
    }
    

    demo/webpack.config.js:

    const path = require("path");
    
    module.exports = {
      entry: "./src/demo.js",
      output: {
        path: path.resolve(__dirname, "lib"),
        filename: "demo.js",
        library: {
          name: "demo",
          type: "umd",
        },
        globalObject: "this",
      },
      mode: "development",
      module: {
        rules: [
          {
            test: /\.m?js$/,
            exclude: /node_modules/,
            use: {
              loader: "babel-loader",
              options: {
                presets: ["@babel/preset-env"],
              },
            },
          },
        ],
      },
    };
    

    demo/package.json:

    {
      "name": "demo",
      "version": "1.0.0",
      "main": "lib/demo.js",
      "devDependencies": {
        "@babel/core": "^7.15.0",
        "@babel/preset-env": "^7.15.0",
        "babel-loader": "^8.2.2",
        "webpack": "^5.51.1",
        "webpack-cli": "^4.8.0"
      }
    }
    

    Consumer side

    Use the demo library in the browser by script tag:

    index.html:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    
    <body>
      <script src='./demo/lib/demo.js'></script>
      <script>
        window.onload = () => {
          const { Demo } = window.demo;
          const demo = new Demo()
          demo.sayHello();
        }
      </script>
    </body>
    
    </html>
    

    Use the demo in index.js file by ES6 import syntax.

    index.js:

    import { Demo } from "./demo/lib/demo";
    
    const d = new Demo();
    d.sayHello();
    

    Consumer side webpack.config.js:

    const path = require("path");
    
    module.exports = {
      entry: "./index.js",
      output: {
        path: path.resolve(__dirname),
        filename: "index-bundled.js",
      },
      mode: "development",
      module: {
        rules: [
          {
            test: /\.m?js$/,
            exclude: /node_modules/,
            use: {
              loader: "babel-loader",
              options: {
                presets: ["@babel/preset-env"],
              },
            },
          },
        ],
      },
    };
    

    After generating the index-bundled.js file, run node index-bundled.js. Output:

    ⚡  node index-bundled.js 
    hello!