UNPKG

npm-require

Version:

synchronous global require function for the browser to load commonjs modules from a (relative) path, a URL or npm

203 lines (169 loc) 6.32 kB
# npm-require synchronous global require function for the browser to load commonjs modules from a (relative) path, a URL or npm https://www.npmjs.com/package/npm-require # demo ```html <!doctype html> <html> <head> <meta charset="utf-8"> <script src="src/npm-require.js"></script> </head> <body> <script> var minixhr = require('minixhr') // from npm var pkg = require('./package.json') var demo = require('./demo') // resolves to `./demo.js` demo(pkg) </script> </body> </html> ``` <!-- @TODO: what about internal/local non-published modules? @TODO: what about more options for src="npm-require#...?..." - so that different registries (or registry proxies) can be set - and all channeled through an iframe/worker for caching? # DEMO (TEST) Structure: - no folders for different versions - current tests are for current versions - old tests are in version history - tests are numbered feature folders - new features get the next version number - retired features get deleted, thus archived into the version histroy - a feature folder potentially contains `fixture` folder - a feature folder contains a `spec.js` file to describe the feature usage # TODO ```js // @TODO: make test/test.html test stuff // @TODO: make test/benchmark.html test stuff // @TODO: include {test,benchmark}.html as iframes in index.js - where `index.html` is the DEMO PAGE which includes demo and documentation // @TODO: put `src/index.js` structure into place // @TODO: experiment with offlineFirst/ServiceWorker with cross-domain-re-use of modules // @TODO: find `package.json` and load all dependencies with their versions // @TODO: require.config(opts) // to change NPM CDN, etc... // @TODO: require.packageJSON // to show packageJSON of current require // @TODO: maybe support version ranges (check unpkg and wzrd support) // @TODO: compare with npm-requie inofficial and implement // // then // a. LOAD_AS_FILE(Y + X) // // LOAD_AS_FILE(X) // // 1. If X is a file, load X as JavaScript text. STOP // // 2. If X.js is a file, load X.js as JavaScript text. STOP // // 3. If X.json is a file, parse X.json to a JavaScript Object. STOP // b. LOAD_AS_DIRECTORY(Y + X) // // 1. If X/package.json is a file, // // a. Parse X/package.json, and look for "main" field. // // b. let M = X + (json main field) // // c. LOAD_AS_FILE(M) // // d. LOAD_INDEX(M) // // If X/index.js is a file, load X/index.js as JavaScript text. STOP // // 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP // // 3. If X/index.node is a file, load X/index.node as binary addon. STOP // // If X/index.js is a file, load X/index.js as JavaScript text. STOP // // 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP // // 3. If X/index.node is a file, load X/index.node as binary addon. STOP // 4. LOAD_NODE_MODULES(X, START=dirname(Y)) // // 1. let DIRS=NODE_MODULES_PATHS(START) // // 2. for each DIR in DIRS: // // a. LOAD_AS_FILE(DIR/X) // // b. LOAD_AS_DIRECTORY(DIR/X) // 5. `throw new Error("Cannot find module '<module name>'")` // @TODO: use as "test cases" or rather "example output" // require('./routes') // ./package.json#main // ./routes.js // ./routes.json // ./routes.node // // // /home/bytearcher/socket/src/server.js // require('async') // /home/bytearcher/socket/src/node_modules/async // /home/bytearcher/socket/node_modules/async // /home/bytearcher/node_modules/async // /home/node_modules/async // /node_modules/async // // module.paths // [ '/Users/samer/learn-node/repl/node_modules', // '/Users/samer/learn-node/node_modules', // '/Users/samer/node_modules', // '/Users/node_modules', // '/node_modules', // '/Users/samer/.node_modules', // '/Users/samer/.node_libraries', // '/usr/local/Cellar/node/7.7.1/lib/node' ] ``` # usage **`index.html`** ```html <body> <script src="https://wzrd.in/standalone/npm-require"></script> <script src="browser.js"></script> </body> ``` **`browser.js`** ```js var minixhr = require('minixhr') // use module :-) ``` # resolver spec *The `require` function in nodejs does not follow the official module resolver logic, so below follows the resolver logic this module uses and what I think the logic currently used by `require` in nodejs looks like* open issue: * https://github.com/nodejs/node/issues/17966 **Official** (not implemented by this module) * nodejs#require https://nodejs.org/api/modules.html#modules_all_together * commonJS#require http://wiki.commonjs.org/wiki/Modules/1.1#Module_Context **Inofficial** (implemented by this module) Follows official spec as closely as possible, but: * without nodejs CORE MODULES support * without .node file extension support ``` require(X) from module at path Y 1. If X is a core module, a. return the core module b. STOP 2. If X begins with '/' a. set Y to be the filesystem root 3. If X begins with './' or '/' or '../' a. LOAD(Y + X) 4. LOAD_NODE_MODULES(X, dirname(Y)) 5. THROW "not found" LOAD(X) 1. LOAD_AS_DIRECTORY(X) 2. LOAD_AS_FILE(X) 3. LOAD_INDEX(X) LOAD_AS_DIRECTORY(X) 1. If X/package.json is a file, a. Parse X/package.json, and look for "main" field. b. let M = X + (json main field) c. LOAD_AS_FILE(M) d. LOAD_INDEX(M) LOAD_AS_FILE(X) 1. If X is a file, load X as JavaScript text. STOP 2. If X.js is a file, load X.js as JavaScript text. STOP 3. If X.json is a file, parse X.json to a JavaScript Object. STOP 4. If X.node is a file, load X.node as binary addon. STOP LOAD_INDEX(X) 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP 3. If X/index.node is a file, load X/index.node as binary addon. STOP LOAD_NODE_MODULES(X, START) 1. let DIRS=NODE_MODULES_PATHS(START) 2. for each DIR in DIRS: a. LOAD(DIR/X) NODE_MODULES_PATHS(START) 1. let PARTS = path split(START) 2. let I = count of PARTS - 1 3. let DIRS = [] 4. while I >= 0, a. if PARTS[I] = "node_modules" CONTINUE b. DIR = path join(PARTS[0 .. I] + "node_modules") c. DIRS = DIRS + DIR d. let I = I - 1 5. return DIRS ``` --> # license MIT