How to integrate legacy JavaScript with NodeJS in the browser - javascript

Hypothetical legacy scenario:
Say I have 4 scripts that simply get concatenated together as a single script for deployment to provide a utility library with a global namespace in the browser.
I then have 1 separate application script that utilizes the library.
Something like:
<script src="library.js"></script>
<script src="app.js"></script>
In my app.js script, calls are made to the library methods through its namespace, like
var id = lib.id(prefix);
I see that 1 of the 4 library scripts is a useful utility that I want to turn into a Node module. I copy it and create a package and publish it to npm to use in new development.
Problem: Now I have two versions of this script to maintain - one for Node and one for the legacy library.
Is there a way to have one common file that I can include in both the Node module and the legacy library? Or am I stuck maintaining two versions of the file until we phase out the legacy code?
Additional info:
I looked at browserify and webpack, thinking they might be useful, but both suffer from a problem I don't know how to get around. Unless the end module defines global variables, I can't use the module in legacy code, as there is no require command available. In other words, I can't browserify a Node module, then drop it into a legacy web page and use it in my existing app.js, because I can't call var mymodule = require('mymodule'). Is there any way to get browserify or webpack to define and expose a require function to let me access my new Node module from a legacy codebase? Surely, this is not a unique scenario.

Your best bet is to use a UMD pattern to ensure that the module can be used both as a global and in commonJS (ie- node) systems.
The pattern that would fit best for you is returnExports. This ensures that all exported properties are either applied to the global object (ie- window) or to the module object in node.
Since you are not using AMD, you can simplify the pattern somewhat and remove the first chunk of the if statements on lines 18 and 42.
This will require you to reorganize your code so that it fits in with the pattern.
There are other patterns that you may use, such as commonJsStrictGlobal, but I personally prefer returnExports.

Related

What is the benefit of importing process in node?

I am used to simply using process.cwd() directly inside of node applications, however, I have recently read the node docs and saw that it recommends importing it from node:process.
So what is the difference from just calling it directly?
process.cwd()
vs importing it and calling it:
import {cwd} from 'node:process'
cwd()
I am currently building a CLI application in case that makes a difference.
Is there a difference?
Which one should I be using?
importing it from node:process guarentees that you get the built-in process module, not some global that some other code in the project has configured or overridden.
This may be done for safety reasons or just for robustness reasons so other modules in the project can't hack on a global process object before you get to use it.
It also may not normally be needed, but is considered good project hygiene as it deters certain types of hacking.

What is the best approach for TypeScript with ES6 modules?

I am starting a new Web project and trying TypeScript, mainly as an ES6 transpiler but also with the additional benefits of type checking, especially for existing libraries such as jQuery combined with the DefinitelyTyped type definitions.
Since the latest version, TypeScript supports both its own internal modules and ES6 modules, which calls "external" modules. Because ES6 is more standard than TypeScript, my intention is to use ES6/external modules rather than the traditional/internal TypeScript modules.
I have my own code defined in several files/modules, but I want the build to generate a single .js file that I can load from the browser.
The problem is that as far as I can tell, TypeScript is only able to generate a single output file when using its own module format. If I try to use ES6 external modules, then it generates a separate .js file for each .ts file.
This means I would need to concatenate them using browserify, but also I want source map support, which means that I should configure browserify for input and output source maps, then combine it with exorcist so the source map is extracted out of the bundle.
That looks like a very complex build setup. Isn't there a more straightforward way, maybe directly supported by TypeScript? What is the best approach? What do you recommend?
Let TypeScript do what it does best...
Add types to JavaScript be it ES5/ES6/ES7
Transpile to ES5
Resolve modules via the specified module syntax (commonjs, amd, umd, system)
Then find another tool that will take the separate files and combine them into a single bundled file (in the right order). My suggestions are to look into:
webpack
browserify
tsify
Are you looking for a solution in the browser? If so, I highly recommend my project Zwitterion. It removes the complicated build steps, and let's you include TypeScript directly into the browser with normal script tags. You can also use standard ES modules directly, with no extra setup. It uses SystemJS under the hood to achieve that. There is no source map support yet, but that should come. If you would like more information besides what's in the README, you can read "Zwitterion, forget the build step".

Using a browser-ified module in an app that then needs to be browser-ified

