als-require
als-require
is a lightweight library for importing, modifying, and executing CommonJS modules in both browser and Node.js environments. It simplifies modular development by supporting dependency resolution, plugins for code transformation, and dynamic bundling.
Capabilities of als-require
:
- Import and execute CommonJS modules in NodeJs and browser with dependency resolution.
- Dynamically bundle modules into a single executable function.
- Transform module code using custom plugins before execution.
- Support for cyclic dependency detection and flexible logging options.
In version 3
- code refactoring
- improved getting node modules on NodeJs (not in browser)
- Changed constructor
- Now it has options (
{plugins=[],cyclicDependencies,logger}
)
- No
build
and bundle
methods. fn
and stringFn
methods instead
fn(options = {scriptBefore='', scriptAfter='', parameters=[]})
stringFn(options = {scriptBefore='', scriptAfter='', parameters=[],name})
- no minifying and minifying options
- The goal make it more simple. You can minify it separately
- plugins for modifying content
- no context
- You can add it as parameter to fn and pass as parameter's value
Installation
To install als-require
, use npm:
npm install als-require
Importing
Import in nodejs:
const Require = require('als-require')
const fn = Require.getModule('./some/path')
Import in browser:
<script src="/node_modules/als-require/require.js"></script>
or
<script src="/node_modules/als-require/require.min.js"></script>
<script>
Require.version = '1.0';
Require.cyclicDependencies = true
Require.logger = console
Require.getModule('./some/path').then(fn => {fn()})
require('./some/path').then(result => {})
</script>
Usage
als-require
has two files for NodeJS and browser which has same structure and api.
Constructor
Constructor initiating new Require instance.
On Nodejs, it's automaticly reading all modules and applying plugins.
In browser, you should run async method getContent
for reading modules and applying plugins.
Constructor has two parameters: path and options.
The path is a string relative path to modules. And options has plugins
, logger
and flag for allowing cyclicDependencies
.
const plugins = [
function(mod) {
const {content,children,path} = mod
mod.content = content.replace(...)
}
]
const options = { plugins = [], cyclicDependencies = false, logger = console }
fn and stringFn parameters
The fn
method generates an executable function containing the bundled modules.
This function accepts custom parameters and includes pre- and post-bundle code if specified.
The stringFn
method behaves similarly but returns the generated function as a string.
This is particularly useful for embedding the function in HTML or scripts.
Here are parameters:
scriptBefore
- Should be script as string to run it before bundle
scriptAfter
- Should be script as string to run it after bundle
- In this stage available two variables:
modules
and result
.
modules
- the object which includes all modules ({path:content,...})
result
- the function to run bundle which returned after scriptAfter
- In this stage, you can add return for returning something else
parameters
- The array of strings which will include parameters to pass in result's fn
name
- Only for stringFn
for changing function name
- For example, for icluding it in html and call by it's name
Node.Js
const Require = require('als-require');
const mod = new Require('./relative/path/to/module', {
plugins: [],
cyclicDependencies: true,
logger: console
});
const parameters = ['name'];
const scriptBefore = "const SomeVariableAvailableForAllModules = `Hello ${name}`;";
const scriptAfter = `
console.log('All modules processed.');
return result;
`;
const resultFn = mod.fn({ scriptBefore, scriptAfter, parameters });
const name = 'bundleFn';
const bundleString = mod.stringFn({ scriptBefore, scriptAfter, parameters, name });
const result = resultFn('Alex');
console.log(result);
const bundle = `${bundleString}\n const result = ${name}('Alex');`;
console.log(bundle);
Browser
<script src="/node_modules/als-require/require.js"></script>
<script>
const scriptBefore = "const globalVar = 'Hello, world!';";
const scriptAfter = "console.log('Bundle execution complete.');";
const parameters = ['customParam'];
const mod = new Require('./relative/path/to/module');
mod.getContent().then((mod) => {
const resultFn = mod.fn({ scriptBefore, scriptAfter, parameters });
const result = resultFn('Value');
console.log(result);
});
require('./relative/path/to/module',{ scriptBefore, scriptAfter, parameters },'Value')
.then(result => console.log(result))
</script>
Require node_modules packages and node modules
In case of path which not starts with .
, Require will look for file in node_modules (by checking in package.json).
If such package not found (for example require('fs')
), result for this package will return empty object.
const somePackage = require('some-package');
const somePackage1 = require('./node_modules/some-package/index.js');
const fs = require('fs');
module.exports = {somePackage,somePackage1,fs}
In case above somePackage
and somePackage1
should return the package, but fs, should return empty object.
Pay attention, in browser, using './node_modules/some-package/index.js'
instead 'some-package'
, you save extra request/readFile for looking the filename.
API
NodeJs version
class Require {
static contents = {};
static plugins = [];
static cyclicDependencies = false;
static logger = console;
static getModule(path, options = {}) {
return new Require(path, options).fn(options);
}
constructor(path, options = {}) {
const {
plugins = [],
cyclicDependencies = Require.cyclicDependencies,
logger = Require.logger,
} = options;
const combinedPlugins = [...Require.plugins, ...plugins].filter(p => typeof p === 'function');
this.contents = {};
this.path = path;
this.fullPath
this.keys
}
fn(options = {}) {}
stringFn(options = {}) {}
}
Browser version
class Require {
static standartNodeModules = [...];
static contents = {};
static plugins = [];
static cyclicDependencies = false;
static logger = console;
static version;
static isCyclyc(fullPath, path) {}
static async fetch(path, type = 'text') {}
static async getModule(path, options = {}) {}
constructor(path, options = {}) {
this.contents = {};
this.path = path;
this.fullPath;
this.contentReady = false;
this.options = options;
}
async getContent(options = {}) {}
fn(options = {}) {}
}
module.exports = Require;