How to package a client-side Javascript library today? - javascript

I've been catching up with the modern client-side JS ecosystem and reading up on module systems such as CommonJS and AMD (incl. associated tools - browserify, requirejs, onejs, jam, dozens of others). If I'm writing a Javascript library, how do I package it such that it can be most broadly accessible (ideally by users who swear by CommonJS, AMD, and especially neither)?
Popular libraries like jQuery seem to just use old-school file concatenation for building itself and dynamically detect whether it should write to an exports or the global context. I'm currently doing the same thing, but the main downside is that if I (unlike jQuery) depend on a few libraries, it's nice to not have to ask users to manually pre-include the transitive set. (Though I currently just have two dependencies.) And of course global namespace pollution.
Or perhaps it's cleanest to generate multiple versions of my library, for each context?
This also affects packaging and publishing. There are several systems, but I believe the major one is bower, which is easy to deal with since all it does is fetch. However, if I want to package it up for component, then that requires a CommonJS module.
Are there other relevant aspects I should be aware of? Are there any good example projects to follow for all of this?

I have been thinking about this myself and I came to several conclusions:
Create one version of the framework that can be used in both global and AMD setting
Don't obsess over having to ask your clients to include dependencies manually, it is a one-per-project activity and should be done anyway, whether you provide an AMD-packaged or global-scoped framework (3rd party dependecies placement will have to be adjusted anyway, is what I am saying)
I use Grunt for project building/packaging/testing/linting/whatever, so for all other packaging alternatives I have different tasks.
So, in short, build for "old-school/AMD" first, package for "new-age" later.
P.S.
I am also a firm believer that your packaging and delivering process/need shouldn't (whenever possible) dictate your architectural and development decisions.
I try to build the most customizable, modular and usable code I can, while using the packaging paradigm of my choice, then I consider alternative packaging. If I succeeded in the first part, second one is normally either straight-forward or requires very little codebase changes (because of the modularity and proper principles application in the first step).

Related

Should I include a plain JS interface for Typescript-based NPM package?

I'm creating an open source library intended for distribution as an NPM package. I'll write it in Typescript. I'm aware that not all potential users of my library will use Typescript. So I'd like to be friendly to the plain JS coders out there. And people use different build environments, which could add other wrinkles I can't predict right now.
Should I include an API facade that exports plain JS wrappers to my Typescript functions? If that seems wrong, maybe you could explain what a "friendly" approach would be for varied users of my package. Maybe nothing is needed at all.
At a technical level, I can work through individual import/export scenarios. This is more a question about what works well in the field with developer configurations I might not be able to predict.

Why can't React Native (RN) convert the main.bundle.js to native code to avoid the RN Bridge between VM & Native Modules

I was wondering why do we need the RN Bridge in the React Native engine which connects the Javascript VM (JavascriptCore) with the Native Modules. This bridge and message passing setup only slows down the app speed and creates a bottleneck. Why can't the package bundler spawned by React Native CLI, instead of just bundling javascript codes to main.bundle.js, also convert it to native code? one reason I've heard is coz javascript is not strongly typed, but this reason doesn't seem unsolvable. Any other reasons?
Indeed transpiling javascript into native code will provide tremendous performance improvements however it is not an easy thing to do at all. That being said, there are a lot of reasons why transpilation from one language to another is hard, and this is especially true if we consider the host language to be javascript and the target language to be java or something similar like C# and objective c.
Javascript is extremely different from these languages, many of the ideas are hard to map into a one to one, and the mindset is completely different.
Another thing that is special about javascript, and that makes it hard to transpile it to another language, is that javascript can never be a versioned language, and that since its the language of the web it has to always support backward compatibility. This means if a tool were to transpile from javascript to another language, this tool needs to support everything that javascript supports - one might argue that a tool might support only a recent subset of javascript, something like es6, however this is dangerous for two reasons, one it will be hard to define this subset exactly since a lot of es6 features are working by polyfills from es5, and two that this means that this tool wont be able to support all the javascript ecosystem.
here are some of details about some challenging parts of javascript to be transpiled into a language like java:
javascript is a dynamic language, not only there are no restrictions on types, but javascript do an extremely complex type coercing techniques in different operations under different conditions
consider this
true + 1 === 1 + '1' // false
true + 1 === 1 + +1 // true
Javascript introduced modules system only recently (starting from es6) this practically means that any program is one huge chunk of code, where variables live through out the entire program.
Javascript inheritance system (the Prototypal Inheritance system) is extremely different from classical inheritance systems in these languages, for example in javascript at runtime you can change the the class of an object, at the same time in runtime you can also change the methods of a class.
Now on top of all the technical challenges, notice that there is a product wise decision here, in making RN like this. This enabled RN to go to market faster, and not be tied to certain native language, this means its much more easier this way to support new environments by just transpiling ui controls to the native ui of that environment, and keeping javascript as it is. And on top of that if tomorrow, someone find a way to transpile javascript to java, this tool can be easily integrated into RN pipeline, without affecting the other components and supported environments of RN.

Any 3rd party packages used by Angular 4 in run-time (except RxJS)?

