Skip to content

Instantly share code, notes, and snippets.

@skyjur
Last active October 6, 2017 11:24
Show Gist options
  • Select an option

  • Save skyjur/69e9061222aac4d2107da80aae0a2344 to your computer and use it in GitHub Desktop.

Select an option

Save skyjur/69e9061222aac4d2107da80aae0a2344 to your computer and use it in GitHub Desktop.
Minimal implementation for requirejs to load bundles produced by typescript

TypeScript allows to bundle output into a single file using outFile compiler option.

This can be very useful to create single file bundle for web and you might not even need webpack for more simple applications.

One problem that needs to be resolved is module-loader. If we use "module": "amd" compiler option, typescript output will use requirejs specification to define modules. Full requirejs specification is a bit longer, and includes asynchronous script loading. Since we don't need asynchronous script loading we can make simplified implementation. One such simplified implementation of requirejs specs is almondjs.

Howeverif our goal is to oonly support typescript we potentially could have even simpler implementation:

  1. no need for async, already mentioned
  2. In requirejs specs there is some flexibility in the way define accepts arguments, we dont need this flexibility so we only need to write the code for the interface used in typescript output.
  3. we don't need to implement require.config()

In this gist you can see absolute-minimum implementation of requirejs in the index.html that can work with some typescript applications.

<script>
(()=>{
var loaded = {
/* map globally available libraries to modules here, for example for React: */
'react': React,
'react-dom': ReactDOM,
'jquery': jQuery,
'require': require
};
window.define = define;
window.require = require;
var promised = {};
function define(moduleName, modules, callback) {
promised[moduleName] = function() {
delete promised[moduleName];
var exports = loaded.exports = {};
require(modules, callback);
loaded[moduleName] = exports;
delete loaded.exports;
return exports;
}
}
function require(modules, cb) {
var args = [];
for(var i=0; i<modules.length; i++) {
var name = modules[i];
if(loaded[name]) {
args.push(loaded[name]);
} else if(promised[name]) {
args.push(promised[name]());
} else {
throw new Error('Module ' + name + ' is not defined');
}
}
cb.apply(this, args);
}
})();
/* Test: */
function assertIs(val1, val2) {
if(val1 !== val2) { throw new Error(val1 + ' !== ' + val2); }
}
define('a', ['exports', 'b'], (exports, b) => {
exports.a = b.b + 1;
});
define('b', ['exports'], (exports) => {
exports.b = 1;
});
require(['a'], (a) => {
assertIs(a.a, 2);
assertIs(a.b, undefined);
});
require(['b'], (b) => {
assertIs(b.b, 1);
assertIs(b.a, undefined);
});
</script>
<script src="bundle.js"></script>
{
"compilerOptions": {
"outDir": "./dist",
"outFile": "./dist/bundle.js",
"sourceMap": true,
"noImplicitAny": true,
"module": "amd",
"target": "es5",
"jsx": "react",
"lib": [
"es2015", "dom"
]
},
"include": [
"./src/**/*"
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment