Ultimate JS module solution for UMD with dependencies? - javascript

I maintain and collaborate on some JavaScript modules written in CommonJS that are in need of high-quality UMD wrappers.
The dependencies are sourced from npm but have at least CommonJS and AMD support (or I can add it).
The CommonJS version goes on npm The UMD wrapped module will be pushed to bower
The wrapper must work in browsers (AMD + globals), and in Node.js (any and other CommonJS systems if possible). Any automation should preferably happen using Grunt (I'm pretty handy in grunt).
I've spend ages trawling Google en SO but it is a huge mess.
Some hopeful ones that don't quite cut it (or I am missing something, which is entirely possible):
browserify
gluejs
grunt-umd
I'm finding desperate constructs like this everywhere: http://rathercurio.us/building-umd-modules-with-dependencies-with-browserify , but I'm not really cool with such hackery.
Any good tips on this? I'll take any pointer or link or tip.
Edit: clarification: that last thing said, the ideal solution should not require us to assemble chunks of boilerplate template code by hand and create new bugs. I cool with configuring and specifying stuff though.

Your 1st and last stop should be urequire.org, the Universal Module Converter that does much more that just converting CommonJS and AMD javascript modules to UMD (or AMD or CommonJS or a standalone using rjs/almond).
It allows you to manipulate Module's code and dependencies while converting: inject, replace or remove code and dependencies, export to global objects (window) or your bundle, inject & optionally merge common code (like initializations), add runtime information, minify and much much more.
Most of that using simple but hugely powerful declarations & optionally callbacks for fine grained manipulation. It works with standalone config files (.js, .coffee, .json, .yml etc) and as-is as a gruntjs config
uRequire compiles from source modules written in javascript, coffeescript, livescriped, coco & icedcoffeescript without any plugins.
Forget boilerplate, code ceremony and repeating requires. The conversion templates are based on the well known UMDjs but can be customized via declarations to hide or provide functionality.
uRequire is opensource, MIT license and hosted on github and authored by me :-)

Related

How does a packages typescript code is consumed by other packages?

When a package with typescript code is imported. will the consumer use typescript or transpiled code (e.g. typescript to ES5).
Scenario #1: If the consumer uses transpiled code (which is not in typescript). How is VSCode able to recommend auto completions from the packages types?
Scenario #2: If the packages are served with typescript files.
What happens if the consumer is not using typescript?
How does the bundling at the consumer end happen?
TL;DR
Scenario #1: This is the most common scenario for public NPM packages, editors use external .d.ts files that contain type declarations
Scenario #2: I've only seen this with internal libraries
1) You'd need to compile the TS by yourself, but that would probably not be necessary because there will almost always be a compiled-to-js version of the library, too
2) This could go many ways, best case is that the library gives you a pre-optimized JS that is just bundled with your code, worst case is that you have to make sure you have all the right dependencies installed for the library to be able to be compiled with your code and they need to be compatible with the dependencies you're using yourself. In my opinion this isn't worth the hassle, having type declarations for NPM packages is sufficient for the level of type safety TypeScript can provide.
The Long Version
There are dozens of variants how people distribute their TypeScript based code via NPM. Most big libraries I know ship their compiled (and often minified) JS and add .d.ts declaration files for editor support - these may be hand-written or produced by using tsc from a codebase. VSCode uses its TypeScript language server for JavaScript files, too, so in many cases it doesn't even need additional declaration files to provide you with basic autocompletion. Libraries can declare a types field inside the package.json, VSCode and other editors will find types there. There is a rather large community that maintains mostly inofficial type declarations for most libraries on definitelytyped - you may be out of luck for obscure ones.
A few examples
Material UI
Is written in JavaScript
Has hand-written TypeScript declarations (which may or may not be accurate)
React
Is written in JavaScript
Provides no TypeScript declarations with the NPM package but VSCode knows where to find inofficial external ones
Angular
Is written in TypeScript
Uses the deprecated typings field to point to its type declarations
jQuery
Is written in JavaScript
Again, has no provided type declarations but your editor probably knows how to fetch inoffical ones
Seneca
Is written in JavaScript
Has inoffical type declarations that are two years old at the time of writing - good luck finding out whether the API really hasn't changed
Important take-aways:
There is no single way people do things in the JS ecosystem and by extension the TS ecosystem
Most type declarations you're using are not official ones but the ones maintained by the community, mostly on definitelytyped
The types might be lying to you (may be out-of-date, just be plain wrong or for an older TS version)
TypeScript is a superset of JavaScript, it comes with all the same gotchas by definition
All types are erased at runtime, in the end you're running plain JavaScript with all that this entails

