Hello everyone I have a Yarn, Turborepo monorepo. I have 2 Next apps that share some UI components
src
|- apps/ the next js apps
|- packages/ui the UI library
I am unable to add SVGR as I don't have webpack, I use NextJS transpile to get the library into my project. What are my options to import SVGs it my code? I am currently failing during the build
My setup is the same as this
Most of my confusion comes from how the compilation and builds happen with monorepos
Next transpiles the library, but library itself fails during build as SVG files cannot be imported
Basically I am trying to do this
import Star from './star.svg'
In a shared library like this
Do I need to create a react app for this? I am suspecting that I need a more complex setup with proper build step, outputs and entry point for the types
Related
Recently, I started working with React js and am interested to learn more about Storybook.
Created custom react storybook typescript library with a roll-up.
It was working fine [with plain .css file] where I consume it until I install styled components into the custom react storybook library after that it is not working well where I use that library [into different project]
But in both cases, it was built successfully in the custom library folder.
custom library's package.json
custom library's package.json
custom library's rollup configuration file.
custom library's rollup configuration file.
It failed with the below-console error when I tried to use it for a different project.
console error in different project
I am making an application which is divided into two parts, one is a user facing application that will be directly used by the end user lets call it EndUserApp.
Other is a admin / seller application which will be used by seller, admins and morderations, lets call this SellerApp.
These two applications have a lot of UI components in common and have same UI theme and design, so i create a third app, lets call it EComUI
All these apps are inside a monorep which is managed by lerna.
So now I need to import components from EComUI into SellerApp and EndUserApp.
There are two ways this can be achieved,
We can create EComUI as a compiled UI library, which uses a webpack-server(or anyother) to build components and add this lib as a dependency in both SellerApp and EndUserApp and then use it as a normal node package.
The other way is to import the components directly into SellerApp and EndUserApp, from workspace like EComUI/Button.
i have seen both implemented, both of these work, the 2nd method has an advantage of not needing to create a build over and over again or have an additional dev-server running while coding.
While the 1st one has an advantage of being a complete package in itself, that can be moved or uploaded to NPM later on if required.
How should I implement a shared UI lib in a react monorepo? Is there any important drawback that any of the two proposed methods that I'm not seeing?
Why not both?
You can get the best of both worlds by making your library a workspace inside your monorepo. That means that you can effectively import your components directly in the application if needed, while also defining transpilation steps inside the package itself. This makes it easily publishable to npm as the workspace itself is a package.
By having a project structure similar to
/apps
|_ /EndUserApp
|_ package.json
|_ /SellerApp
|_ package.json
/packages
|_ /EComUI
|_ /lib
|_ /src
|_ package.json
You can have both the transpiled version of the library for publishing to npm as well as the sources.
With such a structure you can even choose whether to use library sources inside your apps and transpiling them via configuration specific to the project (minimizing bundle size by dropping backwards compatibility is a thing that comes to mind for newer projects) or the already transpiled version.
I'm trying to use Lit.dev to create reusable web components across my organization, and I'm trying to import one of those components into a new React project using create-react-app
I started by creating a local Storybook project to make sure my components rendered correctly, which they do (see screenshot)
I pushed library of test components to my GitHub account, then I installed to a boilerplate create-react-app project using npm i https://github.com/my-user/my-design-system/, which added my library of components to /node_modules, which I can import into a React app using
import `my-design-system/MyCustomComponent`
For simple components, this is straightforward, and I can successfully render my Lit-created web component in my React project, but for components that use things such as #decorators or importing Sass styles, I get errors. For example:
Module Error (from ./node_modules/sass-loader/dist/cjs.js):
Cannot find module 'sass'
etc...
I feel like I could solve this problem by configuring my React project to use the appropriate loaders and TypeScript configs, etc., but I feel like this is defeating the purpose of creating an external web component library to be framework agnostic. I feel like I am most likely missing a step that converts or builds my Lit project into a JavaScript bundle that other projects can use without much fuss (right now, in my React project, I'm just importing my web component straight from the source file in node_modules/my-design-system/MyCustomComponent
I'm completely new to creating my own packages, so I feel like I lack the vocabulary to accurately describe what I'm trying to accomplish. Can anyone point me in the right direction?
I have a React project created with npx create-react-app where I implemented a handful React Components. I don't really see this project as an "React application", as it's just a personal library of Components I consume in another project, an HTML web application rendered using server-side technologies. My goal is to gradually replace parts of this application with React components. I don't really envision it becoming a single React application, my plan is just to replace the parts I think make sense to be developed with React.
I have no issue implementing these components - I'm using Storybook to organize the independent modules. But I'm struggling with the build process.
If I run npm run build I create a single application, based on the original React application code bootstrapped by create-react-app, which I essentially abandoned in favor of the Storybook setup. If I add the files generated by npm run build my project, I can't get React to render my components properly.
I managed to get a manual build process to work:
In my HTML project I add https://unpkg.com/react#16/umd/react.production.min.js and https://unpkg.com/react-dom#16/umd/react-dom.production.min.js
For each of my React components source files, I run npx babel --presets react-app/prod src/MyComponent.js -o build/mycomponent.js
Then I combine all the npx babel outputs in a single components.js file, adjusting some repeated functions that appear on the top of all files, and suppressing the import and export statements.
I load the component.js file in my HTML project, and I can create my components using plain JS:
ReactDOM.render(
React.createElement(MyComponent, {param: value}, null),
document.getElementById('myComponent')
);
Is there a better process to build my components to a single JS file I could consume in my HTML application?
As you expected, the project should be a reusable module/ UI library (say the name is my-ui) for other projects. I did the similar thing before and just introduce my approach here. First, export the components as normal. Second, create an index.js. Third, import and export those components you exported. Fourth, if you are familiar with webpack, use index.js as the entry in webpack.config.js to bundle the entire project as one file. You can publish this package, or just use it locally.
Then in other projects, import my-ui, you can use any component exported from that module.
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