Expo Go release channel different versions of app inquiry - javascript

I working on a mobile app that utilizes locations from the api provided by Expo. I need to test different accuracies and that requires publishing different versions of the app.
I want to test accuracy: 6, accuracy: 5, accuracy: 4, accuracy: 1
So far I published a default channel with the accuracy being 6. Do I just change the code that is responsible for the accuracy, save it (not commit and push it to git, just saved it), and then publish it expo publish --release-channel accuracy5?
Am I missing something?
Also, how does one delete a channel published?
https://docs.expo.dev/archive/classic-updates/release-channels/?redirected DOCS I used.
I changed the code, saved it and then published it. I just want to be sure that it did indeed publish with the altered accuracy value.

If you're just trying to test different versions of the app through Expo Go, then different release-channels (therefore QR codes / urls) may be a viable approach.
Regarding testing what you have published, one of the best ways is to utilize expo publish:history that would give you the history of different publishing, it can give you the channel and publicationId that you can then use in expo publish:details --publish-id <THE_PUBLISH_ID>.
Then you can either take a look at the actual published bundle under s3Url, or better just rely on some extra metadata that has been updated with this publish (e.g. you can change a version to smth like 1.0.0-accuracy5). The same way you can just make some dummy visual app change to see the newer version reflected in the new channel.

Related

Routes being cached by service worker in react

We are in the process of building a new website for the company I work for which is written in React using CRA. Browser push notifications and a PWA are both required so a service worker is essential, however I beleive the service worker is responsible for some fairly major caching issues.
The website is not yet in production however I added a new page yesterday (and this has happened a few times before) and once deployed to our dev environment nobody in the office was able to access it - they were simply redirected to the homepage (as if the route didn't exist) until they cleared their cache then the route loaded with no issues.
I've read a little bit on semantic versioning however the articles all seem to use NPM rather than yarn and are versioned locally (which isn't great with a team of 8 working on this project) using npm version patch etc.
We are using MS Azure as the build and release pipeline which I assume would be the best place to set versions if this is required.
My question is what are the steps to aviod this problem and am I on the correct lines thinking versioning will mitigate?
Semantic versioning in this context doesn't make any sense, you've been reading most likely about packages (libraries, frameworks) that are published into NPM for the world to use. In CRA projects, and most other web projects too, versioning of your app happens by the build tools as they name the files based on their contents. The filenames include the hash of the contents and are versioned automatically when contents change, eg. app.iue9234980s.js becomes app.92384oujiuoisdf.js etc.
--
If you're using the default Service Worker setup provided by CRA, then you should look at src/serviceWorker.js. In the comments of that file it says
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
What happens here is that the SW and the build process use Workbox SW library that is configured to use precache policy. In this policy, users get the last version that was previously cached from the browser's cache even if there's a new version available, then in the background SW updates the caches, and on another visit users get the newer version. This of course means that users might always be one version "late".
If this behaviour is not what you want, then you need to change src/serviceWorker.js and probably some configuration somewhere in CRA files. You should google something like "custom service workers with cra" for examples.
To better grasp what is happening – and especially what is correct and intended behaviour in differently configured cases – I really recommend (everyone) to read Google's primer on SWs themselves, here: https://developers.google.com/web/fundamentals/primers/service-workers
With understanding of the SWs basic principles, it is then probably useful to checkout the Workbox library https://developers.google.com/web/tools/workbox to see what it can offer for your app.
Reading and understanding the different aspects of SW is key here – it is excruciatinly easy to shoot yourself in the foot with SWs :)

Delivery mechanism for JavaScript bundle consumed by multiple clients

