It was suggested for a react-native plugin that code on npm is best transpiled before publishing instead of relying on the end-developer to transpile.
Seems fine, but react-native users probably tend to have a very homogeneous babel-based setup, so perhaps it wouldn't be so problematic to just leave it in ES6. Fancy uses similar to react-native-web could be an exception where ES6 is rather inconvenient. But then sometimes I go digging in node_modules to see what's going on inside modules. Transpiled code would make that somewhat more difficult.
Question is: It seems like there's probably a most favorable, consistent answer. Is transpiling before publishing the right move? Am I inconveniencing people by performing this step?
Question is not: how to do this. This question addresses that very well.
Thanks!
To my mind yes, transpiling is a good step. We used it in react-native-drawer-layout, so we didn't have our users to enable certain babel features. On the other hand, the more Safaris JS engine reaches spec compliance with ES6, the more I would tend to say no, as transpiled code is almost always slower.
I would say yes - transpile now. Transpile for better compatibility with todays browsers. Re-transpile your package in the future (if you care), when more ES6 features will be supported by browsers - dropping some (now) transpiled code and going with portions of native ES6.
Related
I am trying to figure out how Babel gets used.
In one of my current projects, I see that I have a Babel file, but I never set up any configuration as far as I can tell that deals with Babel. So I want to know if it is actually being used or if I just have it installed.
When I deploy my React app to somewhere like AWS Amplify or Heroku, is Babel automatically being used and this is how my browser can understand React? Or would my browser understand React even without Babel?
You can not be sure that all versions of all browsers understand modern JavaScript. That is why, even if you write modern JS in your code, Babel will automatically turn it to plain vanilla JS so that it is compatible with almost every browsers.
This links I attached below, are of highlighted texts. Please give it a read as I believe it will clear up your confusions somewhat.
https://www.freecodecamp.org/news/jsx-in-react-introduction/#:~:text=But%20the%20browser,JavaScript%20compiler/transpiler.
https://create-react-app.dev/docs/getting-started/#:~:text=You%20don%E2%80%99t%20need,good%20to%20go.
I'm writing a library that exposes some React Components as part of its API.
I'm going to make a few assumptions here :
1 - It is going to be used inside react projects.
2 - Those projects will bundle their dependencies at some point.
3 - Those react projects can use JSX as a way of describing the UI.
4 - Their bundler of choice, Webpack if it's a create-react-app, will use babel in order to parse and transpile that JSX into vanilla JS.
Following that logic, I should be able export some JSX from an external package, because the package's code will be bundled, transpiled alongside the app.
However, when I do so in a create-react-app project, I get the following error :
SyntaxError: /Users/someone/Desktop/someproject/dist/esm/index.js: Support for the experimental syntax 'jsx' isn't currently enabled (35:13):
Add #babel/preset-react (https://git.io/JfeDR) to the 'presets' section of your Babel config to enable transformation.
If you want to leave it as-is, add #babel/plugin-syntax-jsx (https://git.io/vb4yA) to the 'plugins' section to enable parsing.
Yes, I could transpile the JSX, maybe I will. I just don't see any reason to, if it's going to be bundled anyway. I prefer leaving transpiling tweaking and optimisation to the user.
My concern is that if I transpile it myself, I have 2 choices.
import React in scope, and using babel to turn <MyComponent/> into React.createElement(), but this will rule out the possibility to use the new JSX transform
use the new JSX transform myself, and figure out whether or not my code will be compatible with react versions prior to 17. And increase my own bundle size because there is a lot of code added by babel to make that work.
At this point, I think I'm quite excited about this issue because frankly I have no idea why I can't just export plain JSX from my package. I know I'm probably missing something obvious, like a semi-colon or whatever, but I really want to understand.
If you want some code / rollup - babel configs feel free to ask.
Tanks !
Your logic seems to make sense at first glance. But let's examine why this is a bad idea.
JSX is a special syntax that must be transpiled down to the lowest common demoninator to be understood in the browser, or by Nodejs. This is what bundlers do, and as you mentioned, anyone working with react in a node environment is almost certainly using a bundler to do this.
However, there are any number of wierd syntaxes that people may use in their code. When a bundler imports code from a node_module, if the code in those modules is not already transpiled, the bundler would need to transpile them as well. Considering un-transpiled modules may be in any number of strange syntaxes, each module would need its own transpilation instructions (think babel configuration). Having unique transpilation configurations for every node_module would be very unwieldy, not to mention having to transpile each node_module, potentially in a different way, would be bad for performance.
The generally accepted best practice for solve this problem is to simply build your package using a bunder which boils the code down to the lowest common denominator. This enables your package-user's bundler to just bring in the code in a node_module "as is".
While its probably possible to come up with some crazy babe/webpack/rollup instructions to custom-interperet your module as JSX, do you really want your library users to have to do that? Especially in the case of people using create-react-app, customizing the babel config of CRA is not natively supported, which means they will need to take extra-steps to get your library to work. Additionally, webpack defaults to excluding node_modules from js transpilations for obvious performance reasons, and CRA follows this convention. When publishing libraries, you want them to be universally useable as easy as possible to consume.
Transpiling, tweaking, and optimizing code is best left to the person who wrote it, which in the case of a react component library you're trying to publish, is you.
I'm building my first semi-major MERN app with Redux, without a tutorial. It's really challenging, but a ton of fun.
The project I am building is, essentially, a simple re-engineering of Zillow's API (they have a few, I'm after the more basic of the property search results).
I am using the zillow npm module and want to add what appears to be a pretty popular autocomplete Search plug-in.
My big challenge this week has been diving into the build tools. I read thru the webpack docs over the last couple days, then felt solid enough to try building out my Search functionality, which will return results and a map eventually.
It should be noted, I'm using a scaffolding tool developed by a guy who publishes a lot of good React tutorials (from which I basically learned ReactJS -- it's called turbo360). Right now, I am using webpack 4. I just did a fresh git commit: https://github.com/ScorpIan555/real-estate-app/blob/master/webpack.config.js
I have, so far, read a bit of the Babel docs. I piped in .js extentions to the .jsx test for the babel-loader, thinking perhaps that would get it?
What I'm a bit confused by is that it seems to be tripping over a file written in ES5 (from the geocoder npm module I am trying to use). So, I'm wondering if I should be configuring my babel-loader to not try to transpile ES5 modules or what.
This is the module I am trying to utilize, it looks fairly popular and has a recent commit. I also looked at its webpack.config.js file and tried to apply that to mine...
https://github.com/abec/react-autosuggest-geocoder/blob/master/webpack.config.js
I am closing this as I received assistance on a Slack channel. This plugin uses experimental code which I do not wish to use on my app. I will use another plug-in. I was looking for help with my webpack.config and am reliably told it is fine. Thanks to all who viewed this question!
I have a React-webpack web app (client side only - no API server) and was tidying up the package.json file and it occurred to me that all of the dependencies are dev dependencies as you do not run the React web app in production - you build it and distribute the built files.
Is this right?
React and possibly ReactDOM would be dependencies. Any additional libraries you're using that appear on the page would also be dependencies (example: react-autosuggest). Everything else would generally be a devDependency.
There's no great consensus on this yet (see this webpack issue, for instance). Some folks want to do everything as a dependency, others as a devDependency, I'm sure you could make a case for bundled dependencies, etc. The solution I outlined above is a best practice that seems to work well. For example, if you're using a version range on a package, you likely wouldn't care about minor/patch version change to webpack, eslint, karma, mocha, etc. You'd most certainly care about even a patch level change to something like react, so it gets separated out into a much shorter dependency list. (Looking at one project, there seems to be a 4-5x difference between dependency and devDependency. It's much easier to spot the meaningful changes if you corral them into the dependency tree.)
Related: yarn takes the approach I outlined above.
I am updating the build process for an Angular 1.5.8 application, to allow development on Typescript.
After an over-complicated experience with Grunt, the current build process is simple and only uses Gulp and Browserify to build two bundles: my-lib.js and my-app.js. This way, the library, which is bigger, but more stable than my application code, doesn't have to compile so often and the compilation of the application-domain code only takes 0.1 sec. I am happy with that -- as well as the other developers.
Now we are looking forward to migrate to Angular 2.0 and want to start development in Typescript, but I'm not sure on how to integrate it on the build process and even the best approach on how to do it: should it be preferred to use tsc only to compile Typescript into Javascript and let Browserify handle the dependencies? Or should I use tsc as my main build tool and let it resolve dependencies, create mapping files and make the bundles?
Both Typescript and Gulp are evolving very fast and I cannot find documentation for this use on their documentations (1, 2). I would appreciate feedback from experienced people also working on the latest versions of these technologies.
Moving comments to answer:
We have doing very similar exercise at my organization, towards the end of it.
We have used webpack for most of the stuff, though webpack feels little grunt'y and after gulp, I am not a big fan of grunt.
We have used webpack to convert ts to js, bunding, minification. We have not used it yet for html to js string or css in js.
regarding the di part, you will have to worry about only js to ts. ts to js is not an issue as it is taken care by angular's string based di. regarding ts to ts, you will need to defined needed interfaces. Those will help you in moving those js to ts in future. Better to start with core components with least dependencies.
EDIT
Just to answer the part regarding the advantages of having gulp: specifically in the migration scenarios is, the upgrade is not going to happen in one go, so whatever is moved to TS should be handled by tsc and remaining by gulp.
Also gulp is much larger than just ts to js, we are still using it to create deployment package, inject js into html, fixing boostrap font paths, converting small images to base64, etc etc....
tsc has one purpose: to transpile (compile) typescript files.
gulp, on the other hand, is a build tool, which means it can run various tasks including compiling typescript, sass, minification, concatenation etc.
You can look here for an example on how to incorporate typescript and browserify using gulp: https://www.typescriptlang.org/docs/handbook/gulp.html
Another approach, is not to use gulp at all, but rather use npm scripts, you can see a sample here: https://medium.freecodecamp.com/why-i-left-gulp-and-grunt-for-npm-scripts-3d6853dd22b8#.a7lwcmpaf
I believe the absolute simplest way to do this is to use Zwitterion. You can read this article for a quick introduction.
Zwitterion allows you to include TypeScript directly into the browser through normal script tags. All features of TypeScript are automatically available, because the code is transpiled server-side on a file-by-file basis as it is served to the client. Under the hood, it uses SystemJS to emulate the real ES module loader behavior that will be standard in all browsers. If you need this to work in production, you can create a static build with Zwitterion. All of this eschews bundling, so you'll have to decide on what your needs are for performance. Personally, I'm betting on performance not being that big of an issue with HTTP2, and I prefer the simplest of builds to the complication that webpack and all of its friends bring.
As you are moving forward with typescript, my recommendation would be to integrate any module bundler such as webpack (my favorite) Internally it will use ts loader to transpile the code. Also along with compile, you would be able to use ts lint for static code analysis (webpack would take care of it). Webpack also helps if you want to have multiple modules created. Try out yomen https://github.com/FountainJS/generator-fountain-webapp . Once scaffolded you can refer to generated gulp files. It would give you an idea about typescript integration.
The best way to do this without overengineering your gulp setup is to use the plain typescript compiler:
1. Install typescript locally(it won't conflict with your global tsc):
npm i typescript --save-dev
2. Add tsc as npm script(inside package.json).
"scripts": {
"tsc": "tsc"
}
3. Create proper tsconfig.json for your needs and put it in the same folder as package.json
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
4. Use tsc compiler directly from gulp
var child_process = require("child_process");
gulp.task("build", function(cb) {
var tsc = child_process.spawn("npm", ["-s", "run", "tsc"], {stdio: "inherit", cwd: __dirname});
tsc.on("close", function(code) {
console.log("Tsc finished with code", code);
cb();
});
});
Tip. Use https://www.npmjs.com/package/gulp-sequence and vote up :)