Modules are self contained scripts with their own distinct functionality. This allows for the addition or removal of modules as neccessary. It is easy enough to require
modules using Node.js, but in the browser they behave very weirdly based on what browser you’re using. One of the quirks of JavaScripts!
A book is organized into chapters, a good program is divided into modules.
In my blockly big picture post I used an inelegant hack within the CreateDataSet
block to include the stringified class code into the block itself. This is the perfect use case for a module!
Our Goal:
Rather than include the class script inside the CreateDataSet
block, create a seperate module
Workflow
- Create the Analysis class in a file called myModule.js and export it
- Import Analysis within our index.html file
- Change the
CreateDataSet
block to only contain the stringnew Analysis()
- Cross fingers, see if it works??
Before we even begin, I’m still a little confused why each browser has their own errors but in order to run and debug any html code locally download lite-server [npm install lite-server
] then serve your site in the directory where your html is located using lite-server index.html
. This worked far better than using Chrome directly!
myModule.js
I’ve created a file called myModule.js where I’ve defined the Analysis class and I’m exporting it to be used in our html file. The only line that’s changed here from the code in the prior post is the first line, be sure to export this as default
// rather than const PREFIX =
// we will export Analysis as a module
export default class Analysis {
constructor () {
this.value = 0
}
increment () {
this.value += 1;
return this
}
display () {
return this.value
}
}
Import
Back inside our html file we add
import Analysis from "myModule.js";
This was the trickiest part. This script needs to be contained within a type=module
script tag, but in order for the blockly code to access the module we have to make Analysis a global class. The simplist way to do this is by using window.Analysis
:
<script type="module">
import Analysis from "myModule.js";
window.Analysis = Analysis
</script>
example_blocks.js
Now we get elegant. Rather than include the Analysis class defintion within our block, we can simply point to our newly created module
Blockly.JavaScript['example_CreateDataSet'] = function(block) {
return "new Analysis()"
}
Whew! With A LOT of help from Evan Schultz, I successfully loaded my first module!
BONUS
I had to include window.Analysis = Analysis
because in my current framework I created two buttons with event handlers ABOVE the module.
While this works, it’s not good code ettiquite. Instead, we can create the button elements with IDs, then assign the event handlers BELOW the module script tag. That way we create buttons, then specify what those buttons actually DO after our module is loaded. This way, our two buttons show JavaScript
and run JavaScript
will work without needing to specify Analysis at the global scope.