Search code examples
javascripttypescriptbundlees6-moduleswebpack-5

Not able to reference functions in webpack bundle


I am new to JS library development, and I am trying to do the following

  1. Create a library with TypeScript
  2. Create a bundle using webpack5
  3. Publish the library to npm
  4. Use the library in other projects by installing the npm package

I was successful in creating a bundle and uploading it to npm. The problem starts during step 4, when I install the package in a new project. Referencing functions from functions.ts does not work. However, when I import the library in script.js the code specified in index.ts is executed, and I can see the log output. What should I add to index.ts in order to be able to reference functions and classes from other files like functions.ts? The library will be used by front-end JS files. Thank you for your help in advance!

Project folder structure

root
|-dist
|  |-library.js
|
|-scr
|  |-functions.ts
|  |-index.ts
|
|-node_modules

I want to use index.ts as a file that would contain all references to the functions and classes. So, no logic in that file.

functions.ts

export function add(x: number, y: number): number {
  return x + y;
}

export function multiply(x: number, y: number): number {
    return x * y;
}

export function subtract(x:number, y:number): number {
    return x - y;
}

index.ts

import * as func from './functions'

var f1 = func.add(2, 5);
console.log('f1 - ' + f1);

var f2 = func.subtract(6, 2);
console.log('f2 - ' + f2);

var f3 = func.multiply(10, 2);
console.log('f3 - ' + f3);

export { func }

tsconfig.json

{
    "compilerOptions": {
      "target": "es6",
      "lib": ["es6", "dom"],
      "outDir": "src",
      "sourceMap": true,
      "strict": true,
      "module": "ES2015",
      "esModuleInterop": true
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules"]
  }

webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.ts',
  devtool: 'eval-source-map',
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: path.resolve(__dirname, 'node_modules'),
        include: [path.resolve(__dirname, 'src')]
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  output: {
    filename: 'library.js',
    path: path.resolve(__dirname, 'dist'),
    library: 'library',
    libraryTarget: 'umd',
    umdNamedDefine: true
  },
};

New project - script.js

import * as lib from './node_modules/library/dist/library.js'

var a = lib.library.add(2, 9); // -- error, library is not found.
console.log(a);

Solution

  • You are creating a umd library, which aren't as universal as they were when they were named such. You can import them and their code will run but it won't export as intended.

    You may want to use a different library type like module (currently experimental and requires enabling, see link for details) or commonjs-static.

    This can be done instead-of or in-addition-to a umd bundle. You can give webpack an array of config object to compile code multiple ways and configure your package.json with conditional exports for different module loaders.