Monorepo with Expo and Multiple Entry Points - javascript

I have two Expo (React Native) apps that share most of their code and are already in production. We are trying to move them to a monorepo directory structure as follows:
lerna.json
package.json
packages/
mobile-1/
app.json
index.js
package.json
mobile-2/
app.json
index.js
package.json
mobile-common/
src/
... actual app code ...
index.js
package.json
The way our setup works is that we export a function that starts the app from mobile-common/index.js and mobile-{1,2}/index.js are supposed to call this function with initialization parameters specific to each of them.
The problem with this setup is that mobile-common makes use of react-native and expo dependencies, which are also required by exp to start the React Native packager which causes certain issues at build time. We tried the following:
Adding mobile-common, expo and react-native to the dependencies in mobile-{1,2}/package.json and doing lerna bootstrap. This allows us to run the packager but mobile apps crash while building because they find duplicate dependencies.
We never got yarn workspaces to work, either.
lerna bootstrap --hoist also did not work.
npm link also produced issues at build time with duplicate dependencies.
We really want to move to this kind of structure because our previous structure didn't easily allow us to run both apps side by side, and it is becoming increasingly necessary.
Thanks for helping us out!

If you want to setup expo with a monorepo you can look at my example here.
Currently the expo packages must remain in the root package.json because of limitations with watchman not resolving symlinks properly.

Related

Forking & modifying npm package. Src or Dist? What to do with dist?

I am working on a VueJS web app. One of the modules it uses is a wrapper for a javascript library installed through npm and packaged to integrate into vuejs. It does not quite fit our needs, we need to add some functionality to it, so I want to fork it and edit it.
The repo has two folders: src and dist.
As far as I understand, src is the actual src code while dist is a minified version for distribution. Questions:
If I want to edit it, how do I deal with the contents of /dist ? Do I delete it?
Do components installed through npm use the /src/ version or the /dist/ one?
If I delete /dist, work on the /src code, how do I recreate /dist based on the modified /src files?
Thank you.
Based on your questions, I would suggest you get a bit more familiar into your stack and how to actually build your appication.
Generally speaking the /dist folder contains automatically generated files, which may be uploaded to a webserver of your choice. Since you are using VueJS, you should be able to generate these files by running npm run build.
If I want to edit it, how do I deal with the contents of /dist ? Do I delete it?
As I already mentioned, these files are automatically generated by running npm run build. Therefore everytime you run this command, everything in /dist, will be automatically updated.
Do components installed through npm use the /src/ version or the /dist/ one?
Your working directory is always /src. Dependencies can be used like in any other application (this example uses Axios, which is a http client):
import axios from 'axios';
const httpClient = axios.create({ baseURL: 'https://api.something.com' });
httpClient.get(/* ... */);
If you are a beginner and are not 100% sure about how to use depencencies, I highly encourage you to read this article: An Absolute Beginner's Guide to Using npm
If I delete /dist, work on the /src code, how do I recreate /dist based on the modified /src files?
You do not have to delete anything in /dist. Simply running npm run build automatically will add the latest changes.
Please keep in mind that running npm run build is only relevant for your production environment. For your development environment you always want to use a dev server, which can be started with npm run serve.

How do I bundle JavaScript and CSS dependencies locally for offline use?

Potential similar question here.
I'd like to build a simple in-browser app that can run without an internet connection.
To develop a Python project, this isn't even a question. You just pip install whatever in your favorite virtual env and run offline all day. Your dependency list is also managed for you locally.
While building a toy project with npm, I can't figure out how to do the above. Parcel seems like a good tool to build, bundle, minify, etc. But in the end, all dependencies still point to a CDN. I understand this is default behavior, but there seems no way to easily pull all dependencies local and run offline.
Not a web dev so if I'm asking the wrong question, that sort of insight is appreciated also.
Edit: I've already built all the functionality I need. I can run successfully from file:// or a simple http server. What I'm trying to do in consolidate all the dependencies locally so as to not depend on a CDN at runtime. It'd be better to not go to each CDN/GitHub repo, manually download JS/CSS dependencies, and then manually link to them from my code. That's the point of using a bundler or similar. Is Electron or another framework really the best way to do this? For my use that feels like a lot of overhead.
You can use npm to install and maintain your dependencies. Lets say you are create your project from start. You will need to do the following steps. Assuming you have npm installed.
mkdir my-project //create project directory
cd my-project // cd into project direcotry
npm init // init npm project inside the directory.
After this you can install javascript packages using npm i package-name

How to "hide" ommit Babel/Webpack/Plugins configuration files?

I'm building my very own boilerplate starter kit for React + Redux development and wanted to know if there is a way to hide webpack.config.js and .babelrc files?
For example under the hood the create-react-app also has webpack.config.js and .babelrc files but they are hidden until the npm run eject command. How can I do that in a similar way?
Many thanks in advance!
Yes, Facebook's Create React App does this by adding it as a npm package. You can see the package here: https://github.com/facebook/create-react-app or on NPM here https://www.npmjs.com/package/react-scripts.
Then when you build it runs the build scripts inside of the package. I'd put good thought into forking what they have if you are really going down this path and then pull in their updates in a base branch and play forward your modifications.

Split a javascript Javascript project in multiple package using webpack ou npm

I'm trying to build an application that have to run on Windows(PC), Android and iOS.
For this, I will use Electron (for Windows) and React Native (for mobile plateforms). Both will be built with React and Redux. This way, I will be able to implement the logic in Redux reducers and middlewares and use them in both projects.
From now, I have done a POC for the Electron app using webpack. The reducers are currently directly in the app code. I want to extract the Redux relative code in a seperate package to allow me using it in a the React Native project.
I can make an npm package for my Redux module containing the reducers and the middlwares but this way, when I will compile my application, webpack will not compile my seperate package, it will use the precompiled version.
So What I want is to be able to make a separate package but still compile it at application compile time (because it is still in developpement and the dev is very closely related to main application dev).
Do I have to do it only with npm or with webpack as well ?
I'm pretty new to the Javascript dev stack.
I think you have different ways to handle that problem.
You can use NPM package. But in code of package, you will store not only original source code, but compiled code too. I mean before publish that package, you'll need to compile it in normal ES5 code.
I think you can use submodule system provided by Git. You should have separate repository with common code of your reducers. And in each project (Electron, RN, etc.), you will have a directory with git submodule. Webpack should compile code in that directory normally without any problems.
UPD:
About submodules you can read nice article here: https://git-scm.com/book/en/v2/Git-Tools-Submodules#Starting-with-Submodules
In few words, in project it will looks like:
cd yourProjectFolder
git submodule add https://github.com/TalAter/awesome-service-workers submoduleDirectoryName
It will clone repository to your project, and create .gitmodules file. Code from submodule will not exists in current project repository. In remote repository it will contain only link to submodule, but on your machine, you will have full code and you will be able to compile it.

How do I install Meteor Atmosphere packages locally so I can make modifications to it?

I am trying to get up and running with Meteor and seeing what it can offer, while I like it overall, it seems it's a very very rigid system.
I set up a small testing setup using Velocity, it opens a small overlay window on the side which has a class of "velocityOverlay". The overlay is really small and makes error stack traces wrap. All I wanted to do was to edit the css of the "velocityOverlay" and increase the width.
I somehow (after wasting time) managed to find that Meteor is actually putting all the packages in my user directory by default, once I found that, I found the needed css file...
velocity_html-reporter/.0.5.1.aykpxq++os+web.browser+web.cordova/web.browser/packages/velocity_html-reporter/lib/client-report.less.css
And I did a small edit to the width, next thing you know the meteor app crashes when trying to launch using the "meteor" command throwing a "Error: couldn't read entire resource" error. I can't even edit the bootstrap.css file I installed using "ian_bootstrap-3".
Further more, I can't find any way to install packages locally just for my particular project, what if I wanted to modify a package only for my particular project? this is very easy to do in vanilla Node.js, you simply don't use the "-g" when using "npm install".
To add to that, within my project root, there is another ".meteor/local/build/web.browser" folder with most of the global package files replicated again. When does Meteor use which? This is very confusing.
You can run a package locally very easily.
Download it from Github (for example) and put it in the packages/ directory of your application like this /packages/package_name.
Then add it to your application with the same meteor add package_name command as usual.
Meteor will automatically look in the local folder before anywhere else and compile the package with the rest of your code.
This allows you to do any modification you want on the package and test it locally before publishing it to the registry.
Also, folders located in .meteor/local/* are used for building purpose only and are generated automatically by Meteor. So it is not the best place to edit the files!
This worked for me https://atmospherejs.com/i/publishing. mrt link-package didn't work for me, might just be outdated code.
Steps:
Download (or clone) package from GitHub to local dir
Stop meteor if running
2.1. Make sure you have a packages folder: mkdir packages
Locally link your package:
3.1 If you have mrt installed: Run mrt link-package /path/to/package in a project dir
3.2 If you don't have mrt: ln -s /path/to/package packages/package
Then run meteor add developer:package-name, do not forget to change package name
Run meteor in a project dir
From now any changes in developer:package-name package folder will cause rebuilding of project app
Download the package and place it in new package directory in your project root.
open the package.js inside the downloaded package and remove the author's name in the property "name:"
e.g: - name:'dburles:google-maps' to name:'google-maps'
then run
meteor add google-maps

Categories