4

As a newbie I am trying to understand what the logic is under the hoods for react packages in npmjs.com repository.

I find it a little bit strange since some modules that I install works flawlessly with my application (such as react-motion), where some reject to work by giving Uncaught SyntaxError: Unexpected token import error (such as react-sortable-pane).

What I understood up to now is it has something to do with ES5. The modules that are implemented with ES6 or ES7 must be converted to ES5.

My question is, how can I understand if a package is not ES5 compatible and what can I do to convert it to ES5 during or after I used yarn add command to install the package to my node_modulesdirectory?

Mehmet Kaplan
  • 1,723
  • 2
  • 20
  • 43

2 Answers2

3

TL:DR Transpile your code or use:

import { SortablePane, Pane } from 'react-sortable-pane/lib/react-sortable-pane.es5';

First things first.

Two main folders Src and Lib

A common convention for javascript projects is to put all of your development code into a folder called src. This folder may contain code such as ES5 or ES6 depending on what the developer wants to work with.

The other main folder is usually called lib which contains all code from src that is transpiled (with babel for example from ES6 to ES5), converted and usually bundled (webpack minify for example) so that it can work in the browsers that that npm package supports (varies from package to package obviously). This folder only contains code that is relevant to the user using the package, i.e. all tests are not converted and bundled because their is no reason to.

Entry Point

The other important part for npm packages is the entry point for the npm package. By default NodeJS will look for an index.js file in the imported package (I think). This can be overwritten by supplying the main key in package.json.

Example in react-motion's package.json:

"main": "lib/react-motion.js"

We can see that this points to lib. But where is the lib folder on their Github??? It's not their because usually you don't want to check in a lib folder to source control because it's just transpiled for the npm package.

We can confirm this by installing react-motion and looking in node_modules/react-motion. The lib folder here exists with transpiled code that is ready to be used in any browser without babel.

But why don't all npm packages do this for me!?!??!

Most do and they should do really. I do in my packages.

The react-sortable-plane npm package is using this instead "jsnext:main": "./lib/react-sortable-pane.js" which basically means it uses ES5 syntax everywhere but with import/export and I haven't seen before because it isn't widely used.

See https://github.com/rollup/rollup/wiki/pkg.module#wait-it-just-means-import-and-export--not-other-future-javascript-features

As to why they just use import/export with ES5 features I presume it's because import/export has become standard now but I am not sure.

You will still have to transpile this package if you want older browser support or just import the .es5.js file, e.g:

import { SortablePane, Pane } from 'react-sortable-pane/lib/react-sortable-pane.es5';

Hope this helps. I know it's confusing with so many damn environments like UMD, Common, Node etc...

Martin Dawson
  • 7,455
  • 6
  • 49
  • 92
  • The answer is great, thank you. But still I am lost after "npm install"ing two different modules (say react-motion and react-sortable-panes) under the same directory (so they reside in the same node_modules directory of the root project folder). Then what are the steps that I should take to transpile react-sortable-pane and use it, for example which file should I choose as an entry point? I'd appreciate for a possible guidance. – Mehmet Kaplan Nov 05 '17 at 19:13
  • @MehmetKaplan Actually you don't need to transpile any packages at all. Just use the `react-sortable-pane/lib/react-sortable-pane.es5` as you clearly need support for older browsers that don't support the import/export statements. That's what this file is there for. If this file wasn't there then you would have to use babel to convert the package import/export to require statements but this .es5 file already has done this for you. – Martin Dawson Nov 05 '17 at 19:24
  • Thank you @MartinDawson . That was way easier. :-)) – Mehmet Kaplan Nov 05 '17 at 19:26
  • @MehmetKaplan No problem. If any npm package you use doesn't provide a transpiled file that works in old browsers I suggest you ask the package owners to create one for the package rather than transpile it yourself but 99% of them already do, they are just named differently sometimes and you may have to check the lib folder for the one you want. – Martin Dawson Nov 05 '17 at 19:29
  • This is well noted as well. Thanks again @MartinDawson – Mehmet Kaplan Nov 05 '17 at 19:31
1

The solution is to account for any version of Javascript and use a transpiler to make sure that various JS versions which might be in your code and imported modules will be covered by your transpiler's configuration. Going through your modules and trying to figure out which version of Javascript they use isn't a practical exercise. Most projects have a bunch of dependencies, and all those packages have their own dependencies. So you'll end up going down a rabbit hole.

Babel is probably the most well known transpiler. With the right configuration you can have ES5, 6 or 7 code and it will transpile it all into the same JS type so it can run in all standard browser versions.

Basically the answer isn't to try and deduce what ES type your modules are, it's to create a build process that can handle the different types.

Jayce444
  • 8,725
  • 3
  • 27
  • 43
  • Thank you for the answer @Jayce444. Then the obvious question is, is there a generic method (I don't know, maybe a common configuration for webpack) that can take any installed React realted node module and spit out a version that browsers can understand. – Mehmet Kaplan Oct 27 '17 at 08:21
  • Like I said, Babel. Webpack and Babel are bestest buddies :D you'll find plenty of examples of how to configure babel with webpack for building your webapp, just Google around (here's one for example: http://ccoenraets.github.io/es6-tutorial/setup-webpack/). Remember, don't use the `babel-preset-2015` package, use the `babel-preset-env` package as that will handle *all* version of Javascript. And don't forget to view the Babel documentation for configuration options and more information on what it does/can do :) – Jayce444 Oct 27 '17 at 09:21