I have written a self contained angular js module using browserify in order to make use of the commonJS/Node style syntax.
The module works fantastic when tested by itself, so I then use gulp to minify and host that on GitHub.
I've then imported that into another app that is also using browserify. When I run browserify it seems to try and rebrowserify the module and causes no end of problems.
I believe this is because the module requires angular and jquery and qtip2. So it's obviously trying to re parse these.
Is there a standard to not parse modules, or is there a way to exclude the browserifying of the modules? Or is it best to not include things like angular and jquery within your modules? I was trying to make them perfectly stand alone, maybe that's unwise?
Many thanks!
I would suggest providing both options, if it is important for you to have a standalone version that includes angular. This will provide people using your code with a total of three ways of using your code: Using the standalone version, the version that only includes the module, and cloning the repository directly and including the source files as part their build process.
I generally use the third option, but people who don't have build processes will likely prefer the first or second.

Node.js: recursively getting building configuration from dependencies

I'm developing a JavaScript project targeting browsers using the closure compiler, but lately I've been thinking to start using browserify and follow a node-like development approach: splitting the project in a number of smaller node modules, building everything using something like grunt, using node's require system (thanks to browserify) etc.
In order to build the whole project after slicing it into some modules, I need a way to get from every module its scripts, assets, some optional configuration, and to recursively do the same on its dependencies.
Is there any standardized way to do this? Any module already taking care of this? Anything providing assistance to this work?
As requested, here an example of what i need. I'll try to pick the most complex one.
The project heavily rely on HTML5 Canvas. It's supporting FlashCanvas, but I want it to be in a separate module because I also want to build the project without FlashCanvas support, and because I'd like to release the flashcanvas module on NPM so that it can be easily integrated in other projects.
When building with the FlashCanvas support, I need to:
put flashcanvas/flashcanvas.js and flashcanvas/flashcanvas.swf in the data directory that will be shipped with the project.
Include <!--[if lt IE 9]><script src="flashcanvas/flashcanvas.js"></script><![endif]--> in the HTML page.
In case I'm compiling with closure-compiler, the FlashCanvas externs file must be passed to the compiler.
Pass an option to browserify that replaces require('canvas') with require('flashcanvas'), in order to override the functions that create the canvases.
In case FlashCanvas was depending on other modules (this is not the case for this module), take assets/configuration/whatever from the dependencies.
I believe that my problem should be quite common among who's developing with browserify: it sounds pretty normal that some modules offer assets (CSS files, images etc) that you need to include. Still I couldn't find anything to solve the issue. Is my approach the right way to structure a node/browserify project? How am I supposed to get the data listed above from my main module's Gruntfile?

To require or not to require?

So I've been building a single page web app for a while now and I've been writing all my code in an extremely modular approach. I've been using the javascript module pattern for all modules and my main API uses the revealing module pattern to expose a small API for plugins and other modules.
So even if I've been writing my code like this someone mentioned I should be using require.js as it gives a better modular approach.
I decided that require.js doesn't really make it more modular so my next thought was how require.js separates out dependencies. Require.js forces you to name dependencies in each module file. But this to me seems to be a task I have to do for every module and I have a lot of modules. At the moment all my files are concatenated into a single javascript file in my grunt build process so really all my files are loaded at the start. I need most of my modules loaded at the start so it made sense to do this.
So my question is... Should I use require.js even though my code is modular and all my files are concatenated together and loaded at the start? Do i need to worry about dependencies or loading order? Any help/advise or previous experience when dealing with this situation would really help. Thanks
Have you had annoyances putting <script> tags in the correct order to handle dependencies right?
Having a requirejs config file where you declare the third-party code and your own code dependency tree is a much more organised approach than declaring <script> tags by yourself.
When you are testing your app in dev environment, wouldn't be helpful to have all those modules in separated files that are easier to debug instead of all of them concatenated?
With requirejs you can switch between optimised/concatenated/minified code used in production environment and a list of independent files representing each module in the development environment.
Are you creating a global variable for each module in your app?
Requirejs avoids creating a global variable for each module so your global scope doesn't get cluttered.
It's usually a good practice to follow conventions in the way you declare modules. Requirejs implements AMD specification that is a well thought way of loading modules in client javascript.
http://requirejs.org/docs/whyamd.html
It's way easier to follow conventions if they're already implemented in a mature framework. And sometimes we don't notice but between apps we do the same thing differently and that affects in the maintenance phase.
Take a look at the requirejs optimizer. Look all the options it give you. It allows you to exclude files, to change versions of a given module, to change the minification tool, to integrate the optimization process with other tools like grunt or bower, etc.
http://requirejs.org/docs/optimization.html
If you don't need any of this, then just continue doing it in your way.

Categories