Skip to content

Instantly share code, notes, and snippets.

@karlfloersch
Last active March 16, 2016 21:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karlfloersch/a719e3edf00ebe66f7e4 to your computer and use it in GitHub Desktop.
Save karlfloersch/a719e3edf00ebe66f7e4 to your computer and use it in GitHub Desktop.
Webpack loader that wraps a JS file in a function so that you can inject variables to be modified. Original Author: @IngwiePhoenix
var loaderUtils = require("loader-utils"); // https://www.npmjs.com/package/loader-utils
module.exports = function WrapAsFnLoader(source) {
var query = loaderUtils.parseQuery(this.query);
var exportVars = query.exports;
var exStmt = [];
// Build the local variables by using the exports property on the query.
// This allows us to turn a couple this-variables into locals.
// Use a string to indicate that you want to import it as the same name,
// alternatively, provide an array of key-value pairs: The key becomes the local var,
// the key is the environment's property.
exportVars.forEach(function(ex){
if(typeof ex == "string") {
exStmt.push([
"var",
ex,
"=",
"this["+JSON.stringify(ex)+"];"
].join(" "));
} else if(typeof ex == "object") {
for(var propName in ex) {
exStmt.push([
"var",
propName,
"=",
"this["+JSON.stringify(ex[propName])+"];"
]);
}
}
});
// Build the source
this.cacheable();
return [
"module.exports = function testing(env){",
" var fn = function(){",
exStmt.join("\n"),
source,
" }",
" return fn.call(env);",
"}"
].join("\n");
}
@karlfloersch
Copy link
Author

Use Case

Consider this circumstance:

file1:

import Class from ‘class-module’
instance = new Class()
// < execute file2 which modifies instance > //
console.log(instance.new) // outputs “true”

file2:

instance.new = true

You're going to have a hard time doing this with normal webpack loaders.

What wrapAsFn loader can do

This loader will preform the following transformation to file2:

file2:

fnWrap(env){
  var fn = function(){
    var Instance = this["Instance"];
    Instance.new = 'I am new!';
  }
  return fn.call(env);
}

Now in file1 you can write:

import modifier from '!./<pathToWhereYouPutWrapAsFn>/wrapAsFn.js?exports[]=Instance!./testfile'
var Instance = {}
modifier({ Instance })
console.log(Instance.new) // -> Outputs: "I am new!"

Success! We've done it! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment