Hacker News new | past | comments | ask | show | jobs | submit login
Create React App 2.0: Babel 7, Sass, and More (reactjs.org)
200 points by stablemap 6 months ago | hide | past | web | favorite | 70 comments

I'm disappointed setting up typescript is still such a pain with 2.0.

Sorry. We needed to prioritize to get this release out because it's already been snowballing for about a year.

We actually did have "TypeScript support" on a nice-to-have list for this two week sprint but unfortunately didn't get to it:

https://i.imgur.com/l0CpdZy.png (I promise I'm not making this up :-)

I'm confident we'll ship it by the end of this year though.

> I'm confident we'll ship it by the end of this year though.

Oh wow, that statement is so much more than I'd have expected - there's something to look forward to!

There is already a pull request and it looks promising!


What is the status of Flow in the JS ecosystem?

Flow offers a more sophisticated type system that is designed to express types that correspond with the sort of idioms you see in JavaScript in the wild. TypeScript is simpler and less flexible, but that simplicity can translate into increased productivity since there are less foot-guns and also less bugs. Strange/buggy behavior and odd performances issues are not totally uncommon with Flow whereas TypeScript doesn't seem to suffer from this as much. Since TypeScript is much more popular, IDE support tends to be a lot better out of the box, but the flow-langauge-server gives you all the same IDE-like features (intelligent autocomplete, jump-to-def, module resolution etc).

Personally, I like Flow more, and I also think its easier to integrate into an existing codebase (either as comment annotations or gradually via per-file flow comment header), but at the end of the day, not choosing TypeScript amounts to swimming against the current without much justification.

> Personally, I like Flow more, and I also think its easier to integrate into an existing codebase (either as comment annotations or gradually via per-file flow comment header)

For several versions now, Typescript also supports type annotations in JS comments and an allowJS mode for mixing TS and JS in the same project, or using only JS and JS comment type annotations.

>Flow offers a more sophisticated type system that is designed to express types that correspond with the sort of idioms you see in JavaScript in the wild. TypeScript is simpler and less flexible, but that simplicity can translate into increased productivity since there are less foot-guns and also less bugs.

Source? That's the primary design principle behind TypeScript too. TypeScript's type system is powerful enough to practically do arbitrary type-level transformation of data structures, and even do some crazy recursive pure functional type level programming.

The only things I'm missing from TypeScript are variadic generics (which can be emulated quite well with TS 3.0) and higher kinded types - and I don't think Flow supports them either.


Most of that can't be achieved out of the box with TypeScript. TypeScript was designed as a language that would bridge the quality of life gap between es5 and more modern languages, Flow was designed exclusively as a type system for annotating standards compliant JS.

Are you aware the TypeScript has mapped types and conditional types[1]? The vast majority of Flow's type utils can be implemented in TypeScript, and many of them are included by default[2]. As far as I can tell all of Flow's utility types are compiler built-ins[3], but TypeScript's built-ins are declared using the type system itself (or are just natural parts of the syntax):

  type Keys<T> = keyof T
  type Values<T> = T[keyof T]
  type Readonly_<T> = Readonly<T>
  type Shape<T> = Partial<T>
  type NonMaybeType<T> = NonNullable<T>

  // Exact<T> cannot be implemented because TS doesn't have exact types as a separate concept,
  // It should be noted that object literals are exact by-default if there's a type annotation
  // Issue: https://github.com/Microsoft/TypeScript/issues/12936

  type Diff<A, B> = Pick<A, Exclude<keyof A, keyof B>>
  // Rest<T> should be equal to Diff, because TS doesn't have exact types

  type ElementType<T, K extends keyof T> = T[K]
  // PropertyType in unnecessary, because T[K] works for everything

  // Note that this is variadic - "Args" is an array of arguments
  type Call<F, Args extends any[]> = F extends (...args: Args) => infer B ? B : never

  // This works for both objects and tuples.
  type ObjMap<T, F> = { [K in keyof T]: Call<F, [T[K]]> }

  // I couldn't figure out how to implement Class<T>, but you can access the type of a class instance with
  // typeof ClassName.prototype 

  // $SuperType and $Subtype are not documented, so I can't try to replicate them.

  // TypeScript doesn't have existential types, but you can emulate them within the type system, or avoid them using e.g "infer"
  // Discussion and encoding https://github.com/Microsoft/TypeScript/issues/14466#issuecomment-338045331

