Reputation: 31
In my web app I want to give users the ability to author their own modules for use in the app. These are ideally written in JS on the client side.
However, I'm having trouble allowing for classes created on the client side to be accessed by the app. Originally I wanted some kind of module import, but dynamic imports still require a path, which isn't accessible by the browser for security reasons. Just doing a straight import of the JS into a script tag pollutes the global namespace, which isn't ideal either.
Is there some sensible way to do this? I would ideally want to import the class, e.g.
// MyClass.js, on the client side
export default class MyClass {
myPrint() {
console.log('ya blew it');
}
}
And then in App.js:
import(somehow_get_this_path).then((MyClass) => { etc});
Is getting that path possible? The current namespace-polluting method uses a select file dialog but doesn't allow me to tell import what path it has. All you get is a blob. I'm pretty new to this stuff so apologies if this question is dumb.
edit: I've tried getting an object URL using CreateObjectURL, which gives the error:
Error: Cannot find module 'blob:null/d651a896-d568-437f-86d0-72ebcee7bc56'
Upvotes: 2
Views: 1063
Reputation: 163
Read file and use eval
<script>
function importJS(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
eval(reader.result);
input.value='';
};
reader.readAsText(input.files[0]);
};
</script>
Select a *.js file and execute
<br>
<br>
<input type="file" onchange="importJS(event);">
Upvotes: 0
Reputation: 1332
if you are using webpack as a bundler then use can use magic comments to lazy load the components.
or else you can use dynamic imports.
import('path_to_my_class').then(MyClass => {
// Do something with MyClass
});
Edited 1:-
You can use this code to get a working local URL for the uploaded js file. try using this
const path = (window.URL || window.webkitURL).createObjectURL(file);
console.log('path', path);
Edited 2:-
Alternatively, you can create your own object at a global level and wrap the file using an anonymous function (creating closure) such that it won't pollute the global namespace.
// you can add other methods to it according to your use case.
window.MyPlugins = {
plugins: [],
registerPlugin: function (plugin){
this.plugins.push(plugin);
}
}
// MyFirstPlugin.js
// you can inject this code via creating a script tag.
(function(w){ //closure
function MyFirstPlugin() {
this.myPrint = function (){
console.log('ya blew it');
}
}
w.MyPlugins.registerPlugin(new MyFirstPlugin());
})(window)
// get the reference to the plugin in some other file
window.MyPlugins.plugins
Upvotes: 2