using requirejs to load npm packages - javascript

i want to use this code in run in html, how could i use require.js to do this
const monerojs = require("monero-javascript");
the following doesnt work i get "Script error for "monero-javascript""
requirejs(["monero-javascript"], function(monerojs) {
main();
async function main() {
let walletKeys = await monerojs.createWalletKeys({networkType: "stagenet", language: "English"});
}
});

Require.JS is for loading AMD modules.
Node.js modules are either ECMAScript modules (which use import and export) or CommonJS modules (which use require and module.exports).
Even though both AMD and CommonJS modules use a function named require they are, in general, not compatible. (It is possible to write a module so that it meets the requirements of both AMD and CommonJS but this isn't too common).
If you want to use Node.js modules in the browser then use a bundler like Webpack or Parcel (but note that they cannot provide APIs that are specific to Node.js, such as the fs module for reading and writing to and from the file system).

Related

Why do some minified js files contain calls to "require" function

I've been modernizing some old gulp config where js files are concatenated and then minified by migrating to webpack.
Some of bundles contained libraries such as moment.js and isotope-docs.min.js,
When bundling with webpack I would get error that specific file or path is not found.
For example looking at moment.js
There is require("./locale/"+t) which causes my webpack to fail since i dont have locale directory.
Why would bundled js file have require function when browsers dont understand that?
Before ES modules became a thing, JavaScript did not have an official module syntax. Also, developers wanted to write a library once for both Node.js and the browser. The closest thing available was Node.js's require(), which does not exist on the browser.
So what tools like Browserify and Rollup would do is polyfill an implementation of require() (e.g. wrap the code in a "UMD"). This way, the module worked on any plaform and require() calls work as if in Node.js (its implementation may vary and can be extended because dealing with the filesystem is very different from dealing with a network).
Found a fix, you can just add to webpack confing under module noParse e.g
webpack.config.js
module: {
rules: [ ... ]
noParse: /moment.min.js|isotope-docs.min.js/
}

How do I detect if an ES Module is the main module?

How can I detect if an ECMAScript module is the main module? This is easy for CommonJS modules (see Detect if called through require or directly by command line).
There is no require or require.main
No process.mainModule
The import.meta has no clues, only has url
You could use es-main.
From the package README:
import esMain from 'es-main';
if (esMain(import.meta)) {
// Module run directly.
}
NOTE: This module will only work in a Node.JS environment, because the module code uses native Node.JS modules.
In the browser I don't know, but in node with .mjs module the following seems to work :
const isMainModule = import.meta.url.endsWith(process.argv[1])
Explanation:
import.meta.url begins with the protocole file:// eg:
file:///path/to/my/module.mjs
but in node, process.argv[1] is shorter, eg:
/path/to/my/module.mjs
so endsWith is useful here.

CommonJS wrapper for ES module scripts

The Node documentation on ECMAScript Modules makes recommendations for "dual packages" that provide both CommonJS scripts and ES module scripts to users.
Specifically, they suggest transpiling ES module scripts to CommonJS, then using an "ES module wrapper", an ES module script that imports from CJS and re-exports its CJS named exports as ESM named exports.
// ./node_modules/pkg/wrapper.mjs
import cjsModule from './index.cjs';
export const name = cjsModule.name;
My question is: is it possible to do this the opposite way, providing my scripts in ES module format, but adding a simple wrapper file in CommonJS allowing CJS users to require it?
For my part, I can't see a way to do this in synchronous code. It appears to me that CommonJS scripts can only import ES modules via asynchronous dynamic import().
(async () => {
const {foo} = await import('./foo.mjs');
})();
But that means my CJS script can't export anything that depends on foo.
There is no way to synchronously import ESM modules. CJS exports are synchronous, but ESM imports are inherently asynchronous.
In CommonJS, require() is synchronous; it doesn't return a promise or
call a callback. require() reads from the disk (or perhaps even from
the network), and then immediately runs the script, which may itself
do I/O or other side effects, and then returns whatever values were
set on module.exports.
In ESM, the module loader runs in asynchronous phases. In the first
phase, it parses the script to detect calls to import and export
without running the imported script. In the parsing phase, the ESM
loader can immediately detect a typo in named imports and throw an
exception without ever actually running the dependency code.
The ESM module loader then asynchronously downloads and parses any
scripts that you imported, and then scripts that your scripts
imported, building out a “module graph” of dependencies, until
eventually it finds a script that doesn’t import anything. Finally,
that script is allowed to execute, and then scripts that depend on
that are allowed to run, and so on.
It isn't even necessarily possible to transpile ESM to CJS in all cases. For example, ESM can use top-level await, and CJS modules can't. As a result, there's no way to translate this ESM code into CJS:
export const foo = await fetch('./data.json');
CJS and ESM are completely different animals.

How can I integrate custom module loading with webpack?

I'm using Webpack 1 for a frontend project and I have a legacy internal Javascript library which uses its own module system similar to AMD. A module is defined with a code similar to this:
MyLib.define('module id', ['my', 'module', 'deps'], function (my, module, deps) { /* module code */});
Then you can use the modules with a code like this:
MyLib.require(['dep1', 'dep2'], function (dep1, dep2) {});
I would like to be able to use MyLib along with all the other CommonJS modules I'm already using. Can webpack support this somehow?
As far as I know, Webpack doesn't support custom module formats (if someone else knows otherwise, I'd love to be proven wrong, though).
You perhaps could work around this by writing a Webpack loader or a Babel plugin that converts the syntax to one of the module formats that Webpack supports. The latter is what Babel used to do for ES6 imports before Webpack supported them out of the box - it'd just transform them into CommonJS require calls.