Should JavaScript npm packages be minified?

I have created quite a few npm packages, but I still don't know the right answer to this question: "Should JavaScript npm packages be minified?"
I have always understood that minifying minified code is a bad idea so have not done that in my npm packages. However, I see that some npm packages axios, styled-components provide minified versions of their "dist" files alongside unminified versions, while Lodash does not.
Which are right? Who would consume the minified versions?
It all depends on the environment of your package consumers
NodeJS
For a NodeJS audience your package does not have to be minified, since node runtimes normally have direct file access to the node_modules folder. No network transfers are required, and no additional code transformations are performed prior to running the code.
Bundlers / build pipelines
For consumption through a dev environment that uses a bundler in its build pipeline your package is best not minified. In most cases package consumers do implement their own minification process as part of their builds. Moreover, when providing your package in a module format for example:
the dependency tree of implementing codebases can be analyzed more accurately, which might lead to better tree-shaking performance.
Common dependencies across packages are actually the same symbols for all such packages (modules are 'singletons'). This helps with code splitting as well as with keeping bundles small.
The above statement relies on the assumption that, if multiple source files are included, minification is preceded by a bundling process. Minifying separate modules is uncommon. If you do provide separate modules, e.g. for a RequireJS runtime in the browser, minification is still relevant, since these files are mostly fetched over the network.
If you decide not to supply minified code, it's still advisable to run your own tests to see if a standard minification process - e.g. with UglifyJS - does not break the software.
Despite that it is for many consumers unnecessary to minify your code, it's still advisable to supply a minified bundle in addition to your regular distribution, just in case somebody could benefit from it.
For plugins / extensions for frameworks like Angular, Vue, Ember etc. it's usually unnecessary to minify your code, since they all implement their own build pipeline, often through a cli.
Script tags / CDN
These are the cases towards which minification is primarily targeted. If you're hosting a file on a CDN, or otherwise provide it over the web for direct <script> tag usage, what you see is what you get. In both cases the file will have to go over the network. Minification saves bytes.
Minification v.s. transpilation
A very important distinction is to be made between these two. Although minification is not always necessary, it is usually your responsibility to transpile any code that is unlikely to be 100% compatible with the target environments of your package audience. This includes:
Transpiling new ES20XX syntax to - probably - ES5
Polyfilling any ES20XX API implementations
Minification and bundling
If your package consists of a single bundle instead of a bunch of separate modules, minification is always a safe bet. Since a bundler will never try anything funny with a single module/entity (like tree-shaking), it's likely your code will technically not change at all by any build process.
Debugging
If you're going to distribute a minified bundle of your software, it would be nice to also ship a non-minified version for debugging purposes.

How to easily modularize Javascript like C/C++

