skip to Main Content

I am pretty new to webpack and I am wondering if it possible to conduct a pretty simple experiment. I want to bundle the following typescript code:

const myFunc = () => {
    return {
        a: () => {
            console.log("hello from a");
        },
        b: () => {
            console.log("hello from b");
        },
    };
};

export default myFunc;

My current webpack config looks like this:

const path = require("path");
module.exports = { 
    entry: "./test/index.ts", 
    mode: "production", 
    resolve: { 
        extensions: [".ts"], 
    }, 
    output: { 
        filename: "bundle.js", 
        path: path.resolve(__dirname, "./build"), 
    }, 
}; 

When I run webpack --config webpack.config.js I just get back an empty file in for bundle.js. However what I want to happen is to get an IIFE that returns an object that looks like (with minification added)

{
    a: () => { 
        console.log("hello from a")
    },
    b: () => {
        console.log("hello from b")
    }
}

I want to later call eval on a string representation of this object in my react native runtime so that I can access the a, and b functions.

Does anyone know how to alter my webpack config so that I get back an object like this after calling eval? I would assume it would be an IIFE with that as the return of it.

I’ve tried using library target umd but that appears to throw errors and not return the object that I need in react native.

2

Answers


  1. Chosen as BEST ANSWER

    For my solution I achieved the desired result using a configuration like this.

    const path = require("path");
    const nodeExternals = require("webpack-node-externals");
    
    module.exports = {
        mode: "production",
        entry: "./scrapers/index.ts",
        output: {
            iife: false,
            filename: "bundle.js",
            path: path.resolve(__dirname, "./build"),
            library: "myLib", // This will expose your library on a variable named myLib
            libraryTarget: "var", // This will output a var myLib = ... IIFE
        },
        module: {
            rules: [
                {
                    test: /.tsx?$/, // Matches .ts and .tsx files
                    use: [
                        {
                            loader: "ts-loader",
                            options: {
                                configFile: "tsconfig.scraper.json",
                            },
                        },
                    ], // Uses ts-loader to transpile TypeScript
                    // exclude: path.resolve(__dirname, "node_modules"),
                },
            ],
        },
        resolve: {
            extensions: [".ts"], // Resolves these extensions
        },
        externals: [nodeExternals()],
    };
    

    I changed the javascript file like so

    export default {
        a: () => {
            console.log("hello from a");
        },
        b: () => {
            console.log("hello from b");
        },
    };
    

    Then I run eval on the client with the bundle (in react-native)

    const executable = eval(`var myLib,__webpack_exports__={};(()=>{var e=__webpack_exports__;Object.defineProperty(e,"__esModule",{value:!0}),e.default={a:function(){console.log("hello from a")},b:function(){console.log("hello from b")}}})(),myLib=__webpack_exports__;`)
    
    console.log(executable.default.a) // prints the function and everything is working
    

    By setting IIFE to false I was able to get a the executable to be defined.


  2. To achieve this, you’ll need to adjust your Webpack configuration to output a library in a format suitable for your needs.

    Here’s how you can modify your webpack.config.js to output an IIFE that assigns the exported object to a variable:

    const path = require("path");
    
    module.exports = {
      entry: "./test/index.ts",
      mode: "production",
      resolve: {
        extensions: [".ts"],
      },
      output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./build"),
        library: "myLib", // This will expose your library on a variable named myLib
        libraryTarget: "var", // This will output a var myLib = ... IIFE
      },
      module: {
        rules: [
          {
            test: /.ts$/,
            use: 'ts-loader',
            exclude: /node_modules/,
          },
        ],
      },
    };
    

    Make sure you have ts-loader and typescript installed in your project as they are necessary for Webpack to process TypeScript files.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search