I would appreciate any reasonable explanation of the use of BundleConfig and Require.js together in a SPA. How do you choose which scripts should be loaded by BundleConfig when starting the app? Which scripts should NOT be called in BundleConfig and selectively loaded via AMD? Once loaded by BundleConfig, do they have to be called again in require.js' DEFINE statement?
Search as I might, I simply can't find a simple explanation for all this.
Thanks!
BundleConfig will help you get all the script sin the bundle to the client together, in 1 trip. This takes the burden or job off of require.js for that. I often do this for 3rd party scripts, since it is highly likely i need them all client side right away anyway.
Then I can choose to either use require.js to load my scripts as needed (thus AMD) or bundle them too, up front.
Require does not just load things asyncly, though. It also handles the dependency resolution. To me, this is the more important part. It makes sure before I use module A that if it depends on B, which depends on C, which depends on D is resolved first. So they get loaded and run in the proper order.
So whether you use bundling or not, the require.js dependency aspects as super valuable.
Related
I've written PWA application, application isn't big, but now my app.js has 800 lines of the code. It has many methods. How to move these methods to another files divided thematically?
require doesn't work
You have a few options depending on what browsers you support.
You may be able to use native support for modules. You can find more information about this in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules This would be one of the simpler solutions as it does not require any additional tooling but at this time the support outside chrome is not very good.
A second alternative is to break up your code into multiple JS files and just load them all separately. This can have performance implications but if your files are small and few it wont cause too many problems. Just ensure that the code produced in these files put themselves onto a name object to avoid conflicts.
Ex file
(function() {
window.mycode = {};
window.mycode.func = function() {...};
})();
A third option is to use an existing module loader in the browser such as https://requirejs.org/
The fourth option, which is probably the most common, is to integrate a build step into your code that uses npm and a module loader such as webpack or browserify. This also lets you integrate babel which is really common among large javascript projects. The downside is it adds a step to your deployment that needs to be run and you need to learn how to use tools like webpack(which is surprisingly complicated). However, if you do javascript dev you will need to be familiar with them eventually.
I'm developing a 'widget', for lack of a better word, that will be loaded in many different sites that I don't control.
We're using RequireJS to keep things easy, but this has the side effect of breaking A LOT of sites that don't already use/support it.
The be clear - we don't control the sites, and the cause is that many of the sites existing libraries are loading into RequireJS instead of globally, and the code on these sites expects them to be loaded globally.
The only practical solution I can think of so far is to rename RequireJS' require() and define() (and perhaps others), then edit every library we rely on (using sed, of course) to load using the 'new' functions.
Has anyone else dealt with this? Is there a better method I'm missing?
Michael
For anyone who stumbles upon this, here's what I ended up doing...
There isn't a good solution for this at the moment as:
1) All libraries that load into RequireJS need define() to exist in their scope at execution time
and
2) There isn't any mechanism for asynchronously loading scripts that would allow define to be defined (pun not intended) and undefined before/after execution, aside from eval(), and that's just not a good option.
This means that, it's not really possible to have some type of scoped RequireJS without it possibly interfering with other scripts on-page that CAN use RequireJS, but are intended to load globally on that particular site.
So... here's the hacky solution I did...
Instead of loading the JS libraries myself, I bundled them on the fly, along with RequireJS, and wrapped in an immediately executing function.
The reason for doing this on-the-fly, is that some site specific data is necessary for the program to function, and it saves an HTTP request to obtain it (at the expense of a larger file download).
This allowed me to:
1) Use libraries that need to run under RequireJS (or similar) to work property
2) Avoid cluttering up the global namespace for stuff like jQuery
3) Avoid editing library source (eg. changing define() to my_special_define() or similar)
I hope this helps someone if they're trying to do the same thing as me :)
From a performance/maintenance point of view, is it better to write my custom modules with netsuite all as one big JS, or multiple segmented script files.
If you compare it with a server side javascript language, say - Node.js the most popular, every module is written into separate file.
I generally take the approach of Object oriented javascript and put each class in a separate file which helps to organise the code.
One of the approach you can take is in development keep separate files and finally merge all files using js minifier tool like Google closure compiler when you deploy your code for production usage which can give you best of both worlds, if you are really bothered about every nano/mini seconds of performance.
If you see SuiteScript 2.0 architecture, it encourages module architecture which is easier to manage as load only those modules that you need, and it is easier to maintain multiple code files i.e. one per module considering future enhancements, bug fixes and code reuse.
Performance can never be judge by the line count of your module. We generally maintain modules for maintaining the readability and simplicity of the code. It is a good practice to put all generic functionalities in to an Utility script and use it as a library across all the modules. Again it depends on your code logic and programming style. So if you want to create multiple segments of your js file for more readability I dont think its a bad idea.
I'm trying to write a modular library in CoffeeScript. I want to write the code once, and use it in the same way on the server (running Node in this case) and on the browser. How can I do this?
My code structure is like this...
src/a.coffee
src/b.coffee
src/c.coffee
And my dependencies are like this...
a depends on b, c depends on a and b.
I've tried Browserify and requirejs, but I couldn't quite get there with it. I've also looked into Traceur but that's no use since I'm using CoffeeScript. I'm really at a loss, the only thing I can think of, is bundling it all up in one file and doing it traditionally as explained in this blog... https://alicoding.com/write-javascript-modules-that-works-both-in-nodejs-and-browser-with-requirejs/. I really don't want to do that, I'd probably just write it in Dart sooner than I would bundle it up like that. CoffeeScript is really letting me down with this particular issue.
I forgot to resolve this. I ended up using https://github.com/jrburke/amdefine.
Anybody used LabJs in conjunction with javascriptmvc steal? meaning looking for dependency loading in child level as well as taking advantage of LabJs async performance gains.
a.js
.....
steal(../b.js)
.then(../c.js) //c.js requires b.js and d.js to be loaded before it can load
b.js
.....
steal(../d.js) //(need to load d.js when b.js invoked, loading d.js for better classification and maintenance )
Any articles or experiences for labjs + steal will be great.
steal is going to build your production app into a single JS file. You can load that file however you want.
setting aside that steal builds a single file for you for the moment...
the concept of annotating dependencies nested inside each script means that, by itself, you cannot take full advantage of parallel loading, because the loader doesn't know what scripts that A depends on until it finishes loading A and can see that it needs B and C. Of course, once it knows about B and C, it can load those two in parallel, but it cannot load B and C in parallel with A.
the other issue is that LABjs (and most other dynamic script loaders) has, strictly speaking, non-blocking behavior, so if you load some scripts like this, you will have an issue:
A
-- depends on B and C
D
-- depends on A and E
When A finishes loading, and then you start loading B and C, you can't natively (without extra pre-effort) make D wait until B, and C (and thus A) are done.
The reasons behind this are quite complicated to explain, but suffice it to say, that scenario is problematic for dynamic loading with nested dependency annotation.
However, if you know about the dependency tree at the beginning (that is, you don't wait to load scripts to find out about their nested dependency annotations), you can easily take advantage of dynamic parallel loading while making sure order is preserved. You can easily do this:
B
C
A
E
D
and load all 5 of them in parallel, while still making sure they execute in that proper order as noted. The best way to figure out that dependency tree and the necessary order of execution is to have a build process that walks through all your scripts and figures out what the list is and its necessary order.
Using LABjs, that chain above would look like this:
$LAB.setOptions({AlwaysPreserveOrder:true}).script([B,C,A,E,D]);
Pretty simple and straightforward, assuming you know at the outset what that list/order is. Just have your build script drop that one line of code into your HTML page, and boom, you're good.
If you don't have such a build script to do that (I have my own that I've built for my various projects that need this type of thing), you have two choices:
Don't use nested dependency annotation. Manage your list of dependencies (the above list) yourself, and make sure it's in the right order. For a decade or more, that's how people using script-tags in browsers have worked just fine, so it's probably quite sufficient for the majority of sites. I have LABjs chains on many of my sites that I manage manually, and it's no problem at all, as do thousands of other sites which use LABjs.
Use a build script (like Steal) that just puts them all in one file (of course, it has to figure out the proper order too!). You don't get the parallel loading benefit. Bummer.
Hopefully this sheds some light on the issues at hand.