Proper way to use Babel in production - javascript

I want to use babel to transform modern javascript to plain old ES5 JavaScript.
I used the first tool on babel's website "Prototyping-In the browser" and on the website it says
"... if you are working on a production site you should be
precompiling your scripts server-side"
after using that prototyping tool, the browser's console says
"... Be sure to precompile your scripts for production"
as a result I checked the second tool "Babel built-ins CLI" and used it with the help of node.js to generate the compatible JS scripts, the website doesn't mention the same message about production as the first tool I used, although the resulting code is almost the same.
My question is can I grab the resulting JS scripts from the "Babel CLI" tool and
just replace the current ones? is that enough for production? Are they considered precompiled?
Note that I am not using node.js, it is just a javascript application.
Searching around the web got me many results about precompiling JS such as using webpack and Browserify and now I am lost about the state of the files generated from Babel, are they ready to be used or should they be precompiled.
I am posting this question out of confusion, so my apologies if it sounds stupid or not reasonable.

Can I grab the resulting JS scripts from the "Babel CLI" tool and just replace the current ones? Is that enough for production?
Yes, that would work. However you will want to avoid this manual step of copying scripts into a web tool for every little change you make during development. It's better to work with an automated build flow.
Searching around the web got me many results about precompiling JS such as using webpack and Browserify
Babel only transpiles new syntax to old syntax. Webpack and Browserify also bundle modules into a single script that can be loaded into a webpage.

Related

Using React with an existing application with JSX

We are planning to switch new technologies like react for my CMS project which is under development for 10 years.
Until now everything was simple and plain on the front end.
First include jquery.js then if necessary include the components and third party scripts, then code and dance with the DOM.
But now while trying to jump into a higher level of technology and different approach, things can easily get very complicated for me.
After spending more than 10 hours with React documents and tutorials I have a very good understanding about what it is and how it works.
But I realized that I am very unfamiliar with some popular concepts. I never used node.js, never used npm, babel, webpack, and may other many "new" things I have seen every where. I am face to face with these tools because of React and I am convinced that these are the inevitable for modern front end development.
Now the question
Our CMS runs on PHP and depends on MooTools heavily at the front end. Instead of a complete rewrite of a 10 years old CMS I just want to try new technologies partially for some cases. Decided to starting with React.
For the case I want to integrate ag-Grid to React also.
What I did not understand is that how to bring all these tools together.
I won't be able to use the simply include js way of react because of ag-Grid.
In the examples the code written has some JSX. Which means that we write JSX and run it translated for the browser to test if it is ok.
Each time before testing do I need to translate these files?
And more over if the files are translated does debugging become very
complicated?
Can babel make it on the run time? If yes is it a good practice.
There are lots of file in the node_modules folder. Which of them
should I include for production?
All sources on the net are very theoretical and assumes a knowledge. Need some guidance for best practices.
There are lots of questions and not a single step by step guide from beginning to production.
JSX is an extension over spec-compliant JavaScript. It is syntactic sugar for React.createElement(...) and is optional in React development.
React can be written in plain ES5:
React.createElement("div", { foo: "foo" });
Instead of JSX:
<div foo="foo" />
Or with helper functions like h that achieve the same goal, e.g. react-hyperscript.
The fact that there is PHP backend application doesn't prevent from developing React frontend application with JSX. This may require to configure React project to not use built-in Express web server and build client-side application to custom location, i.e. existing app's public folder. In case create-react-app is used, this may require to eject the project).
Each time before testing do I need to translate these files?
They should be transpiled to plain JavaScript (ES5 if it targets older browsers). They can be translated on every change in source files when client-side project runs in watch mode (conventionally npm start).
And more over if the files are translated does debugging become very
complicated?
This is what source maps are for.
Can babel make it on the run time? If yes is it a good practice.
It's possible to use Babel at runtime, and this isn't a good practice, even in development environment.
There are lots of file in the node_modules folder. Which of them
should I include for production?
The contents of node_modules doesn't matter. Almost all of them are development dependencies that are needed to build client-side app. This is the task for a bundler, which is Webpack in create-react-app template. It builds project dependencies to plain JS in dist folder.

Javascript bundling and module loading

I've recently been thrown in to clean up a project which has like 45-50 individual .js javascript files. I wonder what the best approach would be to decrease the loading size of them all. Just concatenate all files into one with npm or gulp? Install some module loader? webpack?
If you're already concatenating, minifying, and uglifying and you don't want all the files to be loaded on all the pages due to a monolithic bundle, you might be looking for something like Webpack's Commons Chunk Plugin.
This plugin walks down the tree of dependencies for each endpoint defined in your Webpack.config file and determines which modules are required across all pages. It then breaks the code into two bundles, a "common" bundle containing the modules that every page requires, which you must load with a script tag on each page:
<script src="commons.js" charset="utf-8"></script>
And an endpoint bundle for each individual page that you reference normally in a script tag placed after the commons script tag:
<script src="specificpage.bundle.js" charset="utf-8"></script>
The result is that an individual page will not have to load modules that will only ever be used on other pages.
Again, this is a Webpack plugin. I don't know if this functionality is available as a Gulp plugin, because it must have knowledge of all endpoints in order to determine which dependencies are common to them all.
I redirect you to the very good https://github.com/thedaviddias/Front-End-Checklist
In particular the following advises:
JavaScript Inline: High You don't have any JavaScript code inline
(mixed with your HTML code).
Concatenation: High JavaScript files
are concatenated.
Minification: High JavaScript files are minified (you can add the .min suffix).
You can accomplish this with a package manager such as gulp, grunt or webpack (for the most famous ones). You just need to choose what you prefer to use.
If you consider webpack, You can start with my very simple (but understanding) starter: https://github.com/dfa1234/snippets-starter
There's no much thing that you can do, basically is:
Concatenation - https://www.npmjs.com/package/gulp-concat
Minification - https://www.npmjs.com/package/gulp-minify
Instead of creating all those scripts, you can get something to re-use on yeoman, f.e. the Fountain, so it will reduce a lot of time just typing procedural code for doing the concatenation/minification.
Also if you can use some lazy load (like RequireJS or some frameworks have support to lazy load the module, like Angular) that will improve the performance of your aplication
EDIT:
If you want even more performance, you can install some compression tool in your server, for example this one for NodeJS https://www.npmjs.com/package/compression
I'm my personal opinion, if you have time, the best approach would be to read and understand the purpose of the project. Then plan a proper refactor. You are not fixing anything with concatenating, this is just a deployment step.
You should analyze which technologies are being used and if you want to maintain this code, in the long run, make a proper refactor into a much more modern stack, maybe you can take a seed project with ES6, webpack, Babel... and create a proper repository well maintained with proper modularity and dependencies resolution.
Once you have that, decreasing the load its just about adding proper tools in build time (babel, webpack, etc).
You would like to add some unit tests and continue working properly :)

How do you build, bundle & minify ES6-modules?

Due the fact, that ES6-modules (JavaScript-modules) are available for testing:
https://www.chromestatus.com/feature/5365692190687232
https://medium.com/dev-channel/es6-modules-in-chrome-canary-m60-ba588dfb8ab7
I wonder, how should I minify and prepare the project release-file? Earlier, I havde bundled all JavaScript-files into the single and minified file, except situations, where I have to load the JS-file dynamically via XHR or Fetch API.
As I understand, it's rather impossible to prepare a single-minified file with the ES6-modules right now or may be, I'm just misunderstanding some ways of work.
So, are the any ways to prepare my ES6-modules into single file and how I should prepare the modern JavaScript-project in 2017 year, where JavaScript-modules will be available?
I wonder, how should I minify and prepare the project release-file?
That is purpose of this action? Okay, minified files take fewer network traffic, and will be downloaded faster, but most NPM libraries provides minified dist-files already. And main question about bundling in one big file.
Why webpack do it? Of cource, due absence of support for ES-modules in browser by native, What's why webpack resolves import statements and round dependencies in synchronous manner*, and then substitute it to IIFE for scoping. And perform babel translation and polyfilling, yes.
But then native support of ES-modules is started, it's become un-useful. One of main goals when exposing your web-app to production, is minify traffic volume for your server, using CDN. Now you can do it in native way, so just import ES-modules from unpkg.org and be happy
*If not using HMR, of course, But it's not appropriate for production mode.
Live examples here: https://jakearchibald.com/2017/es-modules-in-browsers/
This blog explains how you would use the ES6 module syntax and yet still bundle your code into something that the browser will understand.
The blog explains that using SystemJs as an ES6 module polyfill and Babel along with Gulp will enable you to code you modules in ES6 yet sill be able to use it today.
https://www.barbarianmeetscoding.com/blog/2016/02/21/start-using-es6-es2015-in-your-project-with-babel-and-gulp/
Using this guide will help you write your code in ES6 while still having a normal workflow to building, minifying and bundling your code.
Keep in mind there are a lot of tools out there that will help you achieve this but I've followed this method many times and I can vouch for its validity.

Does Grunt offer some "externals" option similar to what webpack provides?

We know that using webpack sometimes we do not want to include a package code inline in our output file(s) as it is assumed that it will be available on the Browser globally at runtime.
This is done because it allows us to avoid bundling all of our dependencies, which allows browsers to cache those libraries between builds.
This is explained a bit here
My question is, can we do something similar in Grunt?
Actually I am working on an application which uses Grunt and I want it to ignore any require("react") lines as it is already being added to page via script tag.

How can I use npm for front-end dependencies?

I want to ask if it is possible (and generally a good idea) to use npm to handle front-end dependencies (Backbone, jQuery).
I have found that Backbone, jQuery and so on are all available through npm but I would have to set another extraction point (the default is node_modules) or symlink or something else...
Has somebody done this before?
Is it possible?
What do I have to change in package.json?
+1 for using Browserify. We use it here at diy.org and love it. The best introduction and reasoning behind Browserify can be found in the Browserify Handbook. Topics like CommonJS & AMD solutions, build pipelines and testing are covered there.
The main reason Browserify works so well is it transparently works w/ NPM. As long as a module can be required it can be Browserified (though not all modules are made to work in the browser).
Basics:
npm install jquery-browserify
main.js
var $ = require('jquery-browserify');
$("img[attr$='png']").hide();
Then run:
browserify main.js > bundle.js
Then include bundle.js in your HTML doc and the code in main.js will execute.
Short answer: sort of.
It is largely up to the module author to support this, but it isn't common. Socket.io is an example of such a supporting module, as demonstrated on their landing page. There are other solutions however. These are the two I actually know anything about:
http://ender.no.de/ - Ender JS, self-described NPM analogue for client modules. A bit too involved for my tastes.
https://github.com/substack/node-browserify - Browserify, a utility that will walk your dependencies and allow you to output a single script by emulating the node.js module pattern. You can use a jake|cake|rake|make build script to spit out your application.js, and even automate it if you want to get fancy. I used this briefly, but decided it was a bit clunky, and became annoying to debug. Also, not all dual-environment npm modules like to be run through browserify.
Personally, I am currently opting for using RequireJS ( http://requirejs.org/ ) and manually managing my modules, similar to how Mozilla does with their BrowserQuest sample application ( https://github.com/mozilla/BrowserQuest ). Note that this comes with the challenge of having to potentially shim modules like backbone or underscore which removed support for AMD style module loaders. You can find an example of what is involved in shimming here: http://tbranyen.com/post/amdrequirejs-shim-plugin-for-loading-incompatible-javascript
Really it seems like it is going to hurt no matter what, which is why native module support is such a hot topic.
Our team maintains a tool called Lineman for building front-end projects. The tool is node-based, so a project relies on a lot of npm modules that operate server-side to build your assets, but out-of-the-box it expects to find your client-side dependencies in copied and committed to vendor/js.
However, a bunch of folks (myself included) have tried integrating with browserify, and we've run into a lot of complexity and problems, ranging from (a) npm modules being maintained by a third party which are either out of date or add unwanted changes, to (b) actual libraries that start failing when loaded traditionally whenever a top-level function named require is even defined, due to AMD/Require.js baggage.
My short-term recommendation is to hold off and stick with good ol' fashioned script concatenation until the dust settles. Until you have problems big enough or complex enough to warrant it, I suspect you'll spend more time debugging and remediating your build than you otherwise would. And I think most of us agree the best use of your time is focusing on your application code, not its build tools.
You might want to take a look at http://jspm.io/ which is a browser package manager. Has nice ES6 support too.
I personally use webmake for my small projects. It is an alternative to browserify in the way it brings npm dependencies into your browser, and it's apparently lighter.
I didn't have the opportunity to compare in details browserify and webmake, but I noticed webmake doesn't work well with modules internally using global variables such as socket.io (which is full of bloat anyway IMO).
I would be cautious about RequireJS, which has been recommended above. Because it is an AMD loader, your browser will load your JS files asynchronously. It will induces more exchanges between your client and server and may degrade the UX of people browsing from mobile networks / under bad WiFi. Moreover, if you succeed to keep your JS code simple and tiny, asynchronous loading is absolutely not needed !

Categories