I created a javascript application with all of the code in one file. The application has grown quite a bit and I think it's time to split it up into multiple files, but I'm having a hard time figuring out how to do this. I think the problem lies with how I have decided to build the app, which uses the following template:
var myApp = function(){ //there are several global variables that all of the modules use; var global1, global2, module1, module2; global1 = { prop1:1 }; //There are also several functions that are shared between modules function globalFunction(){ } var ModuleOne = function(){ function doSomething(){ //using the global function globalFunction(); } return{ doSomething:doSomething } }; var ModuleTwo = function(){ function doSomething(){ //module 2 also needs the global function globalFunction(); //Use the functionality in module 1 //I can refactor this part to be loosely coupled/event driven module1.doSomething(); } }; module1 = new ModuleOne(); module2 = new ModuleTwo(); }; Even if all of the modules were loosely coupled and event driven, I still don't know how I would go about splitting this into multiple files given each module's reliance on the shared functions/variables. Does anyone have suggestions?
55 Answers
Take a look at the design pattern in this article: - you can split your module definition across multiple files in a way that lets common properties be shared but also lets you create variables or methods that are private just to a particular file.
The basic idea is that the individual JS files add to the same module with code like this:
var MODULE = (function (my) { var privateToThisFile = "something"; // add capabilities... my.publicProperty = "something"; return my; }(MODULE || {})); Where in each JS file if MODULE is already defined (from another JS file) you add to it otherwise you create it. You can set it up so that it (mostly) doesn't matter what order the various files are included in.
The article details several variations, and of course you'll probably come up with your own tweaks...
1not to add to the confusion, but coming from a C++ background, I've tried to construct something that resembles something like a c++ namespace in the manner described below. it works, but I'd like to know if this is an acceptable pattern for the OP ?
--------------------------------file main.js:----------------
var namespacename = function(){} namespacename.mainvalue = 5; namespacename.maintest = function() { var cm = new namespacename.game(); cm.callme(); } --------------------------------file game.js:----------------
namespacename.gamevalue = 15; namespacename.game = function(){ this.callme = function(){ console.log( "callme" ); } } namespacename.gametest = function() { console.log( "gametest:gamevalue:" + this.gamevalue ); console.log( "gametest:mainvalue:" + this.mainvalue ); } --------------------------------file index.html:--------------
<html> <head> <title>testbed</title> </head> <body onload="init();"> </body> <script type="text/javascript" src="main.js"></script> <script type="text/javascript" src="game.js"></script> <script type="text/javascript"> init = function() { namespacename.maintest(); namespacename.gametest(); console.log( "html main:" + namespacename.mainvalue ); console.log( "html game:" + namespacename.gamevalue ); } </script> </html> 2Example:
require(["dir/file"], function() { // Called when file.js loads }); 9You can put the shared functions and shared modules on the myApp object so they don't pollute the global namespace, but can be accessed anywhere without being inside the same closure.
myApp.moduleOne = function() {...} myApp.moduleTwo = function() {...} myApp.globalFunction = function() {...} Then, you can define them in any file and use them in any file.
You could also just break the file up into multiple files, but require them to be included in a specific order that preserves your closure. If you're breaking up the files for practical editing reasons, but recombining and minimizing them for actual deployment, then this wouldn't cost you anything in terms of how you write code or how it's deployed, but would give you lots of smaller files for editing convenience.
2My favorite solution to this is use server side scripting to include the other files inside my "main" file. For example, using Perl's Template Toolkit:
var myApp = function(){ [% INCLUDE lib/module1.js %] [% INCLUDE lib/module2.js %] [% INCLUDE lib/module3.js %] } Or PHP:
var myApp = function(){ <?php include 'lib/module1.js'; include 'lib/module2.js'; ?> } 2