I use facebook's create-react-app, which intentionally hide all the configuration setup, and leave us with a lovely simple file structure
That's great! but there's one really annoying thing that come up:
SublimeLinter is no longer works
because the .eslintrc configuration file is not longer at the root of the project.
Key points
I know I can put another .eslintrc file at the root,
but I would like to be able to set my rules in one place
I know it is possible to npm eject to get the entire project structure out in front, but I would like to keep things simple. otherwise it becomes just another boilerplate
I noticed that in the package.json
What I already tried?
a direction I thought about is to change:
"eslintConfig": {
"extends": "./node_modules/react-scripts/config/eslint.js"
}
to:
"eslintConfig": {
"extends": "./.eslintrc.js"
}
but it seems to require all the eslint-plugins (which are magically hidden from node_modules) so I'm not sure it's the right way.
Any insights?
SublimeLinter is no longer works because the .eslintrc configuration file is not longer at the root of the project.
This is not correct.
SublimeLinter will work just fine but you currently have to install a few things globally. The generated project’s README includes the instructions to get linter IDE integration working:
Finally, you will need to install some packages globally:
npm install -g eslint babel-eslint eslint-plugin-react eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-flowtype
We recognize that this is suboptimal, but it is currently required due to the way we hide the ESLint dependency. The ESLint team is already working on a solution to this so this may become unnecessary in a couple of months.
This is, of course, assuming that you’re fine with the ESLint configuration we picked for you.
Related
I have a an .eslintrc.json file whose rules my code is obeying. Except the "no-unused-vars" rule.
It works in my editor, that is, the unused vars are no longer highlighted red, but when I run the app in the console the console throws the warning. It's like they're using two separate configs or something. It's a create-react-app.
Stop your app, run rm -rf node_modules/.cache/eslint-loader, then start it again. If that doesn't work then your editor is probably using a different eslint config than your app, but it's hard to say without looking at your setup.
Either way, check out CRA's official documentation on extending ESLint rules, or even better, use something like craco, react-app-rewired or customize-cra to get complete control over your ESLint config without having to eject from CRA.
As it turned out, the only thing I needed to do was add a .env file in my project root with this:
EXTEND_ESLINT=true
Then everything worked fine. I love simple solutions but my lord was that tedious! :)
I created a react project using npx create-react-app my-app --template typescript. And I found that somehow typescript-eslint is already enabled by default.
I checked the eslint config inside of the package.json
"eslintConfig": {
"extends": "react-app"
},
I thought in order for typescript-eslint to be enabled you would need either "extends": ["plugin:#typescript-eslint/recommended" in your package.json or .eslintrc. But in this case I cannot find either one of these in the codebase. I wonder how the eslint for typescript got enabled?
CRA is intended to be a one-stop shop for setting up your react app. This includes build configs, folder structures, and everything required to develop a react app with the best practices.
Whilst not really explicitly listed anywhere, CRA comes with a preconfigured linting experience using the eslint-config-react-app config.
On their main page, they mention:
Under the hood, we use webpack, Babel, ESLint, and other amazing projects to power your app. (emphasis mine)
It's also mentioned in places like the IDE experience, but in a "you should already know this is a thing" kind of way:
https://create-react-app.dev/docs/setting-up-your-editor/#displaying-lint-output-in-the-editor
For typescript projects, the CRA config ofc includes tooling from the #typescript-eslint project, as it is the standard for linting typescript code.
Without using this project, they would run into many issues attempting to lint typescript codebases (the biggest being that it wouldn't work at all).
The above docs contain information about how you can further configure your linting experience if you want.
Stripped down demonstration - GitHub
We currently have a create-react-app project that is undergoing an incremental migration from Flow to Typescript. This meant disabling some undesirable ESLint rules. In order to customise ESLint, I've added EXTEND_ESLINT=true to the .env file.
Before adding this setting, my Typescript code compiles fine. Afterwards, I get parsing errors on certain (but not all) Typescript grammars.
// Type guards
export function f0<T>(x: T|undefined): x is T { ...
// Constrained generics
export function f1<T extends number>(x: T) { ...
// Type assertions
... return x as T
There may be other unrecognised syntaxes I haven't found yet.
So far
I haven't found any similar problems or bug reports. I understand some Typescript features are not available in the current CRA version, such as const enum, but I haven't found any mention of the features listed above. I am also pretty sure my Typescript and ESLint versions are compatible with typescript-eslint.
I've tried many different .eslintrc combinations. I've left a few of the most promising in the .eslintrc.js file in the attached repository. The current setup is the one recommended by create-react-app, where Typescript linting is set up in the overrides section.
The ESLint Typescript configuration was set up following instructions from the typescript-eslint monorepo, in particular, typescript-eslint/parser and typescript-eslint/eslint-plugin
Solutions
Ejecting is not an option. If no other solution can be found, I would rather just do the Flow -> TS conversion in one go.
We currently extend our CRA configuration with customize-cra. Solutions involving this are welcome.
I enjoy the flexibility the .eslintrc gives me but I am happy to do away with it, provided I can still set lint rules.
Notes
I've included customize-cra in the demo repo to accurately reflect our project, but the problem persists without customize-cra, indicating that it is likely not the culprit.
See src/components/TestComponent/fn.ts for examples of the problem syntax.
My current hypothesis is that there's some setup in the CRA ESLint config that doesn't get carried over when EXTEND_ESLINT=true.
Updates
I've opened an issue at create-react-app
Partial workaround listed on the issue. Still not ideal.
UPDATE: Update react-scripts to latest version at least 3.4.1. It's fixed.
For pre 3.4.1 versions of react-scripts,
Open node_modules/react-scripts/config/webpack.config.js
Replace code block from line 365 with this code.
if (process.env.EXTEND_ESLINT === 'true') {
return undefined
} else {
return {
extends: [require.resolve('eslint-config-react-app')],
};
}
})(),
useEslintrc: process.env.EXTEND_ESLINT === 'true',
Now if you start your app by yarn or npm, you will see it is fixed.
The fix is originally introduced here
https://github.com/facebook/create-react-app/issues/7776#issuecomment-567587642
Run npx patch-package react-scripts to make a patch for it.
And add "postinstall": "patch-package" to your package.json scripts section.
The patch will be automatically applied after npm install
For anyone else encountering this issue, there is an open issue at CRA which seems to be the cause.
I'm trying to get i18n message extracted (defined by react-intl's defineMessages) to work properly in a CRA using TypeScript.
I've got an existing react app bootstrapped by CRA with a couple of hundrets of lines of code. So rewriting the application w/o TypeScript isn't an option.
Here's what i've tried so far:
First Attempt
Following this guide in order to get it to work.
When closely following the guide (although react-intl-cra is deprecated) the language files will generate properly.
However if you create the app using create-react-app react-intl-example --typescript and change the script to
"extract:messages": "react-intl-cra 'src/**/*.{js,jsx,ts,tsx}' -o 'src/i18n/messages/messages.json'"
it will break with a compiler error.
Second Attempt
Since react-intl-cra was refering to a react-app-rewired solution, I've tried adding it alongside customize-cra and babel-plugin-react-intl to a freshly generated CRA (using TS). However no luck there as well and after some short period of research I found that it's officially not supported.
Third attempt:
Adding extract-react-intl-messages to my project and running:
$ npx extract-messages -l=en,ja -o app/translations -d en --flat false 'src/**/!(*.test).tsx'
failed with an error as well.
I ran out of ideas, hence I came here to ask. From what I've seen TypeScript has been well advertised in the last couple of years and I don't think I have to justify that React is still pretty hyped. Moreover I can't imagine, that i18n is an uncommon concern in application development.
However I wasn't able to find any up-to-date guide or anything useful on npmjs.com.
TL;DR;
What I need:
Extract messages from defineMessages from react-intl into json files
Must work in a CRA using --typescript
Should not utilize npm run eject
What I've tried:
react-intl-cra
react-app-rewired + customize-cra + babel-plugin-react-intl
extract-react-intl-messages
It's explained here: https://github.com/akameco/extract-react-intl-messages#typescript
Basically you need to
npm install --save-dev #babel/core #babel/preset-typescript #babel/preset-react
and add
#babel/preset-typescript
to your .babelrc:
{
"presets": [
"#babel/preset-react",
"#babel/preset-typescript"
],
}
Then you can run
npm run extract-messages 'src/**/*.[jt]sx'
I started to build a component library that I want to publish on NPM (and reuse in other apps) by creating a React app using create-react-app. Unfortunately the create-react-app default configuration doesn't seem to support building such component libraries (see these issues). So it seems I have to eject.
Do you have some instructions what to configure after ejecting to make this a component library I can reuse in other apps (I guess some Webpack stuff)?
Re-framing my comments into an answer.
Don't eject! CRA hides a lot of stuff under the hood and ejecting throws it up. It's relatively easier to just clone your src into another project with the tooling setup done.
And it's not very difficult to setup one yourself! Here's the things you will need to do:
Basic babel and webpack configuration so your code compiles.
Make sure React and React-DOM are added as external dependencies in your package.json file and added as alias in your webpack.config.js. (A thorough discussion is here.) This is important to ensure you ship the smallest bundles only. Also, React doesn't play well with multiple copies.
Optionally, do the same for any other heavier libraries, e.g. Material-UI, Bootstrap, Lodash etc.
In webpack's configuration, decide how you want your library exports should be? You should be good with UMD.
Add main (and optionally module) entries in your package.json to let npm imports know where the components should be imported from.
Publish it.
Done!
Or, you can simply clone one of these super thin component projects and put in your components there -
https://github.com/wangzuo/react-progress-label
https://github.com/aaronshaf/react-toggle
There are more complete starter-kits as well, but IMO it's important to first know the details yourself before you abstract them away. Once you are familiar with the process, you should try leveraging the kits too as they go much beyond the basics, like test integration, react-storybook support and great npm publishing support.
UPDATES:
The purpose of CRA is to allow quick experimentation and on-boarding to React development, without going through the (somewhat complicated to a beginner) tooling setup. The intended use case of CRA, as denoted by the "App" in the name, is the whole app, not a component. Although developing anything built on language features like ES6 takes some tooling, an app typically takes more setup than a component. E.g. you also need a server component which hosts the generated code. CRA does all this and more for you.
And if you are working on an app, you will eject when you want to take control of the server side of it. It adds value in that case as you will get the basic hosting code auto-generated by CRA during eject.
To address test needs, CRA also has Jest integration, which is a test runner having React specific features like snapshot testing. Again, setting it up manually with your build pipeline is a handful and CRA once again hides all of this complexity from you, so you can simply focus on writing the tests.
This is super simple - you don't actually need webpack if you want to publish a package. Don't install it just for that if you don't want to.
If you use ES6:
You can use a simple script to create a dist folder that babel will create the files after transpiling:
"scripts": {
// other scripts
// .. might want to change "rm -rf" below if you're on a PC
"build:production": "rm -rf es && cross-env NODE_ENV=production node_modules/.bin/babel ./src -d es"
},
What this does is:
Remove the es folder, which is a build folder.
Runs babel for your files (in case they are located in src folder, change it to wherever your files reside) and create the es folder with the transpiled files.
In order to use the script above you need to install the following dependencies:
babel-cli / babel-core / babel-preset-es2015 / cross-env
Make sure you have a .babelrc file so that babel will work:
{
"presets": [
["es2015", { "modules": false }]
]
}
Now all you have to do (after running npm run build:production) is to run:
npm publish
And your library is published in npm. This is also the command you run if you want to update, just don't forget to update the version number in your package.json.
In case you have files you dont want published to npm, just have a file in your root called .npmignore (similar to .gitignore) and list everything you want excluded.
If you don't use ES6:
In this case you don't need to transpile anything, just go straight to the npm publish section above and run it on the root folder you want published.
create-react-app is meant for quick setting up and development of apps, not really for development of libraries. For one thing, create-react-app creates an index.html file when building, which is usually not needed by libraries. Libraries require a different set of configuration (much less).
I faced this problem myself and have written a React component boilerplate for writing and publishing React components: https://github.com/yangshun/react-component-starter, after referencing how popular ES6 libraries were written, such as Redux.
Pros:
Similar to create-react-app, batteries are included
It has got all the important areas covered: development, linting, testing, and distributing
Minimal configuration
Babel for transpilation to ES5 and CommonJS format
ESLint included and configured
Jest tests examples
Webpack configuration that compiles to UMD
React Storybook for quick development of the components
Support for stylesheet distribution alongside your component
Cons:
Highly opinionated in terms of choice of tooling; they follow the choices set by create-react-app.
Have to manually update each package dependencies in future (you'll face this issue if you did eject anyways)
There is minimal configuration included and setup is easy. The various webpack, Babel and ESLint configurations should be quite understandable.
Hope this will be helpful to you. Feel free to give suggestions and comments on how it can be improved.