i18n message extraction in CRA using TypeScript - reactjs

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'

Related

How to install typescript + jest with create-react-app?

I want to install typescript and jest in a create-react-app-based app. I feel that since this is such a common installation choice there must be at least one "everything just works" set of configuration steps to follow.
I initially ran npx create-react-app my-project --template typescript. That was great for a while. I wrote several thousand lines of code with that. And then one day I decided I wanted to add some mocks to a spec file with code like this:
import jest from "jest";
jest.mock('./somemodule');
...but the "jest" instance is undefined. So I followed directions in different articles to install further devDependencies. But these seem to conflict with dependencies inside of create-react-app, suggesting that I need to focus on setting up my project correctly the "Create-react-app Way" according to its expectations.
Rather than burden StackOverflow with the details of my build and package management issues, I figure I'll just ask the simpler question - what is the correct way to set up create-react-app+typescript+jest in a way where it doesn't have a bunch of irritating, random problems?
And then after I've followed this advice, if I still have problems, I might ask a second, separate SO question with specific details.
The command below should create a new React project supporting Typescript and Jest without need of further modification.
npx create-react-app my-app --template typescript
Details about the above command can be found here: https://create-react-app.dev/docs/adding-typescript/
The above command will set up a new project. But if, like me, you have an existing create-react-app project with issues like:
the Jest module is undefined or doesn't seem to have expected functions
your npm run start and npm run build fail due to conflicting dependencies
or you just want to get to a "standard" package.json configuration without all the hassle of copying your source into a new project.
...you can use the process below to fix/upgrade your package.json:
Use the same npx create-react-app my-app --template typescript command above to create a separate working ("Good") project with all the right dependencies. This project will just be used as a reference.
Compare the package.json of the Good project to the non-working ("Bad") project, and make sure the Bad package.json has the same modules and version#s as the Good package.json. You probably don't have to delete any modules in the Bad package.json that aren't in the Good package.json.
rm -rf node-modules in the Bad project.
rm package-lock.json in the Bad project.
npm install in the Bad project.
Self-answering for posterity.

How to add custom webpack config with ionic v4 and react?

I have set up a project using ionic framework v4 with React and wish to add a webpack loader to allow importing graphql queries from .graphql files, as described here.
I can't find any official documentation on how to change anything relating to webpack (for example, nothing here), and existing answers on the subject seem to apply only to using Angular or v2/v3 of ionic.
The Apollo docs describe an alternative way of solving this for Create-React-App (which I may try as a workaround), but I might wish to change webpack config in other ways, so I am also asking how to solve this question more generally.
You can customize webpack using react-app-rewired
If you don't use ionic cli to build and run your app, you can use a normal install of react-app-rewired.
If you use the ionic cli, there is an additional step/trick:
Ionic uses react-scripts under the hood, so you need to trick it into using react-app-rewired instead of react-scripts.
Here is a simple and low-invasive way to have Ionic cli use react-app-rewired instead of react-scripts: add this package.json postinstall script:
{
"scripts": {
"postinstall": "cd node_modules/.bin && mv react-scripts react-scripts-real && ln -s ../react-app-rewired/bin/index.js react-scripts",
...
}
}
Update: This fails when you run ionic build because it defaults back to using react-scripts build.
Not sure why I didn't see this before, but taking a closer look at the bootstrapped ionic project, it’s clearly using create-react-app/react-scripts.
Although CRA demands you do a one-time eject in order to configure anything relating to the build, I was able to use react-app-rewired and customizable-cra to customise the build and start scripts. As far as I can tell this works fine with ionic.

How to edit config files in react-create-app?

I want to use some third-party packages upon react, which are:
https://ant.design/ - a design system
https://github.com/vazco/uniforms - for generating and validating forms.
I am using create-react-app for as a boilerplate
After installing all packages (with yarn) and running yart start I am getting this error:
How can I add #babel/plugin-proposal-class-properties without running yarn eject to modify .babelrc file?
Or is there any other solution for this problem?
It looks like the only way is to eject. CRA has purposely avoided too much customization. See https://github.com/facebook/create-react-app/issues/167

'Failed to minify the code from this file' appearing in create-react-app when trying to build production

I have created a react project using Create-React-App and now would like generate the production build. When I use npm run build I am getting the error:
Failed to minify the code from this file:
./node_modules/pify/index.js:3
Create-React-App suggests the following corses of action:
To resolve this:
Open an issue on the dependency's issue tracker and ask that the package be published pre-compiled.
Fork the package and publish a corrected version yourself.
If the dependency is small enough, copy it to your src/ folder and treat it as application code.
will take to long and seems to already be a issue (#50) raised for pify.
I am not sure how I would approach but I think it may be the best option
is not going to work because it is a dependency of a different package.
What I am looking for is come guidance on how to solve this solution before I use option 2 and rewrite a whole package.
I belive the solution would involve ejecting from create-react-app and messing with the webpack config file.

Configuration for create-react-app after ejecting to build a component library

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.

Resources