Scenario:
A shared component implemented as a micro-front-end and hosted on S3...
JS bundle containing the whole app (webpacked) hosted on S3
JS bundle contains hash with the latest commit, e.g. component.{hash}.js
Question:
When we ship a new bundle, what's the best strategy for ensuring the new bundle is consumed by all clients after release, taking into account browser/CDN caching? Important note: we would like client's to get updates immediately (internal).
Examples
On release, generate a component.html file that pulls in the bundle (script tag) based on the latest hash. Ship the new component.html to S3. Clients use <link rel-'import' href='somedomain.com/component.html'> always giving them the latest shipped version.
Issue: The bundle can still take advantage of CD/browser caching, but the HTML file cannot be cached since we need it to be hot for any release. Also seems odd that we have to make two downloads to just get to a single bundle.
Ship as an NPM module that can be consumed at build time by a client.
Issue: If we have 10 clients, all 10 need to build and ship to release with the new component. Assuming package.lock won't cause issues for wildcards (don't know it well enough).
Note: Internal component; may undergo frequent changes, e.g. AB testing, etc.
It's generally important that page/app consuming your component be tested and updated with whatever new version of your component is released. Therefore, your idea of using NPM is a good one. It's generally desirable to have this lag time, so that developers of the pages/apps can verify functionality and also handle any API changes that may have occurred (intentional or otherwise).
For NPM, Semantic Versioning (SemVer) is a defacto standard. The idea is that you number your versions in such a way that bugfixes (no API changes) can be immediately updated in apps. Some developers are okay with installing the latest patch-version of your module. Many prefer to lock to a specific version, and will only release after testing like any other update.
NPM aside, what I've done in the past is use hashed or versioned URLs for the library. I've also kept a latest URL, which redirects to the latest version. For those integrating my library that don't care what version they're on, they'll always get the latest version this way. Additionally, browsers can cache the redirect target and share that cache with other pages that might specify an exact version.
Important note: we would like client's to get updates immediately (internal).
This isn't really all that possible in all cases. In most cases, using proper response headers for caching will solve it. There are edge cases though. For example, what will you do if the user loads a page and then goes offline before your JavaScript loads?
It's always tricky when deploying new pages. Some of your clients will be on old versions, some on new. Maintain backwards compatibility as best as you can, and set your caching headers as appropriate for your circumstances.

write incremental number inside a file with grunt

i'm trying to figure out a way to make grunt write an incremental number or a hash on a file.
i have a file named config.yml which contains this:
version: 0.0.0
every time i change some files that i can specify somewhere (say all the .js and .css files), grunt should increment that number in some way.
i've seen some cache busting plugin but it's not what i am looking for as i don't want to have something like config.987234892374982.yml or config.yml?v=1.0.0 for example. i'm looking for a way to have grunt to find that number in that file, change it in a way that makes sense (incrementally ideally, or a random hash) and then save the file.
can you help in some way? thanks a lot!
I would seriously recommend against automatic version bumping for anything beyond the build number.
A version number is more than just an indication of how many times your product has been built. In essence, a version number is a semantic promise to your end user concerning compatibility with earlier releases. Node.js and npm and other systems using versioning are built around the core concept that X.Y.Z version numbers contain the following logic:
Software that doesn't have the same X version will have severely breaking changes that require those upgrading (or downgrading) to completely redesign the logic of how they use the software, and in some cases they even have to find alternatives because what they're doing right now doesn't work anymore.
Software within the same X version can relatively easily be swapped out without having to make sweeping changes to your own site or product.
Software within the same Y version can be swapped out without having to change any code, because it's supposed to be only bug fixes and security fixes. Only code that works around the things fixed needs to be changed.
Software within the same Z version has the exact same source, so if you have 2 copies of the same Z.Y.Z version, they can be used interchangeably.
This is the core contract that NPM and other package managers ask all their content providers to adhere to. In fact, it has already been shown that in some cases where content providers don't adhere to this versioning system, consumers of this content who assume semantic versioning apply have found their build to fail. Many consumers assume that if version 3.5.N works, that any version within the 3.5.X family will be interchangeable, and make use of that assumption by automatically building their code with the most recent version of the 3.5.X family.
Because of this, it's not a good idea to automatically bump versions beyond the build number. Bumping the patch version should only be done when you actually release a new version to the public, not after every build. Bumping the minor version should only be done when you have added new features to the product, but without the need for major changes to software that uses your product. Bumping the major version should only be done when you make drastic and destructive changes to your API, like moving and/or removing functions, function parameters, objects or attributes.

Can I build my meteor app to work with several different sets of packages using different mobile exports?

I am working on a fairly large webapp in Meteor. As advised my many experts, a good way to go for large apps is to split the different parts of the code in separate packages, like, e.g. Telescope. I designed everything with this objective in mind so I expect to be able to port everything to a package based "architecture".
Moreover, I plan to open source soon, so it should be also easier to maintain that way.
I have different types of users. Depending on it, I would like to build the app differently:
One type of user is using the browser based version of the app. This user will get everything since I don't know how to selectively send some parts of the UI/client code (and I assume I can not)
One type of mobile user will only have a subset of packages.
Another type of mobile user will have another subset of packages.
So I have a browser full version (delivered by server) and two mobile app versions.
My understanding of mobile app exports is that I can compile different versions of my client code by removing/adding some specific packages before compiling, since a mobile app from meteor is a packaged version of all client side related code in an app.
Is that correct? Am I overlooking something?
I have been looking into this for a couple of days and things are changing in the Meteor world with the upcoming v1.3.
Regarding my question, yes, it could have been a way to go after meteor v1 if I believe this article
However, one of Meteor dev "announced" that Meteor will eventually drop the package system in favour of npm. One of the good things is that npm allows lazy (i.e. conditionnal & role based) loading of the different npm assets.
I will then look into this possibility. The one thing I miss would be an article or a tutorial showing what are the best practices when splitting a meteor app into npm packages. I assume that some, if not most of the advises for package based architecture are still standing.

Meteor "--mobile-settings" being overriden by server values?

I'm trying to provide some per-build configuration for a Meteor mobile app. The --mobile-settings option looked to be ideal for this task - it allows you to pass configuration (JSON) to mobile clients at build time - in the same way that the --settings option does for the server.
However, I'm seeing some unexpected behaviour... anything passed to the mobile clients via --mobile-settings looks to be being overridden when the client refreshes from the server.
Here's what I did....
Wrote a very simple app which reads a settings value from Meteor.settings.public.blah and displays it on-screen.
Deployed this app to the meteor servers (without any mobile-settings file).
Built the same app for android, pointing to the server above and with the --mobile-settings option set - pointing to a settings file which declared the 'blah' property. Installed it on a device.
When I ran the app on the device, the app started and the screen correctly displayed the blah setting.
However, after a couple of seconds the app refreshed and the setting disappeared.
On refresh, why would a mobile-specific, build-time value be overridden from the server? Does the mobile-settings file need to exist on the server too?
Thanks in advance.
Update
Ok, going by a discussion below, I think I need to clarify my question a little...
What I've described above is the behaviour I'm seeing. However, I find this behaviour confusing and I'm struggling to find any documentation on this feature to detail what the expected behaviour is.
The best I could find was a thread where one of the original devs commented (https://groups.google.com/forum/#!msg/meteor-talk/Jbfnk5kCvW4/6qvccun2dQ0J). He said...
You just build your mobile apps twice with different json passed to --mobile-settings.
This does not seem to support the behaviour I'm seeing - where the json passed to --mobile-settings would be overwritten by whatever was deployed to the server. Hence my confusion.
I would appreciate it if anyone could point me to any documentation or confirm this behaviour either way.
In short
Let's look at
meteor build --help
It reads:
--mobile-settings Set optional data for the initial value of Meteor.settings
in your mobile application. A new value for
Meteor.settings can be set later by the server as part of
hot code push.
So it looks like the settings you provide for the server with the METEOR_SETTINGS environment variable always takes precedence. The "mobile settings" are only there as a fallback/defaults values if there are no server setting yet.
Let's look at Meteor source code :)
Still, it may not be clear what's the purpose of having another settings object for a mobile device. I am not an expert on Cordova, but I guess the problem here is how the application gets bootstrapped.
Normally, when you request the initial page from meteor server the Meteor.settings object is - of course - up-to-date with your server config. This is taken care of by the webapp package here:
https://github.com/meteor/meteor/blob/devel/packages/webapp/webapp_server.js#L352
Note that it becomes a bit more complicated when you install the application on your mobile device. Of course the installation process has nothing to do with your server current state, hence there's no way to get the initial values for settings unless they're know in advance during the mobile build process. That's the only reason you need that --mobile-settings option. They're not there to alter your settings for a mobile device but to provide initial values before the up-to-date settings object can be loaded from your server during the hot-code-push.
And it will always happen if the two settings objects are different, because as you can see in the code here the PUBLIC_SETTINGS value is taken into account while computing the hash which is used to tell if the the client code is up-to-date.
Conclusion
So the conclusion is: your "mobile settings" - or at least the public part of it - should reflect the current server configuration as close as possible. Every time you change your public settings you should also rebuild your mobile application and publish the update to make sure your new customers have the up-to-date version of settings out-of-the-box.
Ideally, the client application should not depend on Meteor.settings to startup properly. Even if the object is empty there should be some default behavior that does not break the user experience.

Categories