Create React App 2.0: Babel 7, Sass, and More
reactjs.org
reactjs.org
I’ve been pretty happy with the team’s thoughtful approach to adding a dependency or not.
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.
Sometimes it gets confusing connecting the negative news of these large companies to their cool open source projects.
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)
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.
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
}
}Native TypeScript support will be a huge improvement.
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.
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.
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.
Untested and off the top my head but maybe something like:
type Values<T> = T extends { [K keyof T]: infer R } ? R : any type Props = {
age: number
name: number
}
type Values = Props[keyof Props] 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...
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.
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.
Oh wow, that statement is so much more than I'd have expected - there's something to look forward to!
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.
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.
[1] https://dev.to/daveirvine/postcss-with-css-modules-andreact-...
import styles from "./style.css";
<Component className={styles.myClassName} />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.
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.
(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.)
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 also didn't understand why so much functionality for different languages are harbored by a single tool, instead of multiple smaller tools.
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...
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.
How does staging fit in here ?
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?
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 didn't "eject", upgrading is as simple as 'npm update react-script'. This is the norm in JavaScript.