0

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:

  • 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!

  • `docker run`, `npm run` .. what is all this? If you are user meteor-up then you shouldn't have to do any of that, and if you are sure you need it then I would strongly suggest you avoid using meteor-up and just use the official `meteor build` mechanism and deploy manually. Have you already tried that? – Christian Fritz Sep 16 '21 at 15:35
  • @ChristianFritz thank you for the answer! `docker run` line features in config/start.sh which is generated by meteor-up. I guess it's setting the docker with options I set in my mup.js (like 'volumes'). I need to define it because the React App I use to generate the static website is located outside the Meteor build (and outside the docker that runs my Meteor App). `npm run` is a command line called by my Meteor App through my `process_exec_sync`function. The idea is to use NodeJs to change directory to where my React App is, and run its `build` script. – LoneWolfLow Sep 17 '21 at 09:48
  • And I'm not familiar with how to setup Dockers and NGINX, it would take me eon to deploy it manually and make it work. That's the reason why I use meteor-up – LoneWolfLow Sep 17 '21 at 09:53
  • Is there a reason to have two apps rather than one? Sounds like your life would be much easier if you merged the react app into meteor, which could be trivial. – Christian Fritz Sep 17 '21 at 15:05
  • The reason is that I need to host the built version of my React App (which is fed by a JSON created by my Meteor App) on a S3 bucket. My Meteor App is a backoffice hosted on a EC2. – LoneWolfLow Sep 20 '21 at 08:52
  • Unless there's a way to render a specific part of routes as a static website, I can't merge it into my Meteor App – LoneWolfLow Sep 20 '21 at 08:55
  • yes, that's possible. Look for SSR (server side rendering) in Meteor + React. – Christian Fritz Sep 20 '21 at 15:52
  • Thank you! I looked at SSR but it wasn't what I was looking for (the endpoint is SSG). But I found my error (I updated my first post) and everything works perfectly now! – LoneWolfLow Sep 24 '21 at 08:10
  • great! perhaps post your update as an answer so that the question doesn't look unresolved or close the question. – Christian Fritz Sep 24 '21 at 14:43

1 Answers1

0

!!!!! 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!