Share codebase using common Sdk module in create react app Reactjs application - reactjs

I want to start a new app that will have both web and reactnative interfaces.
I decided to move all business -non enviroment dependent- code into a third package -aka sdk- that i can share between both react & react native .
So my project now has 4 modules
Web -- created with cra
Sdk -- mainly redux + redux saga + react containers + Hoc's
Mobile -react native
Server - nodejs express api.
All web, mobile and server will depend on Sdk module.
sdk module will depend on server module -mainly to impory mocks and data interfaces.
Is there any standard way to achieve such structure ?
Most probably i would love to
use yarn workspaces to hoist all node-modules into one folder to avoid reinstalling packages in every project
i will be working in all 4 projects at same time, so i need hotreload to be aware of this.
** challenges im facing **
Cra doesnot transpile code outside src folder so although web project does refresh qhen i make changes on sdk. It cannot understand es6 code.
Jest also doesnot understand es6 from node_modules
How can i avoid rebuilding step while working on both sdk and web modules simultaneous ?

Yarn workspace sounds like a good approach for the project structure you're thinking.
You can have a packages directory where you can add your projects:
/packages
- web
- sdk
- native
Now you can use babel to watch for code changes for each of your package using babel -w and yarn workspace will take care of linking them together.
If the babel watchers are running, any changes that you make to the sdk will be reflected to both web and native packages. You can also club all of these together using something like concurrently to fire up watchers using a single command.
I have co-authored an open-source library where we follow a similar structure which you may check here. The difference in this project is that our redux logic is in a separate repo.
In order for jest to work, you can add a test env into your .babelrc file which transpiles modules. So you can add two different environments like test which transpiles into commonjs modules and an es environment which keeps ES modules so your users can take advantage of tree-shaking. Example config
Hope this gives you a good starting point :)

You could try a Project structure like this:
| package.json
|- node_modules
|- Web
| package.json
|- SDK
| package.json
|- Mobile
| package.json
|- Server
| package.json
Then you could install everything within the root folder and set the NODE_PATH env variable :
export NODE_PATH='yourdir'/node_modules

Related

Should we bundle shared component library separately in lerna monorepo?

I have three packages inside standard lerna monorepo.
client
react library
core
Core - is a shared component library with some utils (may or may not publish on npm).
React library is component library which will be shared on npm.
client is a bundled js library which will be consumed in browser with static html files.
core is a dependency in react-lib as well as client
Question 1 - How to setup core, should I transpile with tsc and bundle with tools such as rollup or vite (i personally prefer vite/rollup over webpack). or just leave it as is and import it in client and react-lib with absolute paths like 'core/src/*"?
Question 2 - can i build core in 'es' format and build client just like normal react app with either cra or vite. I tried this but i think i am missing something as final bundle doesn't seem to work in browser.
Any help would be really appreciated.
You have a few questions and I might not be able to answer them all but hopefully enough to guide you for the solution you're looking for.
Core - is a shared component library with some utils (may or may not publish on npm).
If you want to use Lerna then I guess you'll have to eventually publish the package on npm or a private repository. As an alternative, you could also use pnpm workspaces and their workspace: protocol which will allow you to link the packages in your workspace (monorepo) without ever downloading them from npm, for example if you use workspace:* then it will always use and link to the latest code from your local workspace. You could also use workspace: protocol with Lerna (or Lerna-Lite) since they both support it.
For your next Questions, I'll answer the last part of your Question 1 first because that affects the other portion of the question.
Question 1: ...or just leave it as is and import it in client and react-lib with absolute paths like 'core/src/*'?
Use absolute paths outside of the package is not a good thing to do since it will only work on your local project and you cannot publish that to npm since it will be broken for the other users. It's better to stick with the workspace and let the package use the main or exports entries defined in your package.json. In other words, it's preferable to always build/transpile and let your other package use the transpiled code and if you need to debug then make sure to also include sourcemap
Question 1: How to setup core, should I transpile with tsc and bundle with tools such as rollup or vite (i personally prefer vite/rollup over webpack)
It probably doesn't matter which one you use TypeScript, Rollup or WebPack, In one of my project I use TypeScript in watch mode, it will auto-transpile whenever you change your code, the downside is that the more packages you have then the more TypeScript threads are opened in watch mode (1x per package) but in your case if you only have 3 then it's fine, there's also this TypeScript issue that I'm following which will hopefully bring multi-threaded compilation in the future. You could also use Rollup and the concept would be the same, use it in watch mode for each package (I've done it with Vite/Rollup using vite build --watch
as explained in the next paragraph).
You can take a look at a project I've done Vue 3 and pnpm workspace using pnpm workspace with the workspace: protocol, it uses Rollup for transpiling and also uses Vite library mode which allows to bundle your library for distribution (on npm or others...), this allows you to bundle each package as a lib that is easily reusable by other projects. It's a Vue 3 project, so it's not a React project but it should give you enough ideas on how to do in React and it should help to answer your Question 2. Also that project is not using Lerna/Lerna-Lite but since it uses the workspace: protocol then it would be super easy to add Lerna on top of it in the future (basically just adding the lerna.json config should be enough)

Sharing code between a Typescript React project and a Typescript Express project