Do I still need a module loader if I'm using ES6 modules?

Unfortunately my knowledge of JavaScript module loaders is still growing and I'm trying to understand their relationship to the new ES6 Modules. As far as I can tell using a module loader like CommonJS or RequireJS using ES5 compliant JavaScript really needed the use of an asynchronous module loader to increase performance and load only as needed using the respective module loader's syntax.
However looking at the ES6 module documentation and reading other information, it appears to me that module loading is natively supported via the import and export keywords. If this is the case am I correct that ES6 JS modules natively support asynchronous module loading and therefore I do not need to use an additional tool like CommonJS or RequireJS?
it appears to me that module loading is natively supported via the import and export keywords.
Not exactly. The import and export declarations only define the dependencies and the interface of each module. They allow to statically extract strings that name the required modules, nothing else.
If this is the case, do I not need to use an additional tool like CommonJS or RequireJS?
No. You still need to use a loader for ES6 modules, which resolves the names or paths or whatever from the imports to actual module files and loads them with an implementation-dependent method.
There are many tools or toolchains available, examples for the different solutions are
webpack: bundles everything into one large script
System.js: loads single modules dynamically and asynchronously (similar to what require.js does)
native: node.js and web browsers are still figuring out how to support module loading without additional libraries
babel transpilation: you can convert ES6 modules to AMD or CommonJS format and use the known tools like require.js for these
As far as my understanding goes, ES6 supports the syntax for defining and importing modules. The actual act of importing the modules that are required are a job of the infrastructure.
In modern browsers (as of 2016 that is) do not have built in functionality to support module loading and as such you will still need something like SystemJS to do the actual loading.
ES6 JavaScript Files are inherently treated as a module. if you define anything in a .js file, it will only be visible within that file (local scope ). what export does is, it exposes the classes / variables defined as export, visible to outside. then you can import it to a another module. There are other ways to define modules such as using Commonjs or AMD etc.. . Module loaders are required if you want to dynamically lazy load modules. ex. Systemjs is a such a Dynamic Module loader. it will fetch the physical module file from server dynamically when it is requested, and will prevent having multiple loads the same file. in SPA application in past had to load everything at the beginning to it to work. with dynamic module loaders now we can have only the files we need to do the intended job. hope this will help you.
https://github.com/systemjs/systemjs

Categories

Resources