I have a large project entirely built in JavaScript, I have an ordered and "inside modularized" 5k lines .js file that's the engine of whole site.
Now I have to make other site (extension of this one) in which I'll have to repeat a lot of code, my question is, I've seen lot of possibilities using Browserify, CommonJS, etc. But that's not what I'm searching, I'm searching modularize JavaScript just like C/C++, making #includes with the files of the functions or functionalities and reuse code like that. I'm already doing this including other JS files in HTML, but that JS files are only variables and some arrays, not functionality of the site.
I use jQuery too, in that large 5k lines .js file I have almost all inside the jQuery document.ready event, that's bringing trouble too, because I'll have to make a document.ready event for every file?
I need some orientation please
CommonJS will let you require() modules, this is the foundation for the NodeJS module system. Browserify simplifies this implementation for use in browsers and even allows you to require Node modules (as long as they don't depend on binaries, the file system and other features a browser doesn't support).
var lib = require('someLibrary');
ECMAScript6 (aka: ES6) brings imports to javascript. While browsers don't fully support ES6 yet, you can use Babel to "transpile" ES6 to ES5. This ES5 will take advantage of CommonJS to replicate the importing behaviour.
import { SomeClass, someFunction, someValue } from 'some/library';
In all cases, your javascript will require some kind of pre-processing to transpile it into javscript a browser can understand. This usually means taking all your separate source files and bundling them into a single minified bundle file. This reduces the number of requests the browser has to make.
To handle all this transpiling and bundling, several popular build systems exist including Grunt, Gulp and Webpack. Grunt is older and typically slower because of it's configuration-based design. Gulp is simpler and faster because it relies on NodeJS streams. Webpack is the newest and most powerful, but at the cost of complexity. For what you're hoping to do, I'd recommend looking at Webpack since it can modularize not only your javascript but your stylesheets and other web assets.
http://webpack.github.io/docs/tutorials/getting-started/
Use webpack to bundle your code http://webpack.github.io/docs/tutorials/getting-started/

compiling javascript program with requirejs to remove require dependency

I have written a JavaScript app using requirejs to handle dependency injection. I have compiled the file, but I get the obvious error when including it as a script:
Uncaught ReferenceError: define is not defined
I would like my JavaScript app NOT to depend on an AMD loader if the developer decides not to use one. However, due to the complexity of the application, I would like to use it to handle my app's dependencies.
Is there a compiler available that compiles JavaScript to remove the AMD dependency? I've seen a little bit of buzz around Grunt, but haven't found any straight answers on whether or not this is a feature of Grunt.
You can't completely remove the require/define dependency, but you can replace it with a much smaller shim that doesn't introduce any significant performance penalty. See the How can I provide a library to others that does not depend on RequireJS? section of the Optimization guide:
If you are building a library for use on web pages that may not use RequireJS or an AMD loader, you can use the optimizer to combine all your modules into one file, then wrap them in a function and use an AMD API shim. This allows you to ship code that does not ship with all of RequireJS, and allows you to export any kind of API that works on a plain web page without an AMD loader.
almond is an AMD API shim that is very small, so it can be used in place of require.js when all of your modules are built into one file using the RequireJS optimizer. The wrap build config option will put a function wrapper around the code, or you can provide your own wrapper if you need to do extra logic.

tips for migrating a javascript app to using AMD (eg requirejs)

I have a javascript project were most modules are using some third party libs as 'global' dependencies (in particular jquery and jquery plugins)
I would like to "clean" the project (to express all libraries as requirejs dependencies.), however this is in my case a large task (lots of files, lots of third-party libs).
How could I make the migration easier / quicker ?
Can I "fake" using amd dependencies by wrapping the third-party libs in modules that just load them (with the order! plugin ?)
Is it safe to mix modules that load third-party libs as modulesand modules that directly use the global ?
If I wanted to automate things, are there any tools could I use to 'parse' a requirejs module to tell me if a particular symbol is used ?
Edit : What I mean by my last question is "Would it be possible to automatically rewrite my js files so that hey explicitely import dependencies instead of relying on browser globals ?"
Can I "fake" using amd dependencies by wrapping the third-party libs in modules that just load them
Yes you can, RequireJS has a shim config that is designed just for that.
Take a look at this article it will help you organize your JavaScript code with RequireJS http://www.stefanprodan.eu/2012/09/intro-requirejs-for-asp-net-mvc/
I had a similar question about the need of wrapping third party code in AMD modules. My conclusion was, that there are no benefits in my case (large Backbone app). So you should ask yourself if you really need to import jquery for example per AMD. This will end in modules where you import jquery every time, which is a lot of error prone boilerplate code.
So in short it makes no sense to use AMD for code that you will use in any case.

Categories

Resources