I have been trying to come up with an elegant solution to share code between two projects that are closely related to each other.
I have a React web app which simply includes all of the client code and I have an Express app which serves the React web app, but it also acts as an API. Because I use Typescript for both projects, I want to reuse some types. To accomplish that, I created a shared project.
My current folder structures is as follows:
web-app
shared
server
Now I want to link the web-app and server projects with my shared project, but there are some restrictions:
This shared folder should not be uploaded to npm.
I have to be able to still deploy everything with Heroku (which rules out npm link I believe).
I would prefer not to eject my React project.
I am not sure whether my current structure of projects allows the functionality I need, so feel free to also suggest other folder structures.
You can use yarn workspaces for that kind of purpose,
There's a minimal working boilerplate I have created exactly for that kind of configuration:
https://github.com/rok-tel/ts-express-react
take a look at ./packages/shared folder which is consumed both by server (express) and client (react)
Consider use Nx - https://nx.dev/
This is an awesome framework to manage monorepos.
Use their React application boilerplate for the client side project
Use their express project boilerplate to create the API
Use their shared code package boilerplate to create shared code package
Docs for creating the shared code package:
https://nx.dev/l/r/tutorial/07-share-code
If you are using create-react-app to create the web-app then you can easily use NODE_PATH environment variable to do absolute imports without creating node modules.
Create a .env file at the root level (same level as package.json of web-app directory)
Set an environment variable, NODE_PATH to shared/ (NODE_PATH=shared/)
Now instead of doing something like
import { editUser } from ‘../../../shared/actions’;
you can use
import { editUser } from ‘shared/actions’;
Fixing ESLint
Install eslint-plugin-import to prevent eslint from throwing import errors. And update your .eslintrc file as
{
"settings": {
"import/resolver": {
"node": {
"moduleDirectory": ["node_modules", "shared/"]
}
}
}
}
Fixing Flow
Add the following content to your .flowconfig file
[options]
module.system.node.resolve_dirname=node_modules
module.system.node.resolve_dirname=shared

Does a React application HAVE to run on its own server process?

I come from a background in Angular, but I wanted to start learning React. I want to make a React front-end for a nodejs Express web service.
In Angular, I could simply build the source code into a static folder with a standard index.html, and it can be deployed on any web server. With React however, every tutorial I see is about running React in its own server using create-react-app and npm start.
I know you can also just use script tags to import the React framework in a static page, but then you can't use JSX syntax, and I would like to. Is it possible to simply build a React project into a static folder with an index.html that can be deployed on any web server?
Yep, you can do what you're describing. If you want to use JSX syntax, you'll need Babel, which transpiles it into standard JavaScript.
You can avoid the complexities of setting it up by using create-react-app to create the app, then running npm build instead of npm start. This will compile everything into a build directory, complete with index.html.
CRA uses its server for development purposes. You don't need CRA for using React of course. But, as your app getting bigger and bigger you will need some more extra tools. For example you want to see your code instantly without refreshing your browser. Here comes the dev server and hot reloading.
CRA uses Webpack behind the scenes. It is a great tool for bundling (obviously) all your files (including css), minifying, uglifying, optimizing your code etc.
For simple code or testing purposes using one file and attaching React and Babel to your file could be enough but for real apps you will need more. Either you will use something like Webpack on your own or you will use CRA and let it do all the extra stuff for you.

How to use ReactJS in hybrid scenarios

I have an existing MVC project built with Yii2 (a PHP framework) which generates and serves HTML pages.
I'd like to write just one complex Component (with 3rd-party modules and a lot of other dependencies) only for a page (generated by Yii2); so it's important to clarify that I don't want to leave all the frontend side to ReactJS and I don't want / can't migrate to a complete frontend app managed by ReactJS.
What's the best way to integrate ReactJS (with its stuff like npm, Webpack, etc)?
Should I write the ReactJS app in a "npm environment", bundle everything and include the "build" static resources into the Yii2-generated page?
For complex scenarios it is better to use "npm stack" to build your assets and create asset bundle to only register files generated by tools like webpack or gulp. Yii tools for compiling and compressing assets works fine for simple cases, but they're very limited when you compare it to tools from npm ecosystem.
You could look how official website of Yii Framework was build: they used yarn and gulp to build frontend assets and one simple bundle to register generated files. The main difference from normal "npm fronted flow" is that they used assets-packagist to install frontend dependencies.

Bundle with react js

I am a beginner with reactjs so I start to create a site, I do all installations, I installed Webpack to generate automatically the bundle.js all it works well and the file bundle.js is well generated but nothing that posster on the index page (page index is empty) and there are also no errors on the console. Somewhat help me please
It can be a bit messy to get up & running if you're not experienced with these technologies and how module bundling in Webpack works.
This is exactly why Facebook created the "create-react-app" solution so that you can get running without any build config and focus on creating the app that you're after instead. You can use it and "eject" to a custom setup anytime and see how they've done it:
create-react-app by Facebook
Here is a guide that you can follow along to create a simple config build:
Setup a React Environment Using webpack and Babel
You can also check out some of the other solutions that the community offers, here is a list of 143 React starter projects:
Find your perfect React starter project

Resources