Reviving an ancient Meteor.js project in 10 minutes 🦖
Tags: meteor, javascript, maintainability
Published: 2023-10-10 15:04:21

Just a few weeks ago I read this trending article on bun:

{% link https://dev.to/thejaredwilcurt/bun-hype-how-we-learned-nothing-from-yarn-2n3j %}

The author also mentioned my still to date favorite JavaScript ~~framework~~ development platform Meteor.js:

> In 2023 I tried to run my 2014 Meteor project again and the version of the CLI that is compatible with the project doesn't exist any more and the project cannot be ran locally or deployed without completely re-writing the entire project to the latest version of Meteor. All documentation for the 2014 version is just gone.

I asked the author in the comments to provide me a link to the repository, which he generously did:

{% github https://github.com/TheJaredWilcurt/sharibble %}

So I cloned the repo and checked what's actually up with this one.

<small>Photo by <a href="https://unsplash.com/@betagamma?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Daniil Silantev</a> on <a href="https://unsplash.com/photos/EAZYpk6f4ec?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a></small>

## Checking out the project

I cloned the project and at the very first examined the Meteor release used to build the project:

```shell
$ git clone git@github.com:TheJaredWilcurt/sharibble.git
$ cd sharibble
$ cat app/.meteor # 0.8.3
```

So, I found this project to be at release `0.8.3`, which is [from June, 2014](https://github.com/meteor/meteor/tree/release/0.8.3). The latest available documentation are the [release 1.3 docs](https://docs.meteor.com/v1.3/). 
The [related 1.3 release is tagged on GitHub](https://github.com/meteor/meteor/releases/tag/release%2FMETEOR%401.3) from 2016, so there is basically a gap of two years in between this.

EDIT: one of the core maintainers [pointed out](https://forums.meteor.com/t/reviving-an-old-meteor-project/60680/6?u=jkuester), that the binary is also still available and the project is actually runnable on 0.8.3. Furthermore another community member linked a [pre 1.0 documentation](https://learn-meteor.netlify.app/), which they hosted on their own.

## What do we do now?

We could open an issue to revive old docs, since [all the docs are still available](https://github.com/search?q=repo%3Ameteor%2Fdocs+0.8.3&type=commits) and only need to be generated and published again.

However, I wondered how long it would take to make this project run again on Meteor's latest version (as of Today is [release 2.13.3](https://github.com/meteor/meteor/releases/tag/release%2FMETEOR%402.13.3)). I found this to be much simpler than expected and would like to show how it works.

By doing so I'd like to inspire people with older projects to try and check them out again. Furthermore I'd like to emphasize how well this platform has been designed by it's original team at MDG (nowadays running Apollo GraphQL) that it basically runs even 10 years old code without sacrificing modern tools and features.

Here we go.

### Create a new Meteor.js project

The fastest way is to create a new project and copy the existing files into the "new" structure.

For the least barriers we should use [Blaze](https://blazejs.org) using the `--blaze`  option, because it's the original frontend engine that powered nearly all Meteor.js projects before the strategy of making Meteor.js frontend agnostic:

```shell
$ cd sharibble # if not already in the project root
$ meteor create --blaze newapp
```

If you compare the `app` with the `newapp` you will realize the project structure is now slightly different and `newapp/package.json` differs a lot from `package.json`. Back in the days, Meteor.js was not entirely compatible with the broader ecosystem and mostly focused on their own package-environment.

### Include server-side code

First of all, we should be able to run the meteor server again. In order to do that open another terminal and run the `newapp` via `meteor`:

```shell
$ cd newapp
$ meteor
[[[[[ ~/dev/github/sharibble/newapp ]]]]]     

=> Started proxy.                             
=> Started HMR server.                        
=> Started MongoDB.                           
=> Started your app.                          

=> App running at: http://localhost:3000/
```

Now don't cancel the running process but use the other terminal to copy and link the files

```shell
$ cp -Rv app/server/* newapp/server/
```

Now open the main entry point for the server, which is `newapp/server/main.js` and replace the boilerplate with an import of our copied server file:

```js
import './server'
```

The meteor server auto restarts and should report any issues. After a few seconds it actually reported this one:

```js
I20231010-16:14:45.378(2)? Exception in setInterval callback: TypeError: (intermediate value).addSeconds is not a function
I20231010-16:14:45.408(2)?     at server/server.js:130:41
I20231010-16:14:45.409(2)?     at packages/meteor.js:365:18
I20231010-16:14:45.409(2)?     at Meteor.EnvironmentVariable.EVp.withValue (packages/meteor.js:1389:31)
I20231010-16:14:45.409(2)?     at packages/meteor.js:613:25
I20231010-16:14:45.409(2)?     at runWithEnvironment (packages/meteor.js:1486:24)
```

I inspected the code in `server.js` and fortunately this was only due to a missing import. The `Date` class is missing a custom `addSeconds` function. It's actually defined in `app/lib/prototypes.js`, which we therefore copy and link, too:

```shell
$ mkdir -p newapp/lib 
$ cp -v app/lib/prototypes.js newapp/lib
```

Now the error is gone. From here you can refactor things to get rid of extending the prototype of the builtin `Date` object, which is nowadays considered a code-smell but was back then a common concept.

### Copy all client code

Let's try to migrate the client code, so we can finally attempt to run the app:

```shell
$ cp -Rv app/client/* newapp/client # client template files
$ cp -Rv app/public newapp # public folder contains static assets for the client
```

In the main entry point for the clien (at `newapp/client/main.js`) we now need to link the files as we did on the server. Remove the boilerplate and replace it with this code:

```js
import './sharibble.html'
import './client'
import './main.css'
import './scripts/main'
import './scripts/owl.carousel'
```

Finally, open the app on `http://localhost:3000` and open the browser console to detect any issues:

```shell
Uncaught ReferenceError: Session is not defined
```

Add `session` to your `newapp` project via `meteor add session` and reload the browser. A new error arises:

```js
Uncaught TypeError: Meteor.uuid is not a function
```

It comes from the following code in `newapp/client/client.js` at line 5:

```js
Session.set("userGuid", Meteor.uuid())
```

Replace it with the following:

```js
import { Random } from 'meteor/random'
Session.set("userGuid", Random.id())
```

Finally, the browser renders, obviously a chat app.


![sharibble app revived](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwo8mx8rscop56jzgyig.png)

## Get the chat back running

However, when entering any input I get an error on the server:

```shell
Exception from sub userIcon id 6Bt6Txe39ZrFHcRcH ReferenceError: _ is not defined
```

This is easily fixed by importing underscore on the `server.js`, which is available by default. Add to the very top of `server/server.js` the following line:

```js
import { _ } from 'meteor/underscore'
```

Now the chat is restored! It runs again! 🥳

### Get image linking back running

As the banner says, "link images in the chat", I'm all in. However, this also throws an error but this time it's a client-side error. It's easily resolved by also importing the `newapp/lib/prototypes.js` file on the client. Insert before the imports at `newapp/client/main.js` the following line:

```js
import '../lib/prototypes'
```

The image is now linked but not displayed as the database update from the client is prevented (403 error). Back in the days one of Meteor's selling points was to enable clients to send DB updates but it [turned out to be too insecure on it's own](https://guide.meteor.com/security.html#allow-deny).
However, it's still a great feature for prototyping and therefore available via the `insecure` package:

```shell
meteor add insecure
```

By adding this package the images are viewable and the app is fully restored. 🥳🥳🥳



![fully restored app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ih9lkt7nw3a705kbp7re.png)

You can find the result also on my fork of the original repository:

{% github https://github.com/jankapunkt/sharibble %}

## How to go from here

Meteor.js comes with a vast amount of [documentation](https://docs.meteor.com/) and [a comprehensive guide](https://guide.meteor.com/) that covers nearly everything important, ranging from topics for bloody beginners to advanced users, as well as [important security topics](https://guide.meteor.com/security.html).

You may even want to move away from Blaze (😢) and pick on of the many modern frontends, like Vue3, React, Solid, Svelte etc. (see [docs for available options](https://docs.meteor.com/commandline.html#meteorcreate)).

## Summary

The platform Meteor.js and the packages around it have evolved a lot, yet their core functionality remained backwards compatible for nearly 10 years. This is an impressive amount of time, considering the fast pacing and ever changing JavaScript ecosystem in general.

With the upcoming Meteor 3 release there will be one of the first bigger breaking changes that will not be backwards compatible. However, this step was good and necessary to keep up with the rest of the ecosystem. If you have any older applications you [want or need to migrate](https://guide.meteor.com/prepare-meteor-3.0), now is the best time to do it!

---
## About me

I regularly publish articles here on dev.to about **Meteor.js** and **JavaScript**.

You can also find (and contact) me on [GitHub](https://github.com/jankapunkt/), [Twitter](https://twitter.com/kuester_jan) and [LinkedIn](https://www.linkedin.com/in/jan-kuester/).

If you like what you are reading and want to support me, you can [sponsor me on GitHub](https://github.com/jankapunkt) or [send me a tip via PayPal](https://paypal.me/kuesterjan).