Jump to content

AMD vs Common JS for html5 modular development?


ShotgunJed
 Share

Recommended Posts

Given that 'native' module system has now landed, which is very very similar to CommonJS I'm not sure this is even a question of debate anymore, use what the spec uses.

Your list of technologies doesn't make sense either, webpack is a bundler, requireJS also a bundler (primarily for AMD but before that ship had sunk added commonJS support), and commonJS is a module specification.

Outside of legacy I've not seen anyone using or recommending requireJS, it did its job and helped evolve the module battlefield, but is no longer relevant. There are a host of competing bundling solutions, webpack is very popular but isn't spec compliant, does some horrible things to module inclusion and is a proper ball-ache to set up. Other solutions like browserify (an old dog now, but gets new teeth when necessary) and rollup are superb solutions, they are both simple to use and well maintained. Bundle solutions should be simple above all else, but which one is 'best' depends largely on what you want to achieve (as always). Rollup, for example, is superb for packaging libraries, webpack naturally takes longer to set up and if you want to invest in that then it makes more sense to do less trivial stuff with it.

Personally, I almost always plump for Browserify if I get the choice. It's simple to use, is mature so is performant and has a bazillion plugins and extensions that are battle hardened.

In truth, you could spend ages 'fiddling' with your build configuration, but, its a bit of a waste of time. Get something that works, roll with it and touch it only when absolutely necessary.

As with a lot of competing libraries, they mostly are capable of doing whatever you want, and your preference often comes down to how well maintained, how well documented and whether you like the api they expose for consuming them.

What is your actual requirement for bundling? 

Link to comment
Share on other sites

Yeah use the native module. You still have to pack the data yourself though (which you end up using something like Babel Webpack and whatevs), but if you want something closer to C++ or Java, at least use TypeScript due to its strong and static typing.

Link to comment
Share on other sites

2 minutes ago, Alectora said:

Yeah use the native module. You still have to pack the data yourself though (which you end up using something like Babel Webpack and whatevs), but if you want something closer to C++ or Java, at least use TypeScript due to its strong and static typing.

May I know what is this "native module"? I know it has the word native in it, but do you have to download anything to use it? Any syntax or perhaps some official documents outlining this feature?

Link to comment
Share on other sites

7 hours ago, ShotgunJed said:

Not much, just wanting to have the module system (e.g: let x = require('');) to make development more cleaner, like in traditional OOP programming like C++, Java, etc

I'd second using the native module specification, which is basically commonJS with some alterations (commonJS is used by node, to great effect, although using modules in a browser has its own problems, hence why its taken a while to implement, and still possibly does not work as you might like).

For example:

Create a new folder and add two files, main.js and dependency.js.

// dependency.js

module.exports = 'Hello World'
// main.js

const message = require('./dependency.js')

console.log(message)

These use commonJS spec to enable modularisation. If you have node installed simply run it using `node index.js` from that directory (using the command line) and you’ll see 'Hello World' output to the console. Node understands commonJS modules and is able to pull in the dependency you specified using `require('./dependency.js)`, this dependency file exports a string, once it has the exported string it can be used, such as `console.log(message)`. Note that the preceeding './' is important here as it tells node this is a relative import (without it node will, by default, look for that dependency in the `node_modules` folder it uses).

To take this a step further consider changing dependency.js:

// dependency.js

const messages = [
  'Hello',
  'World'
]

module.exports = messages.join(' ')

If you now run `node index.js` you’ll see the same thing output. This works as node executes the file when it requires it, which ends up joining the `messages` array in to a string and exporting that string.

This is important to know as you can start to see why pulling in dependencies over a network connection can, and will, cause your entire application to halt while it waits for the network to resolve the dependency, the JS engine to execute it, and finally continuing execution from the `main.js` file.

Module resolution over a network problems aside, browsers do not understand commonJS, although some have implemented the new module specification, the conversion from commonJS to new module spec (lets call it ESNext spec) is simple:

// dependency.js

export default 'Hello World'
// main.js

import message from './dependency.js'

console.log(message)

If you try and `node index.js` then node is going to complain at you, however, this code will work in some (soon to be all) browsers now, just add an html page that references the script:

<script src='./main.js' type='module'></script>

Now serve up the folder will all three files in, point your (compliant) browser to the html et voila, 'Hello World' printed to the console.

There is more to the module spec, such as exporting named exports, but you've got pretty much all of the pieces.

The only remaining puzzle piece here is creating a build that all browsers can understand, that is where the bundlers come in, although, in this case you need to do two things:

1) transpile from new module spec to something like commonJS

2) bundle some code so that understands commonJS

Note that using commonJS isn't a strict requirement, but many tools will do it this way.

The simplest way I know is to use browserify (bundler) and babel (transpiler, well, strictly its more than this):

$ npm init
$ npm i -D browserify babelify babel-preset-es2015

If you have node installed then you also have npm installed, so you can use npm to install browserify, babelify (which is a way to let browserify consume babel) and babel-preset-es2015 (babel now works via plugins, which can be bundled together as presets, here we just use a generic one, which includes modules).

Both browserify and babel need a little bit of config, this can be supplied in one command line command but its easier to create a bit of json for it, you can create separate files for this but both tools will read it from the `package.json` which will have been created for you by running `npm init`, add the following two blocks to `package.json`:

"browserify": {
  "transform": [
    "babelify"
  ]
},
"babel": {
  "presets": [
    "es2015"
  ]
}

This tells browserify to use babelify as a transform and then tells babel to use babel-preset-es2015 as its preset, from here things get considerably easier.

`npm init` has probably created `scripts` block for you, add a script definition:

"start": "browserify main.js > bundle.js"

This is just a helper, you can use the `browserify` line directly from the command line, if you have it in your path, by using npm scripts it adds the node_modules/bin folder to your path so you can just install stuff local to your folder and run scripts in there, to get going run the script:

$ npm start

This is shorthand (npm has many many shorthands) for `npm run start` and just tells npm to execute the script. 

This starts the process of first transpiling files using babel and then bundling using browserify.

Change your html file to point to `./bundle.js` and open it in any browser (even really old ones) and you'll see your console output.

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...