I am trying to deepen my understanding of modules in JavaScript beyond just using CommonJS, AMD and ES Modules.
This has lead to me look more into webpack to understand how it actually makes modules work in the browser without relying on the still relatively new ES Modules. From what I understand, Webpack bundles the JS, converting import and require statements to its own statements and ships it with a runtime and manifest which allows it to execute them. So Webpack has gotten past the lack of module support by basically implementing its own?
I have tried to compare this to a different bundler — Parcel, but I can’t seem to find any information about how it handles modules.
Does anyone know if my understanding of Webpack is correct, and how that compares to how Parcel does it?
Appreciate any help in advance.
Thanks
The implementation of the ES6 import/export syntax has rendered many traditional module loaders such as RequireJS / AMD and rollup somewhat obsolete. However, asset bundlers like Webpack and Parcel still find their place in modern web development.
An assets bundler packs multiple files into a smaller set of files (including JS, images, fonts, LESS, SCSS etc.), thereby reducing the number of requests to the server and communication overhead. The bundling process typically involves script minification, dead code removal and dependencies management. This also allows more modular front-end web development.
In some ways, Parcel, being newer, is more advanced than Webpack. Parcel supports many different languages and file types out of the box, from web technologies like HTML, CSS, and JavaScript, to lower level languages like Rust, and anything that compiles to WebAssembly (WASM), to assets like images, fonts, videos, and more. You can build multiple targets at once and live-update them as you make changes. Parcel compiles all of your files in isolation in parallel inside workers, caching all of them as it goes along. No explicit configuration is needed for code splitting using dynamic import() statements.
Both Webpack and Parcel provide you a development server to test your project on a browser. Unlike Webpack, the entry point of Parcel is an HTML file instead of a JS file. You should not declare type=”module” within the < script> tags.
Another asset bundler is Browserify. It is a simpler tool which merely bundles your files. It is not as rich in features as Webpack and Parcel.
Related
I've recently gone down the rabbit hole of learning about modular programming with JavaScript, including some history of JS module systems, bundlers and ES2015 Modules. I now understand some of the pains that bundlers help/ed alleviate, such as:
network latency (more effective caching of a single bundle, HTTP/1.0 connections),
performance constraints on the size of application modules (minification, tree-shaking),
ES2015 not supporting some features (bare imports),
and backwards compatibility with older module systems (transpilation of ES2015 Modules syntax).
However I'd like to know if it is possible to create a production JS web application in 2020 that doesn't use a bundler like webpack or Parcel and uses ES2015 Modules? A caveat being that a source-to-source compiler like Babel could still be used provided it preserves ES2015 Modules syntax. I'm not saying I would like to do this but for the sake of argument, what would be the downsides?
Client-side code does not have to be bundled when run in a modern browser, but if you're going to design your code into tons of small modules (for the sake of development efficiency and reuse), then it will be very inefficient to load if you don't use a bundler that can reduce the number of separate files that need to be loaded.
A bundler will be desirable if you design your client JS files for best modular development and thus don't design your client JS files for efficient delivery as the bundler can bundle things together for efficient delivery in a build process.
"Part of the JS SDK" is a matter of terminology and opinion, not facts so I won't really comment on that assertion.
It is certainly possible to design client-side JS files from the beginning for efficient client-side delivery and not use a bundler (like we used to do), but you will not be able to also design the layout of the files for modular development. A bundler allows you achieve both goals which is probably why they are so popular.
However I'd like to know if it is possible to create a production JS web application in 2020 that doesn't use a bundler like webpack or Parcel and uses ES2015 Modules?
Yes, it's possible without a bundler if you run in a browser that supports import and export.
I'm not saying I would like to do this but for the sake of argument, what would be the downsides?
As explained above, you would either give up efficient client-side loading or you would give up ideal modular design as the two have conflicting design parameters.
What is the need for bundle.js for Node.js/Angular/React applications? What if its not used while building and deploying the application?
Where bundling comes from?
We started bundling our assets because of performance reasons.
HTTP1 supports limited requests on a single connection. Creating connections for each asset was killing the performance.
We started bundling things page by page to increase performance with more effective caching.
We were able to add the fingerprint to it and upload it to a CDN. (home-page.231434.js). So we were able to deploy our application by dockerizing it.
Bundling also helps us reduce the page size more because the bundler knows the full system. This means it can remove unused things and minify things easier. You can't do it without a bundler easily.
Also, bundlers are using transpilers. Browsers can't always be able to run the codes that we write like Typescript, and CoffeeScript. Bundlers can transpile these codes easily into bundles.
Do we still need it?
Nowadays things are changed a lot about bundling our assets.
First of all, almost every browser now supports HTTP/2. So we can request multiple files on the same connection. Bundling is not needed because of this anymore. Also, we have http/2 server push.
Libraries like React, Angular, and Vue are a lot more effective in size. They can be easily downloaded to a page from a gzip supporting source.
These are the reasons we don't need bundling anymore.
But based on your project we may still need bundling. This is the real truth.
I would still go with bundling.
In my company, we are using a container orchestration system to control our dockerized applications. We may run more than a version same time. Creating fingerprints for files while bundling and uploading them to CDN is still more effective for us. And also we are trying to get use of prefetching and preloading. CDN helps us reduce the loading times of other country visitors.
And also we are getting support from the service worker to change assets when we need it by page.
So actually nowadays it is just based on your project. There are not many performance reasons anymore.
how to create bundle.js
Nowadays,we usually use pack tools like webpack to pack js、css or other files.With proper loaders, webpack will pack the files into many bundle files and the browser will understand them.
the need for bundle.js
The module bundler will analysis the project ,find the dependency relationship and only fetch the necessary package when loading the web page.
And with module bundler, it will compiler some lanuages that browser can't read, like typescript 、less and so on.
What if its not used
Module bundler is not necessary for web project, but it will improving the performance of web pages.If not using the module bundler, web can't only fetch necessary bundle when loading.So the loading time will be longer.
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.
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/
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 :-)