Rollup js: how to make a closure like d3? - javascript

Most of what I use javascript for is d3 and the rest of my javascript knowledge was self learned by looking at examples, reading docs, etc. The point is my "in-depth" knowledge of javascript is not so deep...
Since I mostly work with d3 I have written a lot of my own functions and closures (as suggested by Bostock in Towards Reusable Charts) which build on top of d3.
To keep track of all the code I have written them in separate files and to use my collection I have tried a few ways such as dynamically appending script tags to the head of the document, concatenating files, etc
Ideally, I should make proper module of my code and bundle it together.
So I have set off on that path and stumbled across rollup and this tutorial by Lengstrof.
I tried following it and got it to work with some minor changes (e.g. it assumes babel-core is already installed and currently there is an issue with postcss.
Anyway, I made a small repo to demonstrate my use case (project repo). It has some modules which includes helper functions, some prototypes, and some closures.
Ideally, these would all be exported into a closure / object just like d3 (e.g. myClos) where I could then call any of the functions I have written.
Unfortunately, I have no idea how to do this and did not find relevant examples / tutorials on how to do this. Also, in doing this, would I have to then call my helper functions like myClos.helper1().
Anyway, I would greatly appreciate your help. The ideal end would be to have the rolled-up file myclos.min.js work like d3 where I include the script tag and then myclos is in the global-namespace.
Many thanks in advance for you assistance.

Make sure you're following the appropriate format for importing/referencing your external helpers/modules (e.g., from your main file: (esmodules) import foo from './helper1'; console.log(foo.helper1()) or (commonjs) const foo = require('./helper1'); console.log(foo.helper1()).) In the module you're trying to export from (helper1): (esm) export default helper1, (cjs) module.exports = helper1. The Rollup docs have good examples of this.

Related

JavaScript namespaced modules in single file VS import/export loaded modules (e.g. requireJS, es6)

I'm trying to figure the most efficient way to structure modules in our website that contains a lot of JavaScript namespaced modules in a single file (app.js) already.
Currently things look a bit like this:
app.js
OURAPP.mapsModule = (function() {
return ...
})();
...
OURAPP.searchModule = (function() {
return ...
})();
..and these are all contained within a single file. So, when we want to use any of these modules we:
search-page.js
...
OURAPP.searchModule.search(query);
...
search.html
...
<script src="js/main.js">
<script src="js/search-page.js">
...
We do have a lot of such modules. However, I'm wondering whether we should be doing something with import/export modules:
Method #2
searchModule.js
export default {
...
}
search-page.js
import searchModule from "./js/searchModule";
...
searchModule.search(query);
...
I'm guessing that a single file namespaced modules will be faster for the page to load(?) as it's only a single file to download. But when I'm looking at testing frameworks (e.g. Jest) they give many examples where module script files are loaded in this manner. Does it lend itself better to testing I'm wondering? Personally, I prefer this structure anyway but it's a bold change of direction from how the site has been built up until now and I'll need to good reason to suggest this. This website's is pretty much all generated server-side with JavaScript just doing the show/hide, query APIs, etc, with the addition on scrips and JavaScript libraries such as jQuery, Bootstrap, Isotope when required on each page.
I've read around but can't find anything comparing exactly both methods here and reasons for and against either. Would appreciate any suggestions or helpful advice, thanks.
Don't default-export objects, use named exports instead:
// searchModule.js
export function search(…) {
…
}
// search-page.js
import * as searchModule from "./js/searchModule";
…
searchModule.search(query);
…
I'm guessing that a single file namespaced modules will be faster for the page to load as it's only a single file to download.
Yes, that's true. However, do not let that affect your decision on how to structure your modules. You should always modularise your code so that it is the cleanest possible. Put the maps stuff in a different module than the search stuff.
You will then use a bundler or packer tool to create a single minified JS file to download that contains all the modules that the respective page needs.

Integrate a D3.js tree into a angular 4 project

I'm working on a webpage and I want to visualize a certain tree structure.
I bumped into this beautiful D3.js tree (http://bl.ocks.org/robschmuecker/7880033), but I'm having trouble importing it into my project since there are several ways (dg3-ng2 for example).
D3.js is a javascript-libary - and Angular works with typescript.
How do I integrate that certain tree into my project so that I also can modify it without any trouble afterwards?
I do have several questions like:
Where do I import the .js and the .json file?
Do I have to convert the javascript code into typescript manually?
Should I write the .js code into a .ts file?
Should I make a reference in my index.html?
Should I make use of a D3-Service?
As you can see I'm quiet confused.
If you use Angular, it's simple)
Istall d3 from npm.
Import d3 in component like that:
import * as d3 from 'd3';
And write you logic, use d3 syntaxis, example:
constructor(private element: ElementRef) {
this.htmlElement = this.element.nativeElement;
this.host = d3.select(this.element.nativeElement);
}
You graphic is a component, in you component descrite functions to build svg, draw axis and etc.
Then on init of component call methods that you describe, example:
ngOnInit(): void {
this.setup();
this.buildSVG();
this.drawFirstPlanRects();
this.drawSecondPlanRects();
this.drawXAxis();
this.drawYAxis();
this.drawCrossLines();
}
I'd strongly recommend using angular-cli since when you install the d3 library you won't have to deal with the boiler plate of hooking it into the app properly. You'd just need to import it into your ts document like the above example shows. On importing the json there are several different ways that it could be handled. You could just store the json in a variable in the .ts file, you could store it in a static json document that you then host along with the app and there a many examples of pulling files and loading json data out there already.
You don't have to convert any of the js code you have since ts is essentially js with types, though you might have to declare an any type for some things, but if you want ts code you will have to manually convert or find a ts example. I'd strongly recommend a good IDE that is compatible with ts. It'll do a lot of the heavy lifting of finding mistakes.
It's rather difficult to answer that question since I don't know the specs of your project. Generally if you are doing a one off thing that does't need angular I'd just keep it simple with js and drop the usage of angular. If this is part of a larger app though I'd recommend writing it in ts since angular2+ is written in ts and most examples you find online will be in ts.
If you are using angular-cli you won't need to make a reference in your index.html file
I'm not sure what you are asking here.
From the questions you are asking I'd strongly recommend really looking at angular and learning how to properly create an app with it and then figure out how to integrate d3 int the project, since some of the questions you are asking aren't related to just working with d3 in angular.

Create separate JavaScript bundles with a shared common library using Browserify and Gulp

For my team at work, I'm trying to set up a semi-automated JavaScript script and dependency management system with the help of Gulp and Browserify.
I'm not even sure if what I'm trying to achieve is possible with the currently available set of tools (and my limited JavaScript knowledge). I believe what I'm trying to achieve is a pretty common scenario, but I haven't been able to find the information I've been looking for.
Consider the following diagram:
The lines indicate depedencies. For shared modules, such as Module-v and Module-y, I don't want the scripts to be duplicated by being included in each of their respective bundles.
I know that using Browserify I can manually ignore or exclude modules, which is fine when the project is young - but as the project grows managing which dependencies need to be included where is going to become very cumbersome.
A similar Q&A here I think has the same essence of what I'm trying to ask, but to me, it isn't quite clear. It also references gulp-browserify which has since been blacklisted.
In my diagram, I can see that I have three Browserify entry points, but my lack of Gulp/Node/Browserify experience means I'm struggling to wrap my head around how I can try to achieve what I want to.
I'm happy to do the work to try and piece it together, as I already have been trying - however project managers are breathing down my neck so I'm having to hack together a temporary "solution" until I can implement something a little more automated and robust.
Thanks in advance.
Edit
It seems from Browserify's plugin documentation that this might be able to be achieved by using factor-bundle which substack pointed out to me; however again due to my lack of Node/Browserify/Gulp experience I am struggling to pull all the pieces together.
Related Questions
How can I use factor-bundle with browserify programmatically?
Figured it out, sharing the learns:
Code example:
var gulp = require('gulp'),
source = require('vinyl-source-stream'),
browserify = require('browserify'),
factor = require('factor-bundle');
gulp.task('browserify', function(){
return browserify({
entries: ['blog.js', 'page.js']
})
.plugin(factor, {
// File output order must match entry order
o: ['bundle/blog.js', 'bundle/page.js']
})
.bundle({
debug: true
})
.pipe(source('common.js'))
.pipe(gulp.dest('bundle/'));
});
The key difference between this output and the diagram, is that the common.js file is automatically generated based on common depenedencies between blog.js and page.js. This is described in the factor-bundle documentation.
Notes:
I found that Node would throw an error if the output files didn't already exist. I'm unsure why as I would have assumed that factor-bundle would simply write a stream to the outputting file regardless of whether it was there or not. As a workaround, after 'cleaning' the output directory, I simply created 'placeholder' files to keep it happy.
I haven't figured out how to access the factor-bundle stream event when using it as a browserify plugin (it may not even be possible), so any further work on the output files (such as uglifying etc) would likely need to be done somewhere else in the pipeline, possibly with another browserify plugin, or even after the fact.

Issue with concatenating a few javascript files

This is a complete noob question, but I gotta ask it anyway
I started playing with backbone.js a few days ago and I was really fascinated. As I got over the "ToDo", I started working on a project of my own. Coming from the world of Java, I prefer keeping everything in as many separate files as possible. Therefore, I split my models views, and routers into separate files, into separate folders.
The problem came when I tried to combine those fiels into one single applciation.js file. Again, coming from the Java world, I love when I can automate stuff, and even more, when I can use familiar tools like ant, to setup build processes for my javascript projects.
I got a sample ant build template which concatenates and minifies all the files in an arbitrary order. When it finished, I tried to run my JS app, and not surprisingly, it failed with a bunch of errors. Many of my models and views try to extend each other, others depende on them as components. If they are not defined in a proper order, the app just reaches a point where it is trying to execute extend of an undefined
I know from before that for JavaScript the order is very important, but somehow I was left with the impression that if all the scripts are in one single file, the JS parser will load all the stuff first and then will try to execute whatever is to be executed. Well, my assumption was wrong.
It is possible to list all the files in the specific order I want them, but do I really need to go for such a primitive step? Unfortunately after spending a few hours researching, I couldn't find anything better.
Is it really possible to concatenate JS files, which depend on each other, in an arbitrary order, without them clashing? I guess, the biggest problem is the fact that the extend function is actually being called, rather than each script simply defining and object literal
So, what's the solution?
UPDATE: I just saw that Sproutcore has its own builder. If SC is roughly similar to BB, in the way one creates and extends entities, how does the SC builder work without clashing?
There are many ways to do this, but here's my recipe. I prefix my development files with a number, starting from the one with no dependencies (base "classes", models that will be depended upon from other models, then views using these models, then routers calling those views, etc.).
Then I use uglify-js (available as a node.js library, that you install using npm install uglify-js) to minify all my js in one file (don't know from your question if you use node.js server-side, though). Then I cat *.js | uglifyjs -o min/myfile.min.js. This will send the content of all my .js files (respecting the order of dependencies because of my prefix) to uglify, which will minify it and save it to a single file.
Since I, too, like automation, I have this set up in a Makefile, though I guess it could be done using Ant (not too familiar with it). The relevant part of the Makefile look like this:
TARGET_MIN_FILE = public/js/min/myfile.min.js
JS = $(shell echo public/js/*.js)
public/js/min/myfile.min.js: $(JS)
cat $(JS) | uglifyjs -o $(TARGET_MIN_FILE)
clean:
rm -f $(TARGET_MIN_FILE)
.PHONY: clean
On the other hand, if you go for the asynchronous module definition (AMD) format, you can require() your modules and it will manage for you the dependency loading in the correct order (see Require.js for more info), as mentioned by TheShelfishMeme.
Your "assumption" is only true for var statements and functions of the form function name(a,b) {}. Those two get hoisted to the top of the script (or function block they are in) and are evaluated first.
If your files depend on other files being loaded first, it stands to reason that when you concatenate them they must be in that order in the final file.
Have a look at requirejs. It takes some time to set up but it should help you with your problem.
This article should help with the implementation.

How to structure nodejs code properly

I've been playing with node.js for a while, and I've really come to appreciate how awesome it is. However, one thing I'm struggling to understand is how I should structure my code so that it is maintainable. Most tutorials I've seen on the internet have all the JS in one file, which is hardly a nice way to manage your code. I am aware there is no such thing in real-terms as a "class" in javascript, but is there a (standard) way for me to format my code for maintainability in the same way I'd structure a PHP project, for example?
I'd add that as far as maintainability goes, I believe the typical style of deeply-nesting callbacks using closures is the single greatest impediment to the understandability of Node programs, as well as being completely unnecessary.
For every:
a.doSomething(val, function(err,result){
b.doSomethingElse(result,function(err,res){
...
});
});
There is always a:
a.doSomething(val, onDoSomething);
function onDoSomething(err,res) {
...
}
My rule of thumb is: a new non-closure callback function is required for anything over three levels of nesting.
(Node.js really needs a style manual.)
Afaik you can use require to include your own js files (containing exported methods) using:
var req = require('./someJsFile');
Within someJsFile.js you can export methods like this:
exports.someMethod = function(){ /*...*/ };
And in your main file you can address such a method using req.someMethod()
So this way you can split up your code in different files, which you require from some central js file.
Here is an article explaining node.js require
After you learned how require works in node.js (pretty straightforward), as suggested by Kooilnc
You can take a look at the source code of the modules available for Node.js:
https://github.com/joyent/node/wiki/modules
If you're planning to use Express (one of the most robust node.js framework out there) to develop your first node applications, you can take a look at its specific samples here:
https://github.com/visionmedia/express/tree/master/examples
(there's also an mvc sample)

Categories