Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

webpack dynamic module loader by require

Tags:

OK, i have searched high and low but cannot reliably deterrmine if this is or is not possible with webpack.

https://github.com/webpack/webpack/tree/master/examples/require.context Appears to indicate that one can pass a string to a function and it load a module...

But my attempt is just not working: webpack.config.js

'use strict';
let webpack     = require('webpack'),
    jsonLoader  = require("json-loader"),
    path        = require("path"),
    fs          = require('fs'),
    nodeModules = {};

fs.readdirSync('node_modules')
    .filter(function(x) {
        return ['.bin'].indexOf(x) === -1;
    })
    .forEach(function(mod) {
        nodeModules[mod] = 'commonjs ' + mod;
    });


let PATHS = {
    app: __dirname + '/src'
};

module.exports = {
    context: PATHS.app,
    entry: {
        app: PATHS.app+'/server.js'
    },
    target: 'node',
    output: {
        path: PATHS.app,
        filename: '../build/server.js'
    },
    externals: nodeModules,
    performance: {
        hints: "warning"
    },
    plugins: [
        jsonLoader
    ],
    resolve: {
        modules: [
            './node_modules',
            path.resolve(__dirname),
            path.resolve(__dirname + "/src"),
            path.resolve('./config')
        ]
    },
    node: {
        fs: "empty"
    }
};

The server.js

let _ = require('lodash');
let modules = [ "modules/test" ];

require( 'modules/test' )();

_.map( modules, function( module ){
    require( module );
});

The module in modules/ named test.js

module.exports = () => {
    console.log('hello world');
};

But the result is always the same... the pm2 logs just say hello world for the static require... but for the dynamic load of the same module

Error: Cannot find module "."

All i want to be able to do is loop through an array of paths to modules and load then...

like image 371
John Avatar asked Mar 14 '17 21:03

John


People also ask

Is import better than require?

One of the major differences between require() and import() is that require() can be called from anywhere inside the program whereas import() cannot be called conditionally, it always runs at the beginning of the file. To use the require() statement, a module must be saved with .

What is __ Webpack_public_path __?

In Webpack, __webpack_public_path__ is a runtime variable that contains the public path used to load the assets. Unlike the static publicPath configuration (or what's --asset-path for esbuild), it can be freely modified by the program.

How does webpack dynamic import work?

Whenever you import a file in your code, Webpack will look for it in the project directory and copy it to the build folder with a new name, then Webpack replaces the import code in your bundled JavaScript file with the path to the newly copied file.

How are ES modules different from CommonJS modules?

The ES module usage format is the official standard to write JavaScript for maximum reusability and is what most web browsers natively support. However, NodeJS supports the commonjs module format by default, which are loaded using require() function, and the variables and functions are exported with the help of module.


1 Answers

You cannot use a variable as argument to require. Webpack needs to know what files to bundle at compile time. As it does no program flow analysis, it can't know what you pass to the function. In that case it might be obvious, but this could go as far as using user input to decide what module to require, and there is no way webpack can possibly know which modules to include at compile time, so webpack does not allow it.

The example you posted is a bit different. You could use require with a concatenated string. For example:

require(`./src/${moduleName}/test`);

Which modules does webpack need to include in the bundle? The variable moduleName could be anything, so the exact module is not known at compile time. Instead it includes all modules that could possibly match the above expression. Assuming the following directory structure:

src
├─ one
│   └─ test.js
├─ two
│   ├─ subdir
│   │   └─ test.js
│   └─ test.js
└─ three
    └─ test.js

All of these test.js files will be included in the bundle, because moduleName could be one or something nested like two/subdir.

For more details see require with expression of the official docs.

You cannot loop through an array and import every module of the array, with the above exception by concatenating a string, but that has the effect of including all possible modules and should generally be avoided.

like image 99
Michael Jungo Avatar answered Sep 25 '22 16:09

Michael Jungo