Angular 4 uses some RxJS types in its public API as well as depends on RxJS internally.
Thinking further on this, it might be good to know if Angular uses other packages for parts of its run-time functionality, so we could use them as well. It might prevent us from introducing extra dependencies for the app by re-using them from Angular.
But looking into node_modules, every Angular 4 app contains a massive amount of packages. Obviously, most of them doesn't get included in the run-time app bundle. At the same time, some of them (like lodash) could be very desirable to use in your Angular app as well.
So, is Angular based on any other packages except RxJS and which of them could be used in our own code similar to RxJS?
Angular is pretty buffed up, meaning it already comes with predefined strategy on how you should accomplish things. I believe it's built on RxJS so you won't be able to get rid of it.
But you don't really have to use it. When you pack your app for production it will not include all of the node_modules packages, only the ones that were used.
If you want to use a JS library that's a lot less heavyweight, and comes less structured, look into react.js and vue.js
Although RxJS is certainly a big player in Angular's dependency pool, it's certainly not the only one, and not even the only one you'll need to depend on to use Angular.
Zone.js, for instance, is another key component in Angular's architecture that you'll need to depend on to use it. Although both libraries are used extensively in Angular, you are by no means mandated to use them – that being said, you'll get a lot more out of the framework if you understand Observables and Zones.
Other things you'll need to depend on are easily inspected in Angular-CLI's polyfills.js file; things like core.js that shim up Angular's ability to run on lower-common-denominator browsers (cough, IE). There's also multiple #angular/*-scoped modules you'll need for other pieces of the framework, such as forms and http.
My recommendation? Boot up a CLI project and see what ends up in the dependencies section of your package.json. RxJS and Zone.js are the big contenders, but you may be surprised by other names on the list.

AMD Module Shaping: How to load only one JS function?

Many JavaScript libraries have a Builder tool that will allow you to "shape" what features of the library you depend on, both in terms of download bandwidth cost to the client and in terms of isolating functionality you actually need.
For example, I like many things in sugar.js, but I simply don't need or want katakana and hiragana character set handling. As the most trivial example, I want to be able to "shape" sugar.js to only export string.isBlank().
Is there a tool available to do this for me? Is there any ongoing effort by the EcmaScript committee to do something like this in a future version of JavaScript? Do any higher-level languages like TypeScript and CoffeeScript, offer hidden support for such "shaping"? I can do such "shaping" in C# for .NET DLLs via monolinker.
Basically, it looks to me like AMD handles the Loader aspect of a modern compiler, but does not handle the Linker aspect. Builders for jquery and dojo only work for a specific module, and aren't true Linkers, just Builders.
UPDATE: Google Closure Compiler is a compiler that takes JavaScript as input and produces JavaScript as output. The Advanced Compilation and Externs documentation suggests there is an API call to do this:
If putting together these export statements seems too tedious, you can use a function to do the exporting for you. See the Closure Library functions goog.exportSymbol() and goog.exportProperty() for examples of exporting functions.
However, this seems pretty convoluted, and makes me directly dependent on Google Closure Compiler. At this point, I am looking for info about future standards from the EcmaScript Committee, with regards to CommonJS, and for any wisdom from people who have thought about this problem and attempted to tackle it. Especially from fellow TypeScript developers; I don't want to have to create declare files in TypeScript for sugar.js, then use Google Closure Compiler against my TypeScript compiler output. It just sounds impossibly complex and hard to debug.
Unfortunately, there's nothing built into Javascript to do this "shaping", and really what you want is a compiler anyway, since roughly one of the roles it serves is to automate "shaping" at many levels (not just with methods).
The Closure Compiler is mature and open source (JQuery is actually minified using the Closure Compiler). So if you're going to begin annotating your JS code for a compiler, it might as well be this one.
There a huge number of side benefits of using a compiler, btw. They will reduce your file sizes (and thus interpretation/run time) a great deal more than simply shaping your included libraries. And while you're developing it will produce a lot of helpful messages to catch bugs early.

Current Best Practice for Modular Javascript Applications

Not looking to start a flamewar :)
I am looking to build a modular javascript app for mobile devices (green field implementation). So the requirements are that it needs to be relatively light weight, support deferred loading of sub modules based on runtime decision (like user preferences) and have minimal template & MVC capabilities. The communication with backend is probably going to be based on websocket API (if it changes anything). Think something like www.twitter.com that needs to run inside Mobile Safari.
I am competent with jQuery and I heard about a lot of newer javascript frameworks (backbone.js, require.js, zepto.js and so on) but haven't had a chance to use them. I doubt I have enough time to learn and prototype with them all so I am looking for some community wisdom as to what is considered the best practice nowadays.
Thanks.
Good application structure is your friend when coding JavaScript apps. I took a look at Spine and Backbone, but ended up using JavaScriptMVC. The major reasons:
Based on jQuery (so every jQuery plugin you find on the web will just integrate nicely)
Provides a default way of organizing your app (according to a plugin/mvc architecture
Promotes best practices (testing etc...)
EJS as templating engine
Easily extensible
Extremely well documented
Build-in productivity tools to generate code, compress code, JS dependency management
Maybe you could combine it with jQuery mobile to suite your needs.
It might suite your need since:
Modularity: create plugins/MVC modules for each module of your app
Deferred loading: Steal (build-in dependency management system) loads your stuff based on when they're accessed
Compression: minimizes band-width by compressing the production.js file with Google Closure compiler.
Modular javascript involves two things
Writing modular code
Loading modular code
Writing modular code is easy. All you have to do is have loosely coupled code that doesn't rely on global state and exposes itself as a module.
Loading modular code requires using a module loader. require.js as you mentioned is popular. or you can try something more recent like seajs.
As for other frameworks, you don't really need them, but if you don't know how to do JavaScript architecture then I'd be tempted to say you should use zepto and spine.js.

Categories