I don't agree with your statement about TypeScript's design. Before ES6 TypeScript _was_ quite different from JS, but for the past 3 or 4 years it has followed modern JS very closely. The flavor of JS it supports is fully compliant with ES2018, and the ONLY feature with codegen impact it has in addition to modern JS and JSX are enums - which compile down to simple object literals.

[1] https://www.typescriptlang.org/docs/handbook/advanced-types.... [2] https://github.com/Microsoft/TypeScript-Handbook/blob/master... [3] https://github.com/facebook/flow/blob/cf03c08109014c4503a392...

Not true, most of that can be done with TypeScript. $Values might be the only one missing.

$Values should be possible with Typescript 3.0+ conditional infer types, presumably something very similar to the built-in ReturnType<T> conditional infer type.

Untested and off the top my head but maybe something like:

    type Values<T> = T extends { [K keyof T]: infer R } ? R : any

It works, just need to add `in` in-between `K` and `keyof`.

Looks like $Values can be written as follows in TypeScript:

    type Props = {
      age: number
      name: number

    type Values = Props[keyof Props]

Does Flow still run as a separate process? That is a non-starter for me.

A separate process from what? The IDE? Why would that be a bad thing?

The last time I used Flow it was intended to be used a daemon constantly watching your code. This made it really difficult to use with tools like Webpack which are built for "atomic" operations like tsc.

Everyone I know who uses it wishes they had gone with TypeScript. Anecdotal for sure, but I wouldn't be surprised if most Flow users felt this way - TS is winning in basically every way.

Thanks for the release regardless!

> Sorry. We needed to prioritize to get this release out because it's already been snowballing for about a year.

Why does the project generated by react-native-cli contains some flow syntax by default? this is stupid. Not everybody has a flow plugin for his IDE. And obviously flow type declarations are not valid JavaScript. I understand you want to push your stack onto your users but no need to be that invasive.

Exactly this. Create React App is awesome except its not TypeScript, and unfortunately the key point of Create Reacte App is that it is opinionated which is its magnificent strength, but it's opinion is not TypeScript as the primary language choice. It's a pity TypeScript isn't the default.

I'd list Create React App as the number one best JavaScript technology of all time, awarded for the massive pain saving it confers. It allows the most fabulous thing in the world, which is to avoid using the JavaScript tooling.

Worth noting that the CRA-TS project (a totally separate repo) is in the process of merging in the changes from CRA 2.0: https://github.com/wmonk/create-react-app-typescript/issues/...

Yeah these guys follow quickly, I've used this multi times and can highly recommend.

Really? If anything the move to babel 7 makes it easy, use babel-loader for .tsx?$ files with @babel/preset-typescript

I've setup about 4 projects over the past year, if you feel like you need help feel free to email me any particular pain points you have and I'll try to get you through them, email in profile (not a react contributor, just frequent react/typescript user on financial applications)

I'd actually love to see a good blog post that details the process of, say, upgrading from Babel 6 to Babel 7 for a non-CRA app, and then adding in some form of TS support on top of that. (I've got a couple apps that I'd like to try doing that with myself in the not too distant future.)

I don’t have a post but I took a half hour the other day and did it, it was basically:

Add typescript, babel typescript, add the plugin in babelrc, and update the Babel cli build command in package.json to look for ts file extensions.

That enabled me to start incrementally adding typescript into an existing node.js codebase, I was surprised how easy it was.

Here were the changes to get typescript working with an existing node.js codebase (babel 7)

package.json (scripts)

  BABEL_ENV=development babel -d build/ src/ --extensions \".ts,.tsx,.js\" --quiet --source-maps inline
package.json (add property)

  "type-check": "tsc",
package.json (dev depenencies)

  @babel/preset-typescript, typescript
babelrc (add with env)

  presets: ["@babel/typescript"]
tsconfig (example)

  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "declaration": true,
    "outDir": "build",
    "strict": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "skipLibCheck": true

Check out https://github.com/strothj/react-app-rewire-typescript-babel... for an example I helped get going. It was fairly straight forward!

Thanks, appreciate it!

They are independent, so you could read two blog posts, one for Babel 7 https://babeljs.io/docs/en/v7-migration and one for TS https://blogs.msdn.microsoft.com/typescript/2018/08/27/types...

Then you'd still need to explicitly do type checking, which is the primary advantage of TypeScript. I guess my IDE can do that, but then I'd still need to add an extra step to my CI server, etc.

Native TypeScript support will be a huge improvement.

+1 for TypeScript. The current existing ports of CRA for TypeScript are always behind.

Use ParcelJS and Typescript. Couldn't be easier.

From memory one of the issues on github says it's coming in 2.1. It just wasn't determined to be a "blocker" for 2.0.

TypeScript is fantastic for its IDE support and instant feedback but I'm waiting for the day it's built into CRA as a first class citizen. Sounds like that day will be soon though maybe even this year.

Why would facebook be interested in making it easy to use a technology that they directly compete against?

Speaking for the React team, we have little reason to suggest people use Flow over TypeScript.

I haven’t personally followed the status of TS in CRA closely, but I know it’s a popular request among our users so I would love for us to make it easy.

That's certainly comforting to hear, then.

Sometimes it gets confusing connecting the negative news of these large companies to their cool open source projects.

Eh, the React team in particular is pretty even-handed when it comes to what goes into CRA. This release, for example, adds support for Apollo, which goes head-to-head with Relay.

I’ve been pretty happy with the team’s thoughtful approach to adding a dependency or not.

> More styling options: you can use Sass and CSS Modules out of the box.

This is what I'm most excited about. Emotion is great but I've heard a lot of great things about CSS Modules, just haven't gotten around to trying them out yet because it's been so complicated to do. I'll definitely be giving it a try now.

I started my engineering career as a front-end developer when being front-end developer meant slicing PSDs to HTML trying to figure out the best way to implement crazy glassy and shadowy designs without transparent PNG support in IE6.

Starting using CSS Modules "properly" with custom built UI components library was definitely the biggest single improvement in easiness of delivering stuff I've experienced across the "whole stack", from the hosting situation, DBs, through popularization of MVC on the server and client side, micro-services to react itself.

Please do give a try. :)

