node.jsreactjsmeteorreact-scriptsmup

MeteorUp volumes and how Meteor can access to their contents


First, thank you for reading my question. This is my first time on stackoverflow and I made a lot of research for answers that could help me.

CONTEXT

I'm developing a Meteor App that is used as a CMS, I create contents and store datas in mongoDb collections. The goal is to use these datas and a React project to build a static website, which is sent to an AWS S3 bucket for hosting purpose.

I'm using meteorUp to deploy my Meteor App (on an AWS EC2 instance) and according to MeteorUp documentation (http://meteor-up.com/docs.html#volumes), I added a docker volume in my mup.js:

module.exports = {
    ...
    meteor: {
      ...
      volumes: {
        '/opt/front': '/front'
      },
      ...
    },
    ...
};

Once deployed, volume is well set in '/opt/myproject/config/start.sh':

sudo docker run \
  -d \
  --restart=always \
  $VOLUME \
   \
  --expose=3000 \
   \
  --hostname="$HOSTNAME-$APPNAME" \
  --env-file=$ENV_FILE \
   \
  --log-opt max-size=100m --log-opt max-file=10  \
  -v /opt/front:/front  \
   --memory-reservation 600M  \
   \
  --name=$APPNAME \
  $IMAGE
echo "Ran abernix/meteord:node-8.4.0-base"

# When using a private docker registry, the cleanup run in 
# Prepare Bundle is only done on one server, so we also
# cleanup here so the other servers don't run out of disk space


if [[ $VOLUME == "" ]]; then
  # The app starts much faster when prepare bundle is enabled,
  # so we do not need to wait as long
  sleep 3s
else
  sleep 15s
fi

On my EC2, '/opt/front' contains the React project used to generate a static website. This folder includes a package.json file, every modules are available in the 'node_modules' directory. 'react-scripts' is one of them, and package.json contains the following script line:

"build": "react-scripts build",

React Project

React App is fed with a JSON file available in 'opt/front/src/assets/datas/publish.json'.

This JSON file can be hand-written (so the project can be developed independently) or generated by my Meteor App.

Meteor App

Client-side, on the User Interface, we have a 'Publish' button that the Administrator can click when she/he wants to generate the static website (using CMS datas) and deploy it to the S3 bucket.

It calls a Meteor method (server-side)

Its action is separated in 3 steps:

1. Collect every useful datas and save them into a Publish collection

2. JSON creation

a. Get Public collection first entry into a javascript object.

b. Write a JSON file using that object in the React Project directory ('opt/front/src/assets/datas/publish.json').

Here's the code:

import fs from 'fs';
    
let publishDatas = Publish.find({}, {sort : { createdAt : -1}}).fetch();

let jsonDatasString = JSON.stringify(publishDatas[0]);

fs.writeFile('/front/src/assets/datas/publish.json', jsonDatasString, 'utf8', function (err) {
    if (err) {
        return console.log(err);
    }
});

2. Static Website build

a. Run a CD command to reach React Project's directory then run the 'build' script using this code:

process_exec_sync = function (command) {
    // Load future from fibers
    var Future = Npm.require("fibers/future");
    // Load exec
    var child = Npm.require("child_process");
    // Create new future
    var future = new Future();
    // Run command synchronous
    child.exec(command, {maxBuffer: 1024 * 10000}, function(error, stdout, stderr) {
        // return an onbject to identify error and success
        var result = {};
        // test for error
        if (error) {
            result.error = error;
        }
        // return stdout
        result.stdout = stdout;
        future.return(result);
    });
    // wait for future
    return future.wait();
}   

var build = process_exec_sync('(cd front && npm run build)');

b. if 'build' is OK, then I send the 'front/build' content to my S3 bucket.

Behaviors:

On local environment (Meteor running on development mode):

FYI: React Project directory's name and location are slightly different. Its located in my meteor project directory, so instead of 'front', it's named '.#front' because I don't want Meteor to restart every time a file is modified, added or deleted.

Everything works well, but I'm fully aware that I'm in development mode and I benefit from my local environment.

On production environment (Meteor running on production mode in a docker container):

Step 2.b : It works well, I can see the new generated file in 'opt/front/src/assets/datas/'

Step 3.a : I get the following error:

"Error running ls: Command failed: (cd /front && npm run build)

(node:39) ExperimentalWarning: The WHATWG Encoding Standard implementation is an experimental API. It should not yet be used in production applications.

npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! front@0.1.0 build: react-scripts build npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the front@0.1.0 build script. npm ERR!

This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR!
/root/.npm/_logs/2021-09-16T13_55_24_043Z-debug.log [exec-fail]"

So here's my question: On production mode, is it possible to use Meteor to reach another directory and run a script from a package.json?

I've been searching for an answer for months, and can't find a similar or nearby case.

Am I doing something wrong?

Am I using a wrong approach?

Am I crazy? :D

Thank you so much to have read until the end.

Thank you for your answers!


!!!!! UPDATE !!!!!

I found the solution!

In fact I had to check few things on my EC2 with ssh:

The reason is that my docker is using Node v8, and my EC2 is using Node v16.

I had to install NVM and use a Node v8, then delete my React-App node_modules (and package-lock.json) then reinstall it.

Once it was done, everything worked perfectly!

I now have a Meteor App acting as a CMS / Preview website hosted on an EC2 instance that can publish a static website on a S3 bucket.

Thank you for reading me!


Solution

  • !!!!! UPDATE !!!!!

    I found the solution!

    In fact I had to check few things on my EC2 with ssh:

    once connected, I had to go to '/opt/front/' and try to build the React-app with 'npm run build' I had a first error because of CHMOD not set to 777 on that directory (noob!) then, I had an error because of node-sass. The reason is that my docker is using Node v8, and my EC2 is using Node v16.

    I had to install NVM and use a Node v8, then delete my React-App node_modules (and package-lock.json) then reinstall it.

    Once it was done, everything worked perfectly!

    I now have a Meteor App acting as a CMS / Preview website hosted on an EC2 instance that can publish a static website on a S3 bucket.

    Thank you for reading me!