One rule of thumb I passed on my friend learning working with CSS Modules: Never share styles between components.

Sometimes it's very tempting but instead try to compose your components in different ways.

You might want to share style or create mixin for white box with a border and shadow for 2 very similar components. Creating WhiteShadowedBox component even if it's a div with 3 lines of CSS is fine and will save a some headache later. Of course needs a better name. ;)

It's fine to use variables and mixins for "style config" like colors, font definitions, margin scales (0.8rem, 1.2rem, 1.6rem) etc but in my experience not much more.

I wrote a bit[1] about CSS Modules with React, but interestingly it looks like CRA isn't using babel-plugin-react-css-modules so I'm trying to figure out what they're doing instead.

[1] https://dev.to/daveirvine/postcss-with-css-modules-andreact-...

It's perfectly fine to just use css-loader to handle CSS modules. No need for babel. Just do:

   import styles from "./style.css";

   <Component className={styles.myClassName} />

I can't imagine using anything other than styled-components... Are there advantages to using CSS Modules instead?

Every time I look at the docs for another styling solution I just see unnecessary complexity for no clear benefit. Styled components are so easy to reason about and organize, especially when doing conditional / state based styling.

These are some pretty great improvements. I never felt I had to have cssmodules or sass, but I’ll definitely use them. Great work!

If you don't feel the need to add another dependency, why would you do so?

I see Facebook’s React team is in the comments. Please keep in mind that the open source aspect of React is part of Facebook’s hiring strategy. While I believe the React team are genuine in their friendliness and passion for their work, they also represent and are payed handsomely by one of the worst offenders in surveillance capitalism.

(I realize some might feel a comment like this is out of place here, but considering the recent news about enormous leaks and privacy violations, I think it would be more strange if it wasn’t brought up.)

I decided to finally bite the bullet and learn React yesterday. Every time they mentioned "we do it like this at Facebook" in the tutorial/docs, my eagerness died a little more. Even little tongue-in-cheek things, like their shopping list app consisting of companies they've acquired (Instagram, Oculus, WhatsApp) felt like a bummer.

Hey, thanks for feedback!

Regarding "we do it like this at Facebook" -- could you point out examples where this isn't useful, and we could remove them? I wrote some of these, mostly to highlight that if something works for a massive codebase with 50,000+ components, it will probably work for yours, even if it doesn't look familiar. I don't know what's an alternative way to say it without losing the core of the message.

Regarding the tongue-in-cheek one. Well. I don't feel strongly about changing it if many people feel this way.

I tried Babel some time ago, but I can remember it was painfully slow. Has this improved?

I also didn't understand why so much functionality for different languages are harbored by a single tool, instead of multiple smaller tools.

I'd say 'multiple smaller tools' is actually what Babel has become. It started out as a tool to compile ES6 to ES5 (6to5 it was called), but now it's a kind of framework(?) that you can add various smaller packages to for various 'transpiling' purposes.

Stoked to see service workers will use Workbox!

Thanks for all the hardwork. I used this library when I worked at Uber and Netflix.

Is it possible to use Redux without an eject?

Absolutely - all you've ever needed to do is `npm i redux react-redux`, then add them to the app. They're just libraries, no special behavior needed.

See the "Configuring Your Store" docs page [0] for copy-pasteable examples of adding Redux to a React project.

Also, we're working on a `redux-starter-kit` project [1] that will soon become an official Redux-branded tool to help with common pain points, like setting up the store properly, simplifying immutable reducer update logic, and more. I talked about it in my React Boston "State of Redux" presentation [2] over the weekend. Please try it out, and let us know how it works and what else we should add!

[0] https://redux.js.org/recipes/configuringyourstore

[1] https://github.com/markerikson/redux-starter-kit

[2] https://blog.isquaredsoftware.com/2018/10/presentation-state...

You can add any JavaScript library without ejecting. Unless it demands changes to your build process.

It always been...

and redux-saga?

Of course redux-saga can be used. Unless your goal is to rewire the project compilation step, ejecting is rarely required.

Forgive me. What is "eject"?

The Create-React-App tool hides all of the Babel and Webpack configuration by default. The only dependency you have in your app is the `react-scripts` package.

This drastically simplifies things for your app, and means you can get the latest build system updates with a single update command whenever a new version of `react-scripts` comes out. However, it also means that if you _do_ need to modify the configuration in some way, it's normally inaccessible.

CRA includes a one-time `npm run eject` command that copies over all of the actual dependencies and config files into your project. "Ejecting" means you're taking ownership of those config files, and also means you lose the ability to easily upgrade with a single command.

You can even change some webpack configs without ejecting using react-app-rewired. Its pretty nice if you only care to change one or 2 simple settings. (like name of build files, babel plugins, etc...)


How difficult would it be to use this to add a staging environment? It seems like that's the only build config change that I ever desire.

I'm not sure with what you mean by staging environment in this context. You can run your app in a webpack-devServer or build it then use your own server.

How does staging fit in here ?

Thanks. That sounds like a pretty elegant way to hide all that complexity. Let's hope things continue to converge and simplify into a more universal set of standards, defaults, and built ins.

So sort of like what forking does on a Github repo?

> If you previously ejected but now want to upgrade, one common solution is to find the commits where you ejected (and any subsequent commits changing the configuration), revert them, upgrade, and later optionally eject again.

That seems insane to be honest, yet it's seems to be the norm to upgrade a framework in JavaScript (same with React Native). Is that the best solution there is? In many other languages, you can upgrade a framework without reverting commits or trying to figure out what to keep or change in huge diffs. Surely there should be a way to keep the base config untouched, and have user changes in a separate config that overrides the base on?

Create React App is not a framework, it is more similar to a scaffolding system that sets up a group of tools and processes. You can upgrade React normally without issue.

The equivalent to what you suggest would be to autogenerate some files with a tool, modify the location and structure or those by hand and then expect the tool to be able to modify then again seamlessly.

If you "eject", you are not supposed to be able to upgrade. Hence the hacky workaround.

If you didn't "eject", upgrading is as simple as 'npm update react-script'. This is the norm in JavaScript.

Perhaps! 2.0 has Babel Macros. I think this may allow user changes to config without rolling the react-scripts package to npm